From 18b3e4006cfe34a42f3089b87397b9b77e772c7a Mon Sep 17 00:00:00 2001 From: ptaylor Date: Fri, 3 Apr 2026 11:35:26 -0700 Subject: [PATCH 1/2] add build-devcontainer action --- build-devcontainer/action.yml | 137 ++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 build-devcontainer/action.yml diff --git a/build-devcontainer/action.yml b/build-devcontainer/action.yml new file mode 100644 index 00000000..3dd2f3ec --- /dev/null +++ b/build-devcontainer/action.yml @@ -0,0 +1,137 @@ +name: "build-devcontainer-image" + +description: "Build devcontainer image" + +inputs: + tag: {type: string, required: true, description: "Image tag"} + arch: {type: string, required: true, description: "Image arch"} + repo: {type: string, required: true, description: "Image repo"} + push: {type: string, required: true, description: "Whether to push the image"} + version: {type: string, required: true, description: "Repository version number"} + retries: {type: string, default: '3', description: "Number of times to retry the container build"} + workspace-dir: {type: string, default: '.', description: "Devcontainer workspace directory"} + devcontainer-json: {type: string, required: true, description: "Path to the devcontainer.json file"} + +outputs: + hash_amd64: + value: "${{ steps.build.outputs.hash_amd64 }}" + hash_arm64: + value: "${{ steps.build.outputs.hash_arm64 }}" + repo: + value: "${{ steps.build.outputs.repo }}" + tag: + value: "${{ steps.build.outputs.tag }}" + name: + value: "${{ steps.build.outputs.name }}" + name_latest: + value: "${{ steps.build.outputs.name_latest }}" + +runs: + using: composite + steps: + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '24' + + - if: runner.environment != 'self-hosted' + name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Create docker context + shell: bash + run: docker context create builder + + - if: runner.environment != 'self-hosted' + name: Setup docker buildx on github-hosted runners + uses: docker/setup-buildx-action@v4 + with: + endpoint: builder + + - if: runner.environment == 'self-hosted' + name: Setup docker buildx on self-hosted runners + uses: docker/setup-buildx-action@v4 + with: + buildkitd-config: /etc/buildkit/buildkitd.toml + buildkitd-flags: --config /etc/buildkit/buildkitd.toml + endpoint: builder + + - if: runner.environment == 'self-hosted' + name: Setup proxy cache + uses: nv-gha-runners/setup-proxy-cache@main + continue-on-error: true + with: + enable-apt: true + + - name: Install devcontainers CLI + shell: bash + env: + push: "${{ inputs.push }}" + run: | + sudo apt update; + sudo apt install -y --no-install-recommends build-essential; + npm install -g @devcontainers/cli@v0.85.0; + if "${push}"; then + # HACK: remove the `-t` arg from the `docker buildx build` command generated by `devcontainer build` + sed -i 's/,t.map(G=>l.push("-t",G))//g' "$(npm list -g | head -n1)"/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js; + fi + + - id: build + name: Build ${{ inputs.repo }}:${{ inputs.tag }} (${{ inputs.arch }}) + shell: bash + env: + NODE_NO_WARNINGS: 1 + arch: "${{ inputs.arch }}" + push: "${{ inputs.push }}" + repo: "${{ inputs.repo }}" + retries: "${{ inputs.retries }}" + tag: "${{ inputs.tag }}" + version: "${{ inputs.version }}" + workspace_dir: "${{ inputs.workspace-dir }}" + devcontainer_json: "${{ inputs.devcontainer-json }}" + run: | + set -euo pipefail; + + declare i=0; + declare -a outputs=(); + + # Ensure tag and repo are lowercase + tag="${tag,,}" + repo="${repo,,}" + name="${repo}:${version}-${tag}" + name_latest="${repo}:latest-${tag}" + + echo "tag=${tag}" >> "$GITHUB_OUTPUT"; + echo "repo=${repo}" >> "$GITHUB_OUTPUT"; + echo "name=${name}" >> "$GITHUB_OUTPUT"; + echo "name_latest=${name_latest}" >> "$GITHUB_OUTPUT"; + + if "${push}"; then + outputs+=(--output "type=image,compression=zstd,force-compression=true,oci-mediatypes=true,push=true,push-by-digest=true,name=${repo}"); + fi + + until devcontainer build \ + --cache-from "${name}" \ + --image-name "${name}" \ + --platform "linux/${arch}" \ + --config "$devcontainer_json" \ + --workspace-folder "$workspace_dir" \ + "${outputs[@]}" 2>&1 \ + | tee "${{ runner.temp }}/${arch}.log" 1>&2 + do + if test "${i}" -lt "${retries}"; then + j=$((i++)); + t=$((i * i * 5)); + echo "Attempt $j failed! Trying again in $t seconds..."; + sleep $t; + else + echo "Failed to build ${name}"; + exit 1; + fi + done + + if test "${push}" = true; then + echo "hash_${arch}=$(grep 'exporting manifest sha256:' "${{ runner.temp }}/${arch}.log" | tail -n1 | grep -oP 'sha256:\w+')" >> "$GITHUB_OUTPUT"; + else + echo "hash_${arch}=" >> "$GITHUB_OUTPUT"; + fi From e04089ee5500a04c7548db1f73e81702f356f3c0 Mon Sep 17 00:00:00 2001 From: ptaylor Date: Thu, 30 Apr 2026 10:58:26 -0700 Subject: [PATCH 2/2] use hashes in action versions --- build-devcontainer/action.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build-devcontainer/action.yml b/build-devcontainer/action.yml index 3dd2f3ec..c6bb155f 100644 --- a/build-devcontainer/action.yml +++ b/build-devcontainer/action.yml @@ -1,4 +1,4 @@ -name: "build-devcontainer-image" +name: "build-devcontainer" description: "Build devcontainer image" @@ -30,13 +30,13 @@ runs: using: composite steps: - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version: '24' - if: runner.environment != 'self-hosted' name: Set up QEMU - uses: docker/setup-qemu-action@v4 + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4 - name: Create docker context shell: bash @@ -44,13 +44,13 @@ runs: - if: runner.environment != 'self-hosted' name: Setup docker buildx on github-hosted runners - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 with: endpoint: builder - if: runner.environment == 'self-hosted' name: Setup docker buildx on self-hosted runners - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 with: buildkitd-config: /etc/buildkit/buildkitd.toml buildkitd-flags: --config /etc/buildkit/buildkitd.toml @@ -58,7 +58,7 @@ runs: - if: runner.environment == 'self-hosted' name: Setup proxy cache - uses: nv-gha-runners/setup-proxy-cache@main + uses: nv-gha-runners/setup-proxy-cache@c5e8f6fd27b493abfd6af230e6a5d4bf43d1d766 continue-on-error: true with: enable-apt: true