diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 82b1903c0..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: CI - -on: - pull_request: - push: - branches: - - main - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ci-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - public-quality: - name: Sanitized public quality gates - runs-on: ubuntu-latest - # The full workspace suites take about 25 minutes (review F15). - timeout-minutes: 75 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version-file: .nvmrc - cache: npm - - - name: Verify export provenance - run: node scripts/verify-export-provenance.mjs . - - - name: Create sanitized candidate - run: >- - node scripts/public-export.mjs - --output "$RUNNER_TEMP/spaceapp-public-export" - - - name: Install candidate dependencies - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm ci - - - name: Install ripgrep (the file search tests run the real rg) - run: sudo apt-get update -qq && sudo apt-get install -y -qq ripgrep - - - name: Public release tests - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm run test:public - - - name: Typecheck candidate - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm run check - - - name: Build candidate - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm run build - - - name: Pack launcher candidate - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm run pack:dry-run -w run-spaceapp diff --git a/.github/workflows/containers.yml b/.github/workflows/containers.yml deleted file mode 100644 index 97d278576..000000000 --- a/.github/workflows/containers.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: Container matrix - -on: - pull_request: - paths: - - "apps/**" - - "packages/**" - - "!packages/run-spaceapp/**" - - "deploy/docker/**" - - "starter-memory/**" - - "Dockerfile" - - "package-lock.json" - push: - branches: - - main - paths: - - "apps/**" - - "packages/**" - - "!packages/run-spaceapp/**" - - "deploy/docker/**" - - "starter-memory/**" - - "Dockerfile" - - "package-lock.json" - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: containers-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - name: ${{ matrix.target }} / linux-${{ matrix.arch }} - strategy: - fail-fast: false - matrix: - target: - - core - - browser - - cli - arch: - - amd64 - - arm64 - runs-on: ubuntu-latest - timeout-minutes: 50 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 - with: - context: . - target: ${{ matrix.target }} - platforms: linux/${{ matrix.arch }} - push: false - load: true - tags: spaceapp-ci:${{ matrix.target }}-${{ matrix.arch }} - provenance: false - cache-from: type=gha,scope=${{ matrix.target }}-${{ matrix.arch }} - cache-to: type=gha,mode=max,scope=${{ matrix.target }}-${{ matrix.arch }} - - - name: Enforce container size budget - run: >- - node scripts/container-image-size-budget.mjs - --target "${{ matrix.target }}" - --image "spaceapp-ci:${{ matrix.target }}-${{ matrix.arch }}" diff --git a/.github/workflows/platform-matrix.yml b/.github/workflows/platform-matrix.yml deleted file mode 100644 index e09ecb53c..000000000 --- a/.github/workflows/platform-matrix.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Platform matrix - -on: - pull_request: - paths: - - "packages/run-spaceapp/**" - - "package-lock.json" - - ".github/workflows/platform-matrix.yml" - push: - branches: - - main - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: platform-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - launcher: - name: Launcher / ${{ matrix.os }} / Node ${{ matrix.node }} - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - node: "22.23.0" - - os: macos-latest - node: "22.23.0" - - os: windows-latest - node: "22.23.0" - - os: windows-latest - node: "24" - runs-on: ${{ matrix.os }} - timeout-minutes: 20 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: ${{ matrix.node }} - cache: npm - - - name: Install workspace dependencies on supported hosts - if: runner.arch != 'ARM64' - run: npm ci - - - name: Install source workspace for the intentional x64 package rejection test - if: runner.arch == 'ARM64' - run: npm ci --force - - - run: npm test -w run-spaceapp - - run: npm run check -w run-spaceapp - - run: npm run pack:dry-run -w run-spaceapp - - run: node packages/run-spaceapp/bin/spaceapp.mjs --version diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 4bfdd49ba..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,721 +0,0 @@ -name: Public OIDC release - -on: - workflow_dispatch: - inputs: - version: - description: Exact semantic version from packages/run-spaceapp/package.json - required: true - type: string - runtime_version: - description: Exact existing or newly built SpaceApp runtime image version - required: true - type: string - browser_source_version: - description: Existing browser image version reused by an amd64 core and CLI release - required: false - type: string - release_mode: - description: Select full, launcher-only, or x64 core and CLI publication - required: true - default: full - type: choice - options: - - full - - launcher-only - - amd64-core-cli - npm_tag: - description: npm prerelease channel - required: true - default: next - type: choice - options: - - next - - personal - -permissions: - contents: read - -concurrency: - group: public-oidc-release-${{ inputs.version }}-${{ inputs.runtime_version }}-${{ inputs.release_mode }}-${{ inputs.npm_tag }} - cancel-in-progress: false - -jobs: - release-policy: - name: Enforce main and exact release version - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Reject non-main dispatches - if: github.ref != 'refs/heads/main' - run: exit 1 - - - name: Confirm main dispatch - if: github.ref == 'refs/heads/main' - run: echo "Release source is main." - - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version-file: .nvmrc - cache: npm - - - name: Require exact-candidate cross-platform installation evidence - run: node scripts/release-evidence.mjs - - - name: Enforce legal, version, and npm channel readiness - env: - RELEASE_VERSION: ${{ inputs.version }} - RELEASE_RUNTIME_VERSION: ${{ inputs.runtime_version }} - RELEASE_BROWSER_SOURCE_VERSION: ${{ inputs.browser_source_version }} - RELEASE_MODE: ${{ inputs.release_mode }} - RELEASE_DIST_TAG: ${{ inputs.npm_tag }} - run: >- - node scripts/public-release-readiness.mjs - --version "$RELEASE_VERSION" - --npm-tag "$RELEASE_DIST_TAG" - --release-mode "$RELEASE_MODE" - --runtime-version "$RELEASE_RUNTIME_VERSION" - --browser-source-version "$RELEASE_BROWSER_SOURCE_VERSION" - - source-candidate: - name: Verify sanitized source and npm candidate - needs: release-policy - runs-on: ubuntu-latest - # The full workspace suites take about 25 minutes (review F15). - timeout-minutes: 90 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version-file: .nvmrc - cache: npm - - - name: Create sanitized source candidate - run: >- - node scripts/public-export.mjs - --output "$RUNNER_TEMP/spaceapp-public-export" - - - name: Archive immutable sanitized source - run: | - mkdir -p "$RUNNER_TEMP/release-artifacts" - tar -C "$RUNNER_TEMP" \ - -czf "$RUNNER_TEMP/release-artifacts/spaceapp-public-export-${{ inputs.version }}.tar.gz" \ - spaceapp-public-export - - - name: Install candidate dependencies - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm ci - - - name: Audit candidate dependencies - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm audit --audit-level=high - - - name: Install ripgrep (the file search tests run the real rg) - run: sudo apt-get update -qq && sudo apt-get install -y -qq ripgrep - - - name: Test candidate - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm run test:public - - - name: Typecheck candidate - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm run check - - - name: Build candidate - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm run build - - - name: Pack dry run - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm run pack:dry-run -w run-spaceapp - - - name: Block fixable source vulnerabilities - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - scan-type: fs - scan-ref: ${{ runner.temp }}/spaceapp-public-export - format: table - severity: MEDIUM,HIGH,CRITICAL - ignore-unfixed: true - exit-code: "1" - - - name: Stamp the reviewed public git head - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: npm pkg set "gitHead=${{ github.sha }}" -w run-spaceapp - - - name: Pack npm candidate from sanitized source - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: >- - npm pack ./packages/run-spaceapp - --pack-destination "$RUNNER_TEMP/release-artifacts" - - - name: Record npm candidate checksum - working-directory: ${{ runner.temp }}/release-artifacts - run: >- - sha256sum "run-spaceapp-${{ inputs.version }}.tgz" - > "run-spaceapp-${{ inputs.version }}.tgz.sha256" - - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: public-release-source-candidate-${{ inputs.version }} - path: ${{ runner.temp }}/release-artifacts/ - if-no-files-found: error - - container-candidate: - name: Sanitized ${{ matrix.target }} / linux-${{ matrix.arch }} - needs: release-policy - if: inputs.release_mode == 'full' - strategy: - fail-fast: false - matrix: - target: - - core - - browser - - cli - arch: - - amd64 - - arm64 - runs-on: ubuntu-latest - timeout-minutes: 65 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Create sanitized container context - run: >- - node scripts/public-export.mjs - --output "$RUNNER_TEMP/spaceapp-public-export" - - - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 - with: - context: ${{ runner.temp }}/spaceapp-public-export - target: ${{ matrix.target }} - platforms: linux/${{ matrix.arch }} - push: false - load: true - tags: spaceapp-ci:${{ matrix.target }}-${{ matrix.arch }} - provenance: false - cache-from: type=gha,scope=candidate-${{ matrix.target }}-${{ matrix.arch }} - cache-to: type=gha,mode=max,scope=candidate-${{ matrix.target }}-${{ matrix.arch }} - - - name: Enforce container size budget - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: >- - node scripts/container-image-size-budget.mjs - --target "${{ matrix.target }}" - --image "spaceapp-ci:${{ matrix.target }}-${{ matrix.arch }}" - - - name: Block fixable container vulnerabilities - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - image-ref: spaceapp-ci:${{ matrix.target }}-${{ matrix.arch }} - format: table - severity: MEDIUM,HIGH,CRITICAL - ignore-unfixed: true - exit-code: "1" - - - name: Capture full candidate image report - if: always() - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - image-ref: spaceapp-ci:${{ matrix.target }}-${{ matrix.arch }} - format: json - output: trivy-full-${{ matrix.target }}-${{ matrix.arch }}.json - severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL - ignore-unfixed: false - exit-code: "0" - - - name: Summarize full candidate image report - if: always() && hashFiles(format('trivy-full-{0}-{1}.json', matrix.target, matrix.arch)) != '' - run: >- - node scripts/trivy-report-summary.mjs - --input "trivy-full-${{ matrix.target }}-${{ matrix.arch }}.json" - --label "${{ matrix.target }} / linux-${{ matrix.arch }}" - >> "$GITHUB_STEP_SUMMARY" - - - name: Upload full candidate image report - if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: trivy-full-${{ matrix.target }}-${{ matrix.arch }} - path: trivy-full-${{ matrix.target }}-${{ matrix.arch }}.json - if-no-files-found: error - - amd64-container-candidate: - name: Sanitized ${{ matrix.target }} / linux-amd64 - needs: release-policy - if: inputs.release_mode == 'amd64-core-cli' - strategy: - fail-fast: false - matrix: - target: - - core - - cli - runs-on: ubuntu-latest - timeout-minutes: 65 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Create sanitized container context - run: >- - node scripts/public-export.mjs - --output "$RUNNER_TEMP/spaceapp-public-export" - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 - with: - context: ${{ runner.temp }}/spaceapp-public-export - target: ${{ matrix.target }} - platforms: linux/amd64 - push: false - load: true - tags: spaceapp-ci:${{ matrix.target }}-amd64 - provenance: false - cache-from: type=gha,scope=candidate-${{ matrix.target }}-amd64 - cache-to: type=gha,mode=max,scope=candidate-${{ matrix.target }}-amd64 - - - name: Enforce container size budget - working-directory: ${{ runner.temp }}/spaceapp-public-export - run: >- - node scripts/container-image-size-budget.mjs - --target "${{ matrix.target }}" - --image "spaceapp-ci:${{ matrix.target }}-amd64" - - - name: Block fixable container vulnerabilities - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - image-ref: spaceapp-ci:${{ matrix.target }}-amd64 - format: table - severity: MEDIUM,HIGH,CRITICAL - ignore-unfixed: true - exit-code: "1" - - - name: Capture full candidate image report - if: always() - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - image-ref: spaceapp-ci:${{ matrix.target }}-amd64 - format: json - output: trivy-full-${{ matrix.target }}-amd64.json - severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL - ignore-unfixed: false - exit-code: "0" - - - name: Summarize full candidate image report - if: always() && hashFiles(format('trivy-full-{0}-amd64.json', matrix.target)) != '' - run: >- - node scripts/trivy-report-summary.mjs - --input "trivy-full-${{ matrix.target }}-amd64.json" - --label "${{ matrix.target }} / linux-amd64" - >> "$GITHUB_STEP_SUMMARY" - - - name: Upload full candidate image report - if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: trivy-full-${{ matrix.target }}-amd64 - path: trivy-full-${{ matrix.target }}-amd64.json - if-no-files-found: error - - existing-runtime: - name: Verify existing runtime manifests and attestations - needs: release-policy - if: inputs.release_mode == 'launcher-only' - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: read - packages: read - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - name: Verify existing architectures, SBOMs, and provenance - run: >- - node scripts/verify-published-containers.mjs - --version "${{ inputs.runtime_version }}" - - existing-browser: - name: Verify the reused browser manifest and attestations - needs: release-policy - if: inputs.release_mode == 'amd64-core-cli' - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: read - packages: read - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - name: Verify the reusable browser architectures, SBOMs, and provenance - run: >- - node scripts/verify-published-containers.mjs - --version "${{ inputs.browser_source_version }}" - --targets browser - --architectures amd64,arm64 - - publish-preflight: - name: Approve and prove release tags are new - needs: - - source-candidate - - container-candidate - - amd64-container-candidate - - existing-runtime - - existing-browser - if: >- - always() && - needs.source-candidate.result == 'success' && - ( - ( - inputs.release_mode == 'full' && - needs.container-candidate.result == 'success' && - needs.amd64-container-candidate.result == 'skipped' && - needs.existing-runtime.result == 'skipped' && - needs.existing-browser.result == 'skipped' - ) || - ( - inputs.release_mode == 'launcher-only' && - needs.container-candidate.result == 'skipped' && - needs.amd64-container-candidate.result == 'skipped' && - needs.existing-runtime.result == 'success' && - needs.existing-browser.result == 'skipped' - ) || - ( - inputs.release_mode == 'amd64-core-cli' && - needs.container-candidate.result == 'skipped' && - needs.amd64-container-candidate.result == 'success' && - needs.existing-runtime.result == 'skipped' && - needs.existing-browser.result == 'success' - ) - ) - runs-on: ubuntu-latest - timeout-minutes: 15 - environment: npm - permissions: - contents: read - packages: read - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - if: inputs.release_mode != 'launcher-only' - - - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - if: inputs.release_mode != 'launcher-only' - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Fail closed if any exact artifact already exists - run: >- - node scripts/release-artifact-preflight.mjs - --version "${{ inputs.version }}" - --release-mode "${{ inputs.release_mode }}" - - publish-containers: - name: Publish ${{ matrix.target }} multi-arch image - needs: publish-preflight - if: >- - always() && - needs.publish-preflight.result == 'success' && - inputs.release_mode == 'full' - strategy: - fail-fast: false - matrix: - target: - - core - - browser - - cli - runs-on: ubuntu-latest - timeout-minutes: 75 - environment: npm - permissions: - contents: read - packages: write - id-token: write - steps: - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - name: public-release-source-candidate-${{ inputs.version }} - path: ${{ runner.temp }}/release-artifacts - - - name: Restore verified sanitized source - run: | - mkdir -p "$RUNNER_TEMP/publish-context" - tar -C "$RUNNER_TEMP/publish-context" \ - -xzf "$RUNNER_TEMP/release-artifacts/spaceapp-public-export-${{ inputs.version }}.tar.gz" - - - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish immutable exact-version image - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 - with: - context: ${{ runner.temp }}/publish-context/spaceapp-public-export - target: ${{ matrix.target }} - platforms: linux/amd64,linux/arm64 - push: true - tags: ghcr.io/oll4com/spaceapp-${{ matrix.target }}:${{ inputs.version }} - sbom: true - provenance: mode=max,version=v1 - cache-from: type=gha,scope=publish-${{ matrix.target }} - cache-to: type=gha,mode=max,scope=publish-${{ matrix.target }} - - publish-amd64-containers: - name: Publish ${{ matrix.target }} linux-amd64 image - needs: publish-preflight - if: >- - always() && - needs.publish-preflight.result == 'success' && - inputs.release_mode == 'amd64-core-cli' - strategy: - fail-fast: false - matrix: - target: - - core - - cli - runs-on: ubuntu-latest - timeout-minutes: 75 - environment: npm - permissions: - contents: read - packages: write - id-token: write - steps: - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - name: public-release-source-candidate-${{ inputs.version }} - path: ${{ runner.temp }}/release-artifacts - - - name: Restore verified sanitized source - run: | - mkdir -p "$RUNNER_TEMP/publish-context" - tar -C "$RUNNER_TEMP/publish-context" \ - -xzf "$RUNNER_TEMP/release-artifacts/spaceapp-public-export-${{ inputs.version }}.tar.gz" - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish immutable exact-version amd64 image - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 - with: - context: ${{ runner.temp }}/publish-context/spaceapp-public-export - target: ${{ matrix.target }} - platforms: linux/amd64 - push: true - tags: ghcr.io/oll4com/spaceapp-${{ matrix.target }}:${{ inputs.version }} - sbom: true - provenance: mode=max,version=v1 - cache-from: type=gha,scope=candidate-${{ matrix.target }}-amd64 - cache-to: type=gha,mode=max,scope=publish-${{ matrix.target }}-amd64 - - reuse-browser-manifest: - name: Reuse the existing signed browser manifest - needs: publish-preflight - if: >- - always() && - needs.publish-preflight.result == 'success' && - inputs.release_mode == 'amd64-core-cli' - runs-on: ubuntu-latest - timeout-minutes: 15 - environment: npm - permissions: - contents: read - packages: write - steps: - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Copy the immutable browser manifest without rebuilding it - run: >- - docker buildx imagetools create - --tag "ghcr.io/oll4com/spaceapp-browser:${{ inputs.version }}" - "ghcr.io/oll4com/spaceapp-browser:${{ inputs.browser_source_version }}" - - verify-containers: - name: Verify published manifests and attestations - needs: publish-containers - if: >- - always() && - needs.publish-containers.result == 'success' && - inputs.release_mode == 'full' - runs-on: ubuntu-latest - timeout-minutes: 15 - environment: npm - permissions: - contents: read - packages: read - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Verify architectures, SBOMs, and provenance - run: >- - node scripts/verify-published-containers.mjs - --version "${{ inputs.version }}" - - verify-amd64-containers: - name: Verify published amd64 manifests and attestations - needs: - - publish-amd64-containers - - reuse-browser-manifest - if: >- - always() && - needs.publish-amd64-containers.result == 'success' && - needs.reuse-browser-manifest.result == 'success' && - inputs.release_mode == 'amd64-core-cli' - runs-on: ubuntu-latest - timeout-minutes: 15 - environment: npm - permissions: - contents: read - packages: read - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Verify amd64 SBOMs and provenance for every runtime service - run: >- - node scripts/verify-published-containers.mjs - --version "${{ inputs.version }}" - --targets core,cli,browser - --architectures amd64 - - publish-npm: - name: Publish run-spaceapp with npm OIDC - needs: - - publish-preflight - - publish-containers - - verify-containers - - publish-amd64-containers - - reuse-browser-manifest - - verify-amd64-containers - - existing-runtime - - existing-browser - if: >- - always() && - needs.publish-preflight.result == 'success' && - ( - ( - inputs.release_mode == 'full' && - needs.publish-containers.result == 'success' && - needs.verify-containers.result == 'success' && - needs.publish-amd64-containers.result == 'skipped' && - needs.reuse-browser-manifest.result == 'skipped' && - needs.verify-amd64-containers.result == 'skipped' && - needs.existing-runtime.result == 'skipped' && - needs.existing-browser.result == 'skipped' - ) || - ( - inputs.release_mode == 'launcher-only' && - needs.publish-containers.result == 'skipped' && - needs.verify-containers.result == 'skipped' && - needs.publish-amd64-containers.result == 'skipped' && - needs.reuse-browser-manifest.result == 'skipped' && - needs.verify-amd64-containers.result == 'skipped' && - needs.existing-runtime.result == 'success' && - needs.existing-browser.result == 'skipped' - ) || - ( - inputs.release_mode == 'amd64-core-cli' && - needs.publish-containers.result == 'skipped' && - needs.verify-containers.result == 'skipped' && - needs.publish-amd64-containers.result == 'success' && - needs.reuse-browser-manifest.result == 'success' && - needs.verify-amd64-containers.result == 'success' && - needs.existing-runtime.result == 'skipped' && - needs.existing-browser.result == 'success' - ) - ) - runs-on: ubuntu-latest - timeout-minutes: 15 - environment: npm - permissions: - contents: read - packages: write - id-token: write - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: 22.23.0 - - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - name: public-release-source-candidate-${{ inputs.version }} - path: ${{ runner.temp }}/release-artifacts - - - name: Verify npm candidate checksum - working-directory: ${{ runner.temp }}/release-artifacts - run: sha256sum --check "run-spaceapp-${{ inputs.version }}.tgz.sha256" - - - name: Install trusted-publishing npm CLI - run: npm install --global --ignore-scripts --no-audit --no-fund npm@11.18.0 - - - name: Publish or verify the exact npm candidate - env: - RELEASE_VERSION: ${{ inputs.version }} - RELEASE_DIST_TAG: ${{ inputs.npm_tag }} - RELEASE_GIT_HEAD: ${{ github.sha }} - run: node scripts/publish-npm-candidate.mjs "$RUNNER_TEMP/release-artifacts/run-spaceapp-${{ inputs.version }}.tgz" diff --git a/.github/workflows/reviewed-spaceapp84.yml b/.github/workflows/reviewed-spaceapp84.yml new file mode 100644 index 000000000..101fcacfb --- /dev/null +++ b/.github/workflows/reviewed-spaceapp84.yml @@ -0,0 +1,167 @@ +name: Reviewed SpaceApp candidate 85 + +on: + pull_request: + branches: [main] + +permissions: + contents: read + +env: + TZ: UTC + ELECTRON_SKIP_BINARY_DOWNLOAD: '1' + SPACE_TEMPORAL_RECORD_HISTORIES: '0' + +jobs: + temporal-exact-candidate: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout the exact reviewed candidate + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + repository: 3Nerion7/spaceapp + ref: 693c1cd28ef3a4e7efbcb1ea2935b49b84e4bd5c + persist-credentials: false + - name: Verify commit, tree and changed-file bytes + shell: bash + run: | + set -euo pipefail + test "$(git rev-parse HEAD)" = 693c1cd28ef3a4e7efbcb1ea2935b49b84e4bd5c + test "$(git rev-parse 'HEAD^{tree}')" = a87458347631ce11c657a419a804994aa6feded9 + test -z "$(git status --porcelain)" + cat > "$RUNNER_TEMP/reviewed84.sha256" <<'SOURCE_SHA256' + 7856a0f53b3a476f0ec93d7cc4da1fcca7e850775b2e5d118c7a8ce3f7e7ab8a .github/workflows/temporal-replay.yml + b3f8aa0bec46e639a5d8a46c56dd280e1740b228393778a7dadec1906be9141f apps/api/tests/room-watchdog.test.ts + 272ac7433bf89dc3c4d680bc77b412498743208a4684573c090935bdaeef90e9 apps/api/tests/space-control-capture.test.ts + f4a57c9e02339bb68fc8b8bd0082a0931a74e808edcbedec574664fe537b29a3 apps/worker/package.json + 103eab80f8d9a96d8954d7b01a3566e2cbde9ca6222b80d53ca8df19e0a64c1c apps/worker/tests/fixtures/workflow-histories/README.md + 669f8f2a37378b6edfad77c41f0370da2ed896803d0977c7c0ff4b3c4c66f4ba apps/worker/tests/fixtures/workflow-histories/codex-turn-retry.json + bd877a561855620e167744e215467e20409e71e1a1a9b2b14aa406e4cb16b26e apps/worker/tests/fixtures/workflow-histories/dot-goal-wake.json + b77d3a1389e87f097de6b4d30ed91f60f94030c34c285bf66fbd7aa57dfe191d apps/worker/tests/fixtures/workflow-histories/dummy-turn-retry.json + 75988e4a90837703e5963510ef8cbb9074690ae1f181d72c3b02e7cdb1109241 apps/worker/tests/fixtures/workflow-histories/memory-consolidation-change.json + 608162c52fb0e65dffa00a03518fb179ebd1fc5047b4effd1a58a95d417a681f apps/worker/tests/fixtures/workflow-histories/memory-maintenance-child.json + e9ac8828e6029e8b06663bd7b6bb2d9f7ea0311e653b504c067bc2ba492bbfc8 apps/worker/tests/fixtures/workflow-histories/memory-mutation-retry.json + 19f4cd5a21eb2d813e0289487789d8ce02ed08b8a76ee5f0881fe1a836ef0898 apps/worker/tests/fixtures/workflow-histories/room-action-failure.json + 71dfa94639d310a30d68a68d798bb20dfada1e838567e588e2c7e5bafb574025 apps/worker/tests/fixtures/workflow-histories/supervisor-current-continuation.json + 90c108f3200ed93f2359c93abb0d38d34fcf31a215a096d72e1314255339bb13 apps/worker/tests/fixtures/workflow-histories/supervisor-legacy-continuation.json + 6dbe7ac489e02ff5ac94b0628427cfbc379ec6e5d8f1d12dad379be85152bd58 apps/worker/tests/record-temporal-histories.mjs + c4a24b9b640bd1673f470aca328b2826c595d4a253716c0b4915a7a596139922 apps/worker/tests/room-continuation-fixture.ts + 741dc87d4932d0aeae3655b31eb275f48c8b9045f9db2d386186a68e8557c8af apps/worker/tests/support/temporal-nondeterministic-workflows.ts + c473e29712c23645722c52dece5f022e046ff1c3b990738482e73198b6ddf558 apps/worker/tests/support/temporal-real-workflows.ts + ffab1350234dd04287dfadcc3016e66de31d3e297302dd4d538a34db68d935f1 apps/worker/tests/temporal-workflows.test.ts + e8c7d03fba172eef25c8b880556fabd77bafd67de3178d5b78d5e5a45957ec12 apps/worker/tsconfig.temporal-tests.json + fef9c5163c16c3d2e5bee71f3a1e1e7c3c9819cf4dd4c439975d85588db5e849 package-lock.json + e2761ce0d9ecf815666534ffb231a595b1c602c5f5bc59f9abf4f72503f7fe92 packages/gateway/tests/server.test.ts + SOURCE_SHA256 + sha256sum --check "$RUNNER_TEMP/reviewed84.sha256" + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version: '22.23.0' + - name: Check source checkout hygiene + run: npm run hygiene:preflight + - name: Create sanitized candidate export + run: node scripts/public-export.mjs --output "$RUNNER_TEMP/spaceapp-reviewed84" + - name: Verify exported changed-file bytes + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: sha256sum --check "$RUNNER_TEMP/reviewed84.sha256" + - name: Install the committed dependency lock + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: npm ci --no-audit --no-fund + - name: Build dependencies and check production types + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: npm run check + - name: Strictly check the Temporal tests and imported fixtures + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: npm run check:temporal-tests -w @space/worker + - name: Run real sandbox and replay within 180 seconds + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: timeout --signal=TERM --kill-after=10s 180s npm test -w @space/worker -- tests/temporal-workflows.test.ts + - name: Verify source bytes after execution + if: always() + run: sha256sum --check "$RUNNER_TEMP/reviewed84.sha256" + - name: Verify export bytes after execution + if: always() + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: sha256sum --check "$RUNNER_TEMP/reviewed84.sha256" + + full-exact-candidate: + runs-on: ubuntu-latest + timeout-minutes: 75 + steps: + - name: Checkout the exact reviewed candidate + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + repository: 3Nerion7/spaceapp + ref: 693c1cd28ef3a4e7efbcb1ea2935b49b84e4bd5c + persist-credentials: false + - name: Verify commit, tree and changed-file bytes + shell: bash + run: | + set -euo pipefail + test "$(git rev-parse HEAD)" = 693c1cd28ef3a4e7efbcb1ea2935b49b84e4bd5c + test "$(git rev-parse 'HEAD^{tree}')" = a87458347631ce11c657a419a804994aa6feded9 + test -z "$(git status --porcelain)" + cat > "$RUNNER_TEMP/reviewed84.sha256" <<'SOURCE_SHA256' + 7856a0f53b3a476f0ec93d7cc4da1fcca7e850775b2e5d118c7a8ce3f7e7ab8a .github/workflows/temporal-replay.yml + b3f8aa0bec46e639a5d8a46c56dd280e1740b228393778a7dadec1906be9141f apps/api/tests/room-watchdog.test.ts + 272ac7433bf89dc3c4d680bc77b412498743208a4684573c090935bdaeef90e9 apps/api/tests/space-control-capture.test.ts + f4a57c9e02339bb68fc8b8bd0082a0931a74e808edcbedec574664fe537b29a3 apps/worker/package.json + 103eab80f8d9a96d8954d7b01a3566e2cbde9ca6222b80d53ca8df19e0a64c1c apps/worker/tests/fixtures/workflow-histories/README.md + 669f8f2a37378b6edfad77c41f0370da2ed896803d0977c7c0ff4b3c4c66f4ba apps/worker/tests/fixtures/workflow-histories/codex-turn-retry.json + bd877a561855620e167744e215467e20409e71e1a1a9b2b14aa406e4cb16b26e apps/worker/tests/fixtures/workflow-histories/dot-goal-wake.json + b77d3a1389e87f097de6b4d30ed91f60f94030c34c285bf66fbd7aa57dfe191d apps/worker/tests/fixtures/workflow-histories/dummy-turn-retry.json + 75988e4a90837703e5963510ef8cbb9074690ae1f181d72c3b02e7cdb1109241 apps/worker/tests/fixtures/workflow-histories/memory-consolidation-change.json + 608162c52fb0e65dffa00a03518fb179ebd1fc5047b4effd1a58a95d417a681f apps/worker/tests/fixtures/workflow-histories/memory-maintenance-child.json + e9ac8828e6029e8b06663bd7b6bb2d9f7ea0311e653b504c067bc2ba492bbfc8 apps/worker/tests/fixtures/workflow-histories/memory-mutation-retry.json + 19f4cd5a21eb2d813e0289487789d8ce02ed08b8a76ee5f0881fe1a836ef0898 apps/worker/tests/fixtures/workflow-histories/room-action-failure.json + 71dfa94639d310a30d68a68d798bb20dfada1e838567e588e2c7e5bafb574025 apps/worker/tests/fixtures/workflow-histories/supervisor-current-continuation.json + 90c108f3200ed93f2359c93abb0d38d34fcf31a215a096d72e1314255339bb13 apps/worker/tests/fixtures/workflow-histories/supervisor-legacy-continuation.json + 6dbe7ac489e02ff5ac94b0628427cfbc379ec6e5d8f1d12dad379be85152bd58 apps/worker/tests/record-temporal-histories.mjs + c4a24b9b640bd1673f470aca328b2826c595d4a253716c0b4915a7a596139922 apps/worker/tests/room-continuation-fixture.ts + 741dc87d4932d0aeae3655b31eb275f48c8b9045f9db2d386186a68e8557c8af apps/worker/tests/support/temporal-nondeterministic-workflows.ts + c473e29712c23645722c52dece5f022e046ff1c3b990738482e73198b6ddf558 apps/worker/tests/support/temporal-real-workflows.ts + ffab1350234dd04287dfadcc3016e66de31d3e297302dd4d538a34db68d935f1 apps/worker/tests/temporal-workflows.test.ts + e8c7d03fba172eef25c8b880556fabd77bafd67de3178d5b78d5e5a45957ec12 apps/worker/tsconfig.temporal-tests.json + fef9c5163c16c3d2e5bee71f3a1e1e7c3c9819cf4dd4c439975d85588db5e849 package-lock.json + e2761ce0d9ecf815666534ffb231a595b1c602c5f5bc59f9abf4f72503f7fe92 packages/gateway/tests/server.test.ts + SOURCE_SHA256 + sha256sum --check "$RUNNER_TEMP/reviewed84.sha256" + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version: '22.23.0' + - name: Check source checkout hygiene + run: npm run hygiene:preflight + - name: Create sanitized candidate export + run: node scripts/public-export.mjs --output "$RUNNER_TEMP/spaceapp-reviewed84" + - name: Verify exported changed-file bytes + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: sha256sum --check "$RUNNER_TEMP/reviewed84.sha256" + - name: Install the committed dependency lock + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: npm ci --no-audit --no-fund + - name: Build dependencies and check production types + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: npm run check + - name: Strictly check the Temporal tests and imported fixtures + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: npm run check:temporal-tests -w @space/worker + - name: Install required public-test system dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends ffmpeg ripgrep + ffmpeg -version + rg --version + - name: Run the complete public test command + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: timeout --signal=TERM --kill-after=10s 3600s npm test + - name: Build the sanitized candidate + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: npm run build + - name: Verify source bytes after execution + if: always() + run: sha256sum --check "$RUNNER_TEMP/reviewed84.sha256" + - name: Verify export bytes after execution + if: always() + working-directory: ${{ runner.temp }}/spaceapp-reviewed84 + run: sha256sum --check "$RUNNER_TEMP/reviewed84.sha256" diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml deleted file mode 100644 index 61f929135..000000000 --- a/.github/workflows/security.yml +++ /dev/null @@ -1,250 +0,0 @@ -name: Security - -on: - pull_request: - push: - branches: - - main - schedule: - - cron: "23 4 * * 1" - workflow_dispatch: - -permissions: - contents: read - security-events: write - pull-requests: read - -concurrency: - group: security-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - container-changes: - name: Detect container source changes - runs-on: ubuntu-latest - outputs: - required: ${{ steps.filter.outputs.required }} - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Require image scans only for image source changes - id: filter - shell: bash - env: - BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} - EVENT_NAME: ${{ github.event_name }} - run: | - if [[ "$EVENT_NAME" == "schedule" || "$EVENT_NAME" == "workflow_dispatch" ]]; then - echo "required=true" >> "$GITHUB_OUTPUT" - elif [[ -z "$BASE_SHA" || "$BASE_SHA" =~ ^0+$ ]]; then - echo "required=true" >> "$GITHUB_OUTPUT" - elif git diff --quiet "$BASE_SHA" "$GITHUB_SHA" -- \ - apps \ - packages \ - ':(exclude)packages/run-spaceapp/**' \ - deploy/docker \ - starter-memory \ - Dockerfile \ - package-lock.json; then - echo "required=false" >> "$GITHUB_OUTPUT" - else - echo "required=true" >> "$GITHUB_OUTPUT" - fi - - source: - name: Source, dependencies, and SBOM - runs-on: ubuntu-latest - timeout-minutes: 35 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - fetch-depth: 0 - persist-credentials: false - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version-file: .nvmrc - cache: npm - - - run: npm ci - - run: npm audit --audit-level=high - - name: Install ripgrep (the file search tests run the real rg) - run: sudo apt-get update -qq && sudo apt-get install -y -qq ripgrep - - - run: npm run test:public - - run: npm run public:export:verify - - - name: Secret scan - uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2.3.9 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Block fixable Medium, High, and Critical filesystem findings - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - scan-type: fs - scan-ref: . - format: sarif - limit-severities-for-sarif: true - output: trivy-filesystem.sarif - severity: MEDIUM,HIGH,CRITICAL - ignore-unfixed: true - exit-code: "1" - - - name: Upload blocking filesystem scan - if: always() && hashFiles('trivy-filesystem.sarif') != '' - uses: github/codeql-action/upload-sarif@4187e74d05793876e9989daffde9c3e66b4acd07 # v3.37.3 - with: - sarif_file: trivy-filesystem.sarif - - - name: Capture all filesystem findings - if: always() - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - scan-type: fs - scan-ref: . - format: json - output: trivy-full-filesystem.json - severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL - ignore-unfixed: false - exit-code: "0" - - - name: Summarize all filesystem findings - if: always() && hashFiles('trivy-full-filesystem.json') != '' - run: >- - node scripts/trivy-report-summary.mjs - --input trivy-full-filesystem.json - --label filesystem - >> "$GITHUB_STEP_SUMMARY" - - - name: Upload full filesystem report - if: always() && hashFiles('trivy-full-filesystem.json') != '' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: trivy-full-filesystem - path: trivy-full-filesystem.json - if-no-files-found: error - - - name: Generate source SBOM - uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 - with: - path: . - format: spdx-json - output-file: spaceapp-source.spdx.json - - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: source-sbom - path: spaceapp-source.spdx.json - if-no-files-found: error - - dependency-review: - name: Dependency review - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 - with: - fail-on-severity: high - - codeql: - name: CodeQL - runs-on: ubuntu-latest - timeout-minutes: 35 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: github/codeql-action/init@4187e74d05793876e9989daffde9c3e66b4acd07 # v3.37.3 - with: - languages: javascript-typescript - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version-file: .nvmrc - cache: npm - - - run: npm ci - - run: npm run build - - - uses: github/codeql-action/analyze@4187e74d05793876e9989daffde9c3e66b4acd07 # v3.37.3 - - image: - name: Image scan / ${{ matrix.target }} - needs: container-changes - if: needs.container-changes.outputs.required == 'true' - strategy: - fail-fast: false - matrix: - target: - - core - - browser - - cli - runs-on: ubuntu-latest - timeout-minutes: 55 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 - with: - context: . - target: ${{ matrix.target }} - load: true - tags: spaceapp-${{ matrix.target }}:security-scan - cache-from: type=gha,scope=security-${{ matrix.target }} - cache-to: type=gha,mode=max,scope=security-${{ matrix.target }} - - - name: Block fixable Medium, High, and Critical image findings - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - image-ref: spaceapp-${{ matrix.target }}:security-scan - format: sarif - limit-severities-for-sarif: true - output: trivy-${{ matrix.target }}.sarif - severity: MEDIUM,HIGH,CRITICAL - ignore-unfixed: true - exit-code: "1" - - - name: Upload blocking image scan - if: always() && hashFiles(format('trivy-{0}.sarif', matrix.target)) != '' - uses: github/codeql-action/upload-sarif@4187e74d05793876e9989daffde9c3e66b4acd07 # v3.37.3 - with: - sarif_file: trivy-${{ matrix.target }}.sarif - - - name: Capture all image findings - if: always() - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - image-ref: spaceapp-${{ matrix.target }}:security-scan - format: json - output: trivy-full-${{ matrix.target }}.json - severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL - ignore-unfixed: false - exit-code: "0" - - - name: Summarize all image findings - if: always() && hashFiles(format('trivy-full-{0}.json', matrix.target)) != '' - run: >- - node scripts/trivy-report-summary.mjs - --input "trivy-full-${{ matrix.target }}.json" - --label "${{ matrix.target }}" - >> "$GITHUB_STEP_SUMMARY" - - - name: Upload full image report - if: always() && hashFiles(format('trivy-full-{0}.json', matrix.target)) != '' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: trivy-full-${{ matrix.target }} - path: trivy-full-${{ matrix.target }}.json - if-no-files-found: error