Repository navigation
Scaffold hardened Axum application Docker recipes #401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
289a9eb
7e03616
0ea5874
05d3c6e
68894a0
7f846ae
b8b8296
4936442
66c73e9
1f244a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| name: Axum container preparation | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [main] | ||
| paths: | ||
| - .github/workflows/axum-container.yml | ||
| - Cargo.toml | ||
| - Cargo.lock | ||
| - .tool-versions | ||
| - crates/** | ||
| - examples/app-demo/** | ||
| - examples/container-publishing/** | ||
| - examples/axum-deployment/** | ||
| - scripts/*axum_container*.sh | ||
| - scripts/axum_container*.mjs | ||
| - scripts/package*.json | ||
| - scripts/tests/*axum_container*.mjs | ||
| push: | ||
| branches: [main] | ||
| paths: | ||
| - .github/workflows/axum-container.yml | ||
| - Cargo.toml | ||
| - Cargo.lock | ||
| - .tool-versions | ||
| - crates/** | ||
| - examples/app-demo/** | ||
| - examples/container-publishing/** | ||
| - examples/axum-deployment/** | ||
| - scripts/*axum_container*.sh | ||
| - scripts/axum_container*.mjs | ||
| - scripts/package*.json | ||
| - scripts/tests/*axum_container*.mjs | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| prepare: | ||
| runs-on: ubuntu-24.04 | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Retrieve Node version | ||
| id: node-version | ||
| run: echo "node-version=$(awk '$1 == "nodejs" { print $2 }' .tool-versions)" >> "$GITHUB_OUTPUT" | ||
| - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 | ||
| with: | ||
| node-version: ${{ steps.node-version.outputs.node-version }} | ||
| - name: Use the declared Rust toolchain | ||
| run: | | ||
| version=$(awk '$1 == "rust" { print $2 }' .tool-versions) | ||
| rustup toolchain install "$version" --profile minimal | ||
| echo "RUSTUP_TOOLCHAIN=$version" >> "$GITHUB_ENV" | ||
| - name: Install framework helper dependencies | ||
| run: npm ci --prefix scripts --ignore-scripts | ||
| - name: Prepare one application and lockfile | ||
| run: | | ||
| ./scripts/prepare_generated_axum_container.sh "$RUNNER_TEMP/fixture" | ||
| AXUM_PREPARED_CONTEXT="$RUNNER_TEMP/fixture/container-probe" \ | ||
| node --test scripts/tests/test_axum_container*.test.mjs | ||
| tar -C "$RUNNER_TEMP/fixture" -cf "$RUNNER_TEMP/context.tar" container-probe | ||
| - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 | ||
| with: | ||
| name: axum-context-${{ github.run_id }}-${{ github.run_attempt }} | ||
| path: ${{ runner.temp }}/context.tar | ||
| if-no-files-found: error | ||
| retention-days: 7 | ||
|
|
||
| native: | ||
| needs: prepare | ||
| timeout-minutes: 30 | ||
| # Framework packaging evidence is not application release approval. | ||
| env: | ||
| SCAN_POLICY: report-only | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| - arch: amd64 | ||
| runner: ubuntu-24.04 | ||
| - arch: arm64 | ||
| runner: ubuntu-24.04-arm | ||
| runs-on: ${{ matrix.runner }} | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Retrieve Node version | ||
| id: node-version | ||
| run: echo "node-version=$(awk '$1 == "nodejs" { print $2 }' .tool-versions)" >> "$GITHUB_OUTPUT" | ||
| - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 | ||
| with: | ||
| node-version: ${{ steps.node-version.outputs.node-version }} | ||
| - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 | ||
| with: | ||
| name: axum-context-${{ github.run_id }}-${{ github.run_attempt }} | ||
| path: ${{ runner.temp }}/context | ||
| digest-mismatch: error | ||
| - uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 | ||
| with: | ||
| version: v0.37.0 | ||
| use: false | ||
| driver-opts: image=moby/buildkit:v0.25.1@sha256:79cc6476ab1a3371c9afd8b44e7c55610057c43e18d9b39b68e2b0c2475cc1b6 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⛏ Duplicate BuildKit pin for an unused builder With |
||
| - name: Install framework helper dependencies | ||
| run: npm ci --prefix scripts --ignore-scripts | ||
| - name: Native image, packaging, scan and OCI identity checks | ||
| env: | ||
| ARCH: ${{ matrix.arch }} | ||
| run: | | ||
| tar -C "$RUNNER_TEMP/context" -xf "$RUNNER_TEMP/context/context.tar" --no-same-owner | ||
| ./scripts/test_axum_container_handoff.sh build \ | ||
| "$RUNNER_TEMP/context/container-probe" "$RUNNER_TEMP/accepted" \ | ||
| "linux/$ARCH" "$GITHUB_SHA" "$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" | ||
| - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 | ||
| with: | ||
| name: accepted-${{ matrix.arch }}-${{ github.run_id }}-${{ github.run_attempt }} | ||
| path: | | ||
| ${{ runner.temp }}/accepted/image.tar | ||
| ${{ runner.temp }}/accepted/receipt.json | ||
| ${{ runner.temp }}/accepted/inputs.json | ||
| ${{ runner.temp }}/accepted/scan.json | ||
| ${{ runner.temp }}/accepted/scanner.json | ||
| ${{ runner.temp }}/accepted/sbom.json | ||
| ${{ runner.temp }}/accepted/provenance.json | ||
| ${{ runner.temp }}/accepted/rust-advisories.json | ||
| if-no-files-found: error | ||
| retention-days: 7 | ||
| - name: Retain sanitized failure evidence separately | ||
| if: failure() | ||
| uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 | ||
| with: | ||
| name: failed-${{ matrix.arch }}-${{ github.run_id }}-${{ github.run_attempt }} | ||
| path: | | ||
| ${{ runner.temp }}/accepted/*.log | ||
| ${{ runner.temp }}/accepted/scan.json | ||
| ${{ runner.temp }}/accepted/scanner.json | ||
| ${{ runner.temp }}/accepted/image.json | ||
| ${{ runner.temp }}/accepted/inputs.json | ||
| ${{ runner.temp }}/accepted/rust-advisories.json | ||
| ${{ runner.temp }}/accepted/smoke | ||
| if-no-files-found: warn | ||
| retention-days: 7 | ||
|
|
||
| handoff: | ||
| needs: native | ||
| runs-on: ubuntu-24.04 | ||
| timeout-minutes: 15 | ||
| env: | ||
| SCAN_POLICY: report-only | ||
| permissions: | ||
| contents: read | ||
| actions: read | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Retrieve Node version | ||
| id: node-version | ||
| run: echo "node-version=$(awk '$1 == "nodejs" { print $2 }' .tool-versions)" >> "$GITHUB_OUTPUT" | ||
| - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 | ||
| with: | ||
| node-version: ${{ steps.node-version.outputs.node-version }} | ||
| - name: Select exact immutable artifacts from this run and attempt | ||
| id: artifacts | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| gh api "repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/artifacts?per_page=100" > "$RUNNER_TEMP/artifacts.json" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⛏ No pagination: |
||
| ids=$(node examples/container-publishing/verify_artifacts.mjs artifact-ids \ | ||
| "$RUNNER_TEMP/artifacts.json" --run-id "$GITHUB_RUN_ID" --attempt "$GITHUB_RUN_ATTEMPT") | ||
| echo "ids=$ids" >> "$GITHUB_OUTPUT" | ||
| - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 | ||
| with: | ||
| artifact-ids: ${{ steps.artifacts.outputs.ids }} | ||
| path: ${{ runner.temp }}/bundles | ||
| digest-mismatch: error | ||
| - name: Import accepted variants in a separate job without rebuilding | ||
| run: | | ||
| for arch in amd64 arm64; do | ||
| ./scripts/test_axum_container_handoff.sh import \ | ||
| "$RUNNER_TEMP/bundles/accepted-$arch-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" \ | ||
| "$RUNNER_TEMP/import-$arch" "linux/$arch" "$GITHUB_SHA" "$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" | ||
| done | ||
| - name: Assemble and verify a localhost runtime index without external publication | ||
| run: | | ||
| source examples/container-publishing/tools.env | ||
| registry="axum-index-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" | ||
| trap 'docker rm -f "$registry" >/dev/null 2>&1 || true' EXIT | ||
| docker run -d --name "$registry" -p 127.0.0.1::5000 "$REGISTRY_IMAGE" | ||
| port=$(docker port "$registry" 5000/tcp | awk -F: '{print $NF}') | ||
| for _ in $(seq 1 30); do curl --fail --silent "http://127.0.0.1:$port/v2/" && break; sleep 1; done | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⛏ Registry wait never fails: if the registry never comes up the loop just ends and |
||
| ./examples/container-publishing/publish.sh "127.0.0.1:$port/fixture" fixture \ | ||
| "$RUNNER_TEMP/bundles/accepted-amd64-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" \ | ||
| "$RUNNER_TEMP/bundles/accepted-arm64-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" \ | ||
| "$RUNNER_TEMP/index" "$GITHUB_SHA" "$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,15 @@ name: Deploy actions | |
| on: | ||
| pull_request: | ||
| paths: | ||
| - scripts/*axum_container*.sh | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ♻️ Over-broad triggers: these paths start the full deploy smoke matrix, but this workflow only ShellChecks the axum helpers. Consider moving that ShellCheck into |
||
| - scripts/axum_container*.mjs | ||
| - scripts/tests/*axum_container*.mjs | ||
| - examples/container-publishing/** | ||
| - examples/axum-deployment/** | ||
| - docs/guide/*axum-containers.md | ||
| # ANY workflow or action change must start the repository-wide pin gate (and | ||
| # the smokes) — including a brand-new action directory or an unrelated | ||
| # workflow like test.yml that could introduce a floating ref. | ||
| - .github/actions/** | ||
| - .github/workflows/** | ||
| - .github/zizmor.yml | ||
|
|
@@ -23,6 +32,15 @@ on: | |
| push: | ||
| branches: [main] | ||
| paths: | ||
| - scripts/*axum_container*.sh | ||
| - scripts/axum_container*.mjs | ||
| - scripts/tests/*axum_container*.mjs | ||
| - examples/container-publishing/** | ||
| - examples/axum-deployment/** | ||
| - docs/guide/*axum-containers.md | ||
| # ANY workflow or action change must start the repository-wide pin gate (and | ||
| # the smokes) — including a brand-new action directory or an unrelated | ||
| # workflow like test.yml that could introduce a floating ref. | ||
| - .github/actions/** | ||
| - .github/workflows/** | ||
| - .github/zizmor.yml | ||
|
|
@@ -81,12 +99,15 @@ jobs: | |
| - name: Actionlint | ||
| run: | | ||
| "$RUNNER_TEMP/tools/bin/actionlint" -shellcheck='shellcheck -S warning' | ||
| "$RUNNER_TEMP/tools/bin/actionlint" -shellcheck='shellcheck -S warning' examples/container-publishing/release.yml | ||
|
|
||
| - name: Third-party action pin gate | ||
| run: .github/actions/deploy-core/tests/check-action-pins.sh | ||
| run: | | ||
| .github/actions/deploy-core/tests/check-action-pins.sh | ||
| .github/actions/deploy-core/tests/check-action-pins.sh examples/container-publishing/release.yml | ||
|
|
||
| - name: Zizmor security scan | ||
| run: '"$RUNNER_TEMP/tools/bin/zizmor" --offline .github' | ||
| run: '"$RUNNER_TEMP/tools/bin/zizmor" --offline .github examples/container-publishing/release.yml' | ||
|
|
||
| - name: ShellCheck action scripts | ||
| run: | | ||
|
|
@@ -95,7 +116,16 @@ jobs: | |
| .github/actions/*/tests/*.sh \ | ||
| .github/actions/deploy-core/tests/*.sh \ | ||
| scripts/install-actionlint.sh \ | ||
| scripts/install-yq.sh | ||
| scripts/install-yq.sh \ | ||
| scripts/*axum_container*.sh \ | ||
| examples/container-publishing/publish.sh | ||
|
|
||
| - name: Retrieve Node version | ||
| id: node-version | ||
| run: echo "node-version=$(awk '$1 == "nodejs" { print $2 }' .tool-versions)" >> "$GITHUB_OUTPUT" | ||
| - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 | ||
| with: | ||
| node-version: ${{ steps.node-version.outputs.node-version }} | ||
|
|
||
| - name: Bash contract tests | ||
| run: .github/actions/deploy-core/tests/run.sh | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
♻️ Duplicated Node setup: this "Retrieve Node version" +
setup-nodepair is repeated in three jobs (and deploy-action).setup-nodesupportsnode-version-file: .tool-versionsdirectly, which removes the awk step. Also ⛏ the pin comment is# v6; other actions name the exact release.