From 5274f158bdde42b0e79192e15e9840e6e2479bf3 Mon Sep 17 00:00:00 2001 From: "H.E. Pennypacker" <115990865+pennypacker-he@users.noreply.github.com> Date: Thu, 16 Jul 2026 22:53:40 +0000 Subject: [PATCH] [skip-release] Make native build timeout configurable --- .github/workflows/build-push.yaml | 13 ++++++++++++- ci/github/build_push_contract_test.go | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-push.yaml b/.github/workflows/build-push.yaml index 0d3ed99..4443a0f 100644 --- a/.github/workflows/build-push.yaml +++ b/.github/workflows/build-push.yaml @@ -35,6 +35,11 @@ on: type: string default: "" description: "Additional non-secret, newline-separated Docker build arguments" + build-timeout-minutes: + required: false + type: number + default: 30 + description: "Bounded timeout for each native image build; use 5 through 120 minutes" runners: required: false type: string @@ -102,7 +107,7 @@ jobs: - ubuntu-24.04-arm name: build-${{ matrix.runner }} runs-on: ${{ matrix.runner }} - timeout-minutes: 30 + timeout-minutes: ${{ inputs.build-timeout-minutes }} outputs: image-tag: ${{ steps.record-tag.outputs.tag }} steps: @@ -112,6 +117,7 @@ jobs: ADDITIONAL_GAR_REGISTRY: ${{ inputs.additional-gar-registry }} ADDITIONAL_IMAGE_NAMES: ${{ inputs.additional-image-names }} BUILD_CONTEXT: ${{ inputs.context }} + BUILD_TIMEOUT_MINUTES: ${{ inputs.build-timeout-minutes }} CALLER_REF: ${{ inputs.ref }} CERTIFICATE_IDENTITY: ${{ inputs.certificate-identity }} DOCKER_FILE: ${{ inputs.file }} @@ -138,6 +144,11 @@ jobs: echo "The runners compatibility input must remain the fixed LibOps hosted-runner pair" >&2 exit 1 fi + if [[ ! "$BUILD_TIMEOUT_MINUTES" =~ ^[0-9]+$ ]] || + ((BUILD_TIMEOUT_MINUTES < 5 || BUILD_TIMEOUT_MINUTES > 120)); then + echo "Native build timeout must be an integer from 5 through 120 minutes" >&2 + exit 1 + fi validate_repo_path() { local value="$1" local label="$2" diff --git a/ci/github/build_push_contract_test.go b/ci/github/build_push_contract_test.go index 6e0c1a7..1fc6220 100644 --- a/ci/github/build_push_contract_test.go +++ b/ci/github/build_push_contract_test.go @@ -115,6 +115,24 @@ func TestPublisherRunnersCannotBeCallerControlled(t *testing.T) { } } +func TestNativeBuildTimeoutIsBoundedCallerInput(t *testing.T) { + workflow := workflowSource(t) + inputs := stepBlock(t, workflow, " inputs:\n", " secrets:\n") + buildHeader := stepBlock(t, workflow, "jobs:\n build:\n", " outputs:\n") + validation := stepBlock(t, workflow, " - name: validate input\n", " - uses: actions/checkout@") + + for _, required := range []string{ + "build-timeout-minutes:\n", + "type: number", + "default: 30", + } { + requireContains(t, inputs, required) + } + requireContains(t, buildHeader, "timeout-minutes: ${{ inputs.build-timeout-minutes }}") + requireContains(t, validation, "BUILD_TIMEOUT_MINUTES: ${{ inputs.build-timeout-minutes }}") + requireContains(t, validation, "BUILD_TIMEOUT_MINUTES < 5 || BUILD_TIMEOUT_MINUTES > 120") +} + func TestDefaultImageNameReceivesCanonicalValidation(t *testing.T) { workflow := workflowSource(t) validation := stepBlock(t, workflow, " - name: validate input\n", " - uses: actions/checkout@")