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
4ea53d6
d7c4ee9
91cb3e6
827317a
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,235 @@ | ||
| name: Axum container preparation | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [main] | ||
| paths: | ||
| - .github/actions/deploy-core/tests/check-action-pins.sh | ||
| - .github/zizmor.yml | ||
| - scripts/install-actionlint.sh | ||
| - scripts/install-yq.sh | ||
| - .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/actions/deploy-core/tests/check-action-pins.sh | ||
| - .github/zizmor.yml | ||
| - scripts/install-actionlint.sh | ||
| - scripts/install-yq.sh | ||
| - .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 | ||
|
|
||
| env: | ||
| ACTIONLINT_VERSION: 1.7.7 | ||
| ZIZMOR_VERSION: 1.16.3 | ||
| YQ_VERSION: 4.53.3 | ||
|
|
||
| jobs: | ||
| prepare: | ||
| runs-on: ubuntu-24.04 | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | ||
| with: | ||
| node-version-file: .tool-versions | ||
| - name: Install pinned validation binaries | ||
| run: | | ||
| bin="$RUNNER_TEMP/tools/bin" | ||
| mkdir -p "$bin" | ||
| INSTALL_DIR="$bin" scripts/install-actionlint.sh "$ACTIONLINT_VERSION" | ||
| INSTALL_DIR="$bin" scripts/install-yq.sh "$YQ_VERSION" | ||
| cargo install zizmor --version "$ZIZMOR_VERSION" --locked --root "$RUNNER_TEMP/tools" | ||
| "$bin/actionlint" -version | grep -qF "$ACTIONLINT_VERSION" | ||
| "$bin/yq" --version | grep -qF "version v$YQ_VERSION" | ||
| "$bin/zizmor" --version | grep -qF "$ZIZMOR_VERSION" | ||
| printf '%s\n' "$bin" >>"$GITHUB_PATH" | ||
|
|
||
| - name: Install ShellCheck | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y shellcheck | ||
|
|
||
| - name: Validate the inactive application release recipe | ||
| run: | | ||
| "$RUNNER_TEMP/tools/bin/actionlint" -shellcheck='shellcheck -S warning' examples/container-publishing/release.yml | ||
| .github/actions/deploy-core/tests/check-action-pins.sh examples/container-publishing/release.yml | ||
| "$RUNNER_TEMP/tools/bin/zizmor" --offline examples/container-publishing/release.yml | ||
|
|
||
| - name: ShellCheck Axum container scripts | ||
| run: shellcheck -e SC1091 scripts/*axum_container*.sh examples/container-publishing/publish.sh | ||
|
|
||
| - 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 | ||
| - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | ||
| with: | ||
| node-version-file: .tool-versions | ||
| - 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 | ||
| # Reuse the daemon; the handoff helper creates the pinned build instance. | ||
| driver: docker | ||
| use: false | ||
| - 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 | ||
| - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | ||
| with: | ||
| node-version-file: .tool-versions | ||
| - name: Select exact immutable artifacts from this run and attempt | ||
| id: artifacts | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| gh api --paginate --slurp "repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/artifacts?per_page=100" \ | ||
| | jq '{artifacts: [.[].artifacts[]]}' > "$RUNNER_TEMP/artifacts.json" | ||
| 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 | ||
|
ChristianPavilonis marked this conversation as resolved.
Resolved
|
||
| curl --fail --silent "http://127.0.0.1:$port/v2/" >/dev/null | ||
| ./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,9 @@ name: Deploy actions | |
| on: | ||
| pull_request: | ||
| paths: | ||
| # 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 +26,9 @@ on: | |
| push: | ||
| branches: [main] | ||
| paths: | ||
| # 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 | ||
|
|
@@ -83,7 +89,8 @@ jobs: | |
| "$RUNNER_TEMP/tools/bin/actionlint" -shellcheck='shellcheck -S warning' | ||
|
|
||
| - 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 | ||
|
|
||
| - name: Zizmor security scan | ||
| run: '"$RUNNER_TEMP/tools/bin/zizmor" --offline .github' | ||
|
|
@@ -97,6 +104,10 @@ jobs: | |
| scripts/install-actionlint.sh \ | ||
| scripts/install-yq.sh | ||
|
|
||
| - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | ||
|
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. ⛏ Leftover changes in this workflow Nothing under The other changes in this file are leftovers too: the comment block at lines 6 and 29 was removed on main by #417 and is re-added by the merge, and the pin-gate step's |
||
| with: | ||
| node-version-file: .tool-versions | ||
|
|
||
| - name: Bash contract tests | ||
| run: .github/actions/deploy-core/tests/run.sh | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -180,3 +180,6 @@ jobs: | |
|
|
||
| - name: Run Prettier (check) | ||
| run: npm run format | ||
|
|
||
| - name: Build docs | ||
| run: npm run build | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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 tool pins, and the static checks now gate the native builds
ACTIONLINT_VERSION,ZIZMOR_VERSIONandYQ_VERSIONare now declared identically here and indeploy-action.yml, so a bump in one file can silently miss the other. Also,preparenow compiles Zizmor before the native jobs can start:preparetook about 1m50s atd7c4ee9eand 5m04s at this head, which adds roughly three minutes to the critical path.Suggestion: move the actionlint/pin/Zizmor/ShellCheck steps into a separate job that runs in parallel with
native(the handoff can still depend on it if desired), and add a comment pairing these pins withdeploy-action.yml.