Skip to content

build(deps-dev): Bump tsx from 4.22.4 to 4.23.0 (#146) #44

build(deps-dev): Bump tsx from 4.22.4 to 4.23.0 (#146)

build(deps-dev): Bump tsx from 4.22.4 to 4.23.0 (#146) #44

Workflow file for this run

name: Release Image
on:
push:
branches:
- main
workflow_dispatch:
inputs:
publish_project_release:
description: Create the matching Git tag and GitHub Release after image verification
required: false
default: false
type: boolean
permissions:
contents: write
packages: write
id-token: write
attestations: write
concurrency:
group: release-image-${{ github.ref }}
cancel-in-progress: false
env:
SHELL: /bin/bash
jobs:
publish_and_verify:
name: publish-and-verify
runs-on: ubuntu-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
SYNOLOGY_RUNNER_BASE_DIR: /volume1/docker/github-runner-fleet
COMPOSE_PROJECT_NAME: github-runner-fleet
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
with:
node-version: "24"
- uses: pnpm/action-setup@v6
with:
version: 10.32.1
- run: pnpm install --frozen-lockfile
- run: pnpm validate-config -- --config config/pools.yaml --env /tmp/release.env
- run: SMOKE_PLATFORM=linux/amd64 pnpm smoke-test
- uses: docker/setup-qemu-action@v4
- uses: docker/setup-buildx-action@v4
- uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Ensure envsubst is available
run: |
set -euo pipefail
if command -v envsubst >/dev/null 2>&1; then
exit 0
fi
if [[ "$(id -u)" == "0" ]] && command -v apt-get >/dev/null 2>&1; then
apt-get update
apt-get install -y --no-install-recommends gettext-base
elif command -v sudo >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y --no-install-recommends gettext-base
else
echo "envsubst is required by cosign-installer." >&2
exit 1
fi
- uses: sigstore/cosign-installer@v4.1.2
- id: release_meta
run: |
node --input-type=module <<'EOF'
import fs from "node:fs";
import YAML from "yaml";
const config = YAML.parse(fs.readFileSync("config/pools.yaml", "utf8"));
const packageJson = JSON.parse(fs.readFileSync("package.json", "utf8"));
if (!config?.image?.repository || !config?.image?.tag) {
throw new Error("config/pools.yaml must define image.repository and image.tag");
}
if (!packageJson?.version) {
throw new Error("package.json must define version");
}
if (packageJson.version !== config.image.tag) {
throw new Error(
`package.json version ${packageJson.version} must match config image tag ${config.image.tag}`
);
}
fs.appendFileSync(
process.env.GITHUB_OUTPUT,
`image_ref=${config.image.repository}:${config.image.tag}\n`
);
fs.appendFileSync(
process.env.GITHUB_OUTPUT,
`image_repo=${config.image.repository}\n`
);
fs.appendFileSync(
process.env.GITHUB_OUTPUT,
`image_tag=${config.image.tag}\n`
);
fs.appendFileSync(
process.env.GITHUB_OUTPUT,
`release_tag=v${packageJson.version}\n`
);
EOF
- name: guard main branch before any publish
run: |
if [[ "${GITHUB_REF_NAME}" != "main" ]]; then
echo "release-image may only publish from main" >&2
exit 1
fi
- name: guard automatic publish version
if: ${{ github.event_name == 'push' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if gh release view "${{ steps.release_meta.outputs.release_tag }}" >/dev/null 2>&1; then
echo "release ${{ steps.release_meta.outputs.release_tag }} already exists; bump package.json and config/pools.yaml before publishing a new image" >&2
exit 1
fi
- run: ./scripts/build-image.sh "${{ steps.release_meta.outputs.image_ref }}" --push
- id: image_digest
run: |
digest="$(docker buildx imagetools inspect "${{ steps.release_meta.outputs.image_ref }}" --format '{{.Manifest.Digest}}')"
test -n "${digest}"
echo "digest=${digest}" >> "${GITHUB_OUTPUT}"
docker buildx imagetools inspect "${{ steps.release_meta.outputs.image_ref }}" | tee /tmp/imagetools.txt
grep -q "linux/amd64" /tmp/imagetools.txt
grep -q "linux/arm64" /tmp/imagetools.txt
- name: Generate image SBOM
uses: anchore/sbom-action@v0
with:
image: ${{ steps.release_meta.outputs.image_ref }}@${{ steps.image_digest.outputs.digest }}
format: spdx-json
output-file: /tmp/github-runner-fleet.spdx.json
- name: Sign image digest
run: cosign sign --yes "${{ steps.release_meta.outputs.image_ref }}@${{ steps.image_digest.outputs.digest }}"
- name: Sign per-platform image digests
run: |
image_repo="${{ steps.release_meta.outputs.image_ref }}"
image_repo="${image_repo%:*}"
docker buildx imagetools inspect "${{ steps.release_meta.outputs.image_ref }}" --raw \
| jq -r '.manifests[].digest' \
| while IFS= read -r digest; do
cosign sign --yes "${image_repo}@${digest}"
done
- name: Attach SBOM attestation
run: |
cosign attest --yes \
--predicate /tmp/github-runner-fleet.spdx.json \
--type spdxjson \
"${{ steps.release_meta.outputs.image_ref }}@${{ steps.image_digest.outputs.digest }}"
- name: Emit SLSA provenance
uses: actions/attest-build-provenance@v4
with:
subject-name: ${{ steps.release_meta.outputs.image_repo }}
subject-digest: ${{ steps.image_digest.outputs.digest }}
push-to-registry: true
- name: Verify image signature and attestations
run: |
cosign verify \
--certificate-identity-regexp "https://github.com/${{ github.repository }}/.github/workflows/release-image.yml@refs/heads/main" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"${{ steps.release_meta.outputs.image_ref }}@${{ steps.image_digest.outputs.digest }}"
cosign verify-attestation \
--type spdxjson \
--certificate-identity-regexp "https://github.com/${{ github.repository }}/.github/workflows/release-image.yml@refs/heads/main" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"${{ steps.release_meta.outputs.image_ref }}@${{ steps.image_digest.outputs.digest }}"
cosign verify-attestation \
--type slsaprovenance \
--certificate-identity-regexp "https://github.com/${{ github.repository }}/.github/workflows/release-image.yml@refs/heads/main" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"${{ steps.release_meta.outputs.image_ref }}@${{ steps.image_digest.outputs.digest }}"
- run: |
for attempt in 1 2 3 4 5 6; do
if pnpm validate-image -- --config config/pools.yaml --env /tmp/release.env; then
exit 0
fi
if [[ "${attempt}" == "6" ]]; then
exit 1
fi
sleep 10
done
- run: |
docker run --rm --platform linux/amd64 --entrypoint /bin/sh "${{ steps.release_meta.outputs.image_ref }}" -lc \
'test "$(cd /actions-runner && ./bin/Runner.Listener --version)" = "2.334.0" && command -v pgrep && pgrep --version | head -n 1 && docker --version && node --version && python3 --version && terraform version | head -n 1'
- run: |
docker run --rm --platform linux/arm64 --entrypoint /bin/sh "${{ steps.release_meta.outputs.image_ref }}" -lc \
'test "$(cd /actions-runner && ./bin/Runner.Listener --version)" = "2.334.0" && command -v pgrep && pgrep --version | head -n 1 && docker --version && node --version && python3 --version && terraform version | head -n 1'
- if: ${{ github.event_name == 'push' || inputs.publish_project_release }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if gh release view "${{ steps.release_meta.outputs.release_tag }}" >/dev/null 2>&1; then
echo "release ${{ steps.release_meta.outputs.release_tag }} already exists" >&2
exit 1
fi
gh release create "${{ steps.release_meta.outputs.release_tag }}" \
--target "${GITHUB_SHA}" \
--title "${{ steps.release_meta.outputs.release_tag }}" \
--generate-notes