Repository navigation
release #10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: release | |
| # Cuts a calendar-versioned release every Sunday from a no-cache rebuild, so | |
| # the published image tracks upstream tool and base-image updates. | |
| # | |
| # CalVer rather than SemVer on purpose: almost every version in versions.json | |
| # is "install latest", so a tag records what the world looked like on a given | |
| # day. It cannot promise a compatibility contract, and SemVer would imply one. | |
| # | |
| # NOTE: GitHub disables scheduled workflows after 60 days without repository | |
| # activity. If releases stop appearing, check whether the schedule was | |
| # disabled before looking for a bug. | |
| on: | |
| schedule: | |
| - cron: '0 3 * * 0' | |
| workflow_dispatch: | |
| inputs: | |
| no-cache: | |
| description: Rebuild from scratch so unpinned tools pick up upstream updates | |
| type: boolean | |
| default: true | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| version: | |
| name: resolve version | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| outputs: | |
| version: ${{ steps.calc.outputs.version }} | |
| month: ${{ steps.calc.outputs.month }} | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Compute CalVer | |
| id: calc | |
| run: | | |
| set -euo pipefail | |
| base="$(date -u +%Y.%m.%d)" | |
| version="${base}" | |
| n=1 | |
| # A second release on the same day becomes .2, .3, and so on | |
| while git rev-parse -q --verify "refs/tags/v${version}" > /dev/null 2>&1; do | |
| n=$((n + 1)) | |
| version="${base}.${n}" | |
| done | |
| { | |
| echo "version=${version}" | |
| echo "month=$(date -u +%Y.%m)" | |
| } >> "$GITHUB_OUTPUT" | |
| echo "Releasing v${version}" | |
| build: | |
| name: build | |
| needs: version | |
| uses: ./.github/workflows/build.yml | |
| permissions: | |
| contents: read | |
| packages: write | |
| security-events: write | |
| id-token: write | |
| attestations: write | |
| artifact-metadata: write | |
| with: | |
| publish: true | |
| no-cache: ${{ github.event_name == 'schedule' || inputs.no-cache }} | |
| tags: | | |
| type=raw,value=${{ needs.version.outputs.version }} | |
| type=raw,value=${{ needs.version.outputs.month }} | |
| type=raw,value=latest | |
| release: | |
| name: publish release | |
| needs: [version, build] | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| artifact-metadata: read | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| # One SPDX document per architecture, scanned in the build job. Each is | |
| # around 52 MB of JSON, which is a hostile download to hang off a release | |
| # page, and it is highly repetitive - measured at 93% compression on | |
| # v2026.08.04 - so both ship gzipped. | |
| - name: Download SBOMs | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: /tmp/sbom | |
| pattern: sbom-* | |
| merge-multiple: true | |
| - name: Compress SBOMs | |
| run: | | |
| set -euo pipefail | |
| shopt -s nullglob | |
| files=(/tmp/sbom/*.spdx.json) | |
| if [ ${#files[@]} -eq 0 ]; then | |
| echo "::error::no SBOMs were downloaded - nothing to attach" | |
| exit 1 | |
| fi | |
| for f in "${files[@]}"; do | |
| raw="$(wc -c < "$f")" | |
| gzip -9 "$f" | |
| gz="$(wc -c < "${f}.gz")" | |
| echo "$(basename "$f"): ${raw} bytes raw, ${gz} bytes gzipped" | |
| done | |
| - name: Create release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ needs.version.outputs.version }} | |
| DIGEST: ${{ needs.build.outputs.digest }} | |
| run: | | |
| set -euo pipefail | |
| cat > notes.md <<EOF | |
| Multi-architecture devcontainer image for \`linux/amd64\` and \`linux/arm64\`. | |
| \`\`\` | |
| docker pull ghcr.io/${{ github.repository }}:${VERSION} | |
| \`\`\` | |
| Digest: \`${DIGEST}\` | |
| This tag is a point-in-time snapshot. Most tools in \`versions.json\` are | |
| installed at "latest", so the same tag rebuilt on another day would not | |
| produce the same image - pin the digest above if you need one exact image. | |
| Verify the build provenance: | |
| \`\`\` | |
| gh attestation verify oci://ghcr.io/${{ github.repository }}:${VERSION} -R ${{ github.repository }} | |
| \`\`\` | |
| \`sbom-amd64.spdx.json.gz\` and \`sbom-arm64.spdx.json.gz\` below are the | |
| SPDX SBOMs for each architecture, generated with Syft. Gunzip to read; | |
| each is an ordinary SPDX 2.3 document any SPDX tool will accept. | |
| EOF | |
| gh release create "v${VERSION}" \ | |
| --target "${GITHUB_SHA}" \ | |
| --title "v${VERSION}" \ | |
| --notes-file notes.md \ | |
| /tmp/sbom/*.spdx.json.gz |