From 9b9bc4b905c1bf1ef622d2ec6f0c0fdf0b2f3dc9 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 13 Jan 2026 14:19:22 -0500 Subject: [PATCH 1/5] Add a github action to get the image from ddbuild --- .../publish-serverless-init-to-ghcr.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/publish-serverless-init-to-ghcr.yml diff --git a/.github/workflows/publish-serverless-init-to-ghcr.yml b/.github/workflows/publish-serverless-init-to-ghcr.yml new file mode 100644 index 000000000..62dee0b06 --- /dev/null +++ b/.github/workflows/publish-serverless-init-to-ghcr.yml @@ -0,0 +1,81 @@ +name: Publish serverless-init to GHCR + +on: + workflow_dispatch: + inputs: + source_image: + description: 'Source image from registry.ddbuild.io (e.g., registry.ddbuild.io/ci/datadog-agent/serverless-init:1.7.8)' + required: true + type: string + version: + description: 'Version tag (e.g., 1.7.8 or 1.7.8-rc1)' + required: true + type: string + image_suffix: + description: 'Image suffix (empty for standard, -alpine for alpine)' + required: false + type: string + default: '' + pipeline_id: + description: 'GitLab pipeline ID' + required: true + type: string + is_latest: + description: 'Tag as latest (true for prod releases, false for RCs)' + required: true + type: boolean + default: false + +permissions: + packages: write + contents: read + +jobs: + publish-to-ghcr: + runs-on: ubuntu-latest + steps: + - name: Install crane + run: | + cd /tmp + wget https://github.com/google/go-containerregistry/releases/download/v0.20.2/go-containerregistry_Linux_x86_64.tar.gz + tar -xzf go-containerregistry_Linux_x86_64.tar.gz + sudo mv crane /usr/local/bin/ + crane version + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Copy image to GHCR + run: | + SOURCE_IMAGE="${{ inputs.source_image }}" + VERSION="${{ inputs.version }}" + IMAGE_SUFFIX="${{ inputs.image_suffix }}" + PIPELINE_ID="${{ inputs.pipeline_id }}" + IS_LATEST="${{ inputs.is_latest }}" + + DEST_BASE="ghcr.io/datadog/datadog-lambda-extension/serverless-init" + + echo "📦 Publishing serverless-init image to GHCR" + echo " Source: ${SOURCE_IMAGE}" + echo " Destinations:" + echo " - ${DEST_BASE}:${VERSION}${IMAGE_SUFFIX}" + echo " - ${DEST_BASE}:v${PIPELINE_ID}${IMAGE_SUFFIX}" + + # Copy with version tag + crane copy ${SOURCE_IMAGE} ${DEST_BASE}:${VERSION}${IMAGE_SUFFIX} + + # Tag for pipeline ID + crane tag ${DEST_BASE}:${VERSION}${IMAGE_SUFFIX} v${PIPELINE_ID}${IMAGE_SUFFIX} + + # Tag as latest if this is a production release + if [ "$IS_LATEST" = "true" ]; then + echo " - ${DEST_BASE}:latest${IMAGE_SUFFIX}" + crane tag ${DEST_BASE}:${VERSION}${IMAGE_SUFFIX} latest${IMAGE_SUFFIX} + fi + + echo "✅ Successfully published image to GHCR!" + echo "📍 View at: https://github.com/DataDog/datadog-lambda-extension/pkgs/container/datadog-lambda-extension%2Fserverless-init" \ No newline at end of file From 9cbbe262c42176bde99501f7a2e7f2f5af282be7 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 13 Jan 2026 14:45:19 -0500 Subject: [PATCH 2/5] Only give permissions for github workflows --- .github/CODEOWNERS | 3 +++ .../serverless-init-ci-publish.sts.yaml | 17 +++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..85aa4636c --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# DD Octo STS trust policies require team approval +# See: https://datadoghq.atlassian.net/wiki/spaces/SECENG/pages/5138645099 +.github/chainguard/serverless-init-ci-publish.sts.yaml @DataDog/serverless-monitoring \ No newline at end of file diff --git a/.github/chainguard/serverless-init-ci-publish.sts.yaml b/.github/chainguard/serverless-init-ci-publish.sts.yaml index 07d915ec5..6b6d8d568 100644 --- a/.github/chainguard/serverless-init-ci-publish.sts.yaml +++ b/.github/chainguard/serverless-init-ci-publish.sts.yaml @@ -1,24 +1,25 @@ # DD Octo STS Trust Policy for serverless-init-ci GitLab pipeline # -# This policy allows the serverless-init-ci GitLab pipeline to publish -# serverless-init images to GitHub Container Registry (GHCR). +# This policy allows the serverless-init-ci GitLab pipeline to trigger +# GitHub Actions workflows that publish serverless-init images to GHCR. # # Reference: https://datadoghq.atlassian.net/wiki/spaces/SECENG/pages/5138645099 # Pipeline: https://gitlab.ddbuild.io/DataDog/serverless-init-ci issuer: https://gitlab.ddbuild.io -# Subject pattern matches the serverless-init-ci repo on any branch or tag +# Subject pattern matches the serverless-init-ci repo on any protected branch or tag subject_pattern: "project_path:DataDog/serverless-init-ci:ref_type:(branch|tag):ref:.*" -# Allow all branches and tags for building RC and prod images +# Only allow protected branches and tags (security control) claim_pattern: project_path: "DataDog/serverless-init-ci" ref_type: "^(branch|tag)$" - pipeline_source: "^(web|pipeline|push)$" + ref_protected: "true" + pipeline_source: "^(web|pipeline)$" ci_config_ref_uri: "^gitlab\\.ddbuild\\.io/DataDog/serverless-init-ci//\\.gitlab-ci\\.yml@refs/(heads|tags)/.*$" -# Minimal permissions: only write packages to GHCR +# Minimal permissions: only trigger GitHub Actions workflows +# The workflow itself uses GITHUB_TOKEN for GHCR access permissions: - packages: write - metadata: read \ No newline at end of file + actions: write \ No newline at end of file From 4692869199a09bf11600418fa42744cdefb6f913 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 13 Jan 2026 15:34:20 -0500 Subject: [PATCH 3/5] Fix codeowners --- .github/CODEOWNERS | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 85aa4636c..9a3b9a468 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,2 @@ -# DD Octo STS trust policies require team approval -# See: https://datadoghq.atlassian.net/wiki/spaces/SECENG/pages/5138645099 -.github/chainguard/serverless-init-ci-publish.sts.yaml @DataDog/serverless-monitoring \ No newline at end of file +.github/chainguard/serverless-init-ci-publish.sts.yaml @DataDog/serverless +.github/publish-serverless-init-to-ghcr.yaml @DataDog/serverless \ No newline at end of file From 215edba9877773c407da34c8c493405148b7a33b Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 13 Jan 2026 15:53:48 -0500 Subject: [PATCH 4/5] Add long running retry for getting public image --- .../publish-serverless-init-to-ghcr.yml | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-serverless-init-to-ghcr.yml b/.github/workflows/publish-serverless-init-to-ghcr.yml index 62dee0b06..dabdddc35 100644 --- a/.github/workflows/publish-serverless-init-to-ghcr.yml +++ b/.github/workflows/publish-serverless-init-to-ghcr.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: source_image: - description: 'Source image from registry.ddbuild.io (e.g., registry.ddbuild.io/ci/datadog-agent/serverless-init:1.7.8)' + description: 'Source image from registry.datadoghq.com (e.g., registry.datadoghq.com/serverless-init:1.7.8)' required: true type: string version: @@ -49,6 +49,33 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Wait for image availability + run: | + SOURCE_IMAGE="${{ inputs.source_image }}" + MAX_ATTEMPTS=20 + RETRY_DELAY=30 + # Maximum wait time: 20 attempts × 30s = 600s (10 minutes) + + echo "⏳ Waiting for image to be available: ${SOURCE_IMAGE}" + echo "Will check every ${RETRY_DELAY}s for up to $((MAX_ATTEMPTS * RETRY_DELAY))s" + + for i in $(seq 1 $MAX_ATTEMPTS); do + echo "Attempt $i/$MAX_ATTEMPTS: Checking if image exists..." + + if crane manifest ${SOURCE_IMAGE} >/dev/null 2>&1; then + echo "✅ Image is available!" + exit 0 + fi + + if [ $i -lt $MAX_ATTEMPTS ]; then + echo "⏳ Image not yet available, waiting ${RETRY_DELAY}s..." + sleep $RETRY_DELAY + fi + done + + echo "❌ Image did not become available after $((MAX_ATTEMPTS * RETRY_DELAY))s" + exit 1 + - name: Copy image to GHCR run: | SOURCE_IMAGE="${{ inputs.source_image }}" @@ -65,8 +92,29 @@ jobs: echo " - ${DEST_BASE}:${VERSION}${IMAGE_SUFFIX}" echo " - ${DEST_BASE}:v${PIPELINE_ID}${IMAGE_SUFFIX}" - # Copy with version tag - crane copy ${SOURCE_IMAGE} ${DEST_BASE}:${VERSION}${IMAGE_SUFFIX} + # Copy with version tag (with retry logic) + # Maximum retry duration: 3 attempts with 10s delays between retries + # This workflow is triggered in parallel with the publish attempt to registry.datadoghq.com + # Registry.datadoghq.com should normally need about ~30 seconds to recieve the new image + MAX_COPY_ATTEMPTS=3 + COPY_RETRY_DELAY=10 + + for i in $(seq 1 $MAX_COPY_ATTEMPTS); do + echo "Copying image (attempt $i/$MAX_COPY_ATTEMPTS)..." + + if crane copy ${SOURCE_IMAGE} ${DEST_BASE}:${VERSION}${IMAGE_SUFFIX}; then + echo "✅ Image copied successfully!" + break + fi + + if [ $i -lt $MAX_COPY_ATTEMPTS ]; then + echo "⚠️ Copy failed, retrying in ${COPY_RETRY_DELAY}s..." + sleep $COPY_RETRY_DELAY + else + echo "❌ Failed to copy image after $MAX_COPY_ATTEMPTS attempts" + exit 1 + fi + done # Tag for pipeline ID crane tag ${DEST_BASE}:${VERSION}${IMAGE_SUFFIX} v${PIPELINE_ID}${IMAGE_SUFFIX} From 63001b880281de478af8929588861bb2705b01fd Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 13 Jan 2026 16:13:33 -0500 Subject: [PATCH 5/5] Add yaml end line --- .github/chainguard/serverless-init-ci-publish.sts.yaml | 2 +- .github/workflows/publish-serverless-init-to-ghcr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/chainguard/serverless-init-ci-publish.sts.yaml b/.github/chainguard/serverless-init-ci-publish.sts.yaml index 6b6d8d568..30ce1176a 100644 --- a/.github/chainguard/serverless-init-ci-publish.sts.yaml +++ b/.github/chainguard/serverless-init-ci-publish.sts.yaml @@ -22,4 +22,4 @@ claim_pattern: # Minimal permissions: only trigger GitHub Actions workflows # The workflow itself uses GITHUB_TOKEN for GHCR access permissions: - actions: write \ No newline at end of file + actions: write diff --git a/.github/workflows/publish-serverless-init-to-ghcr.yml b/.github/workflows/publish-serverless-init-to-ghcr.yml index dabdddc35..e8576549a 100644 --- a/.github/workflows/publish-serverless-init-to-ghcr.yml +++ b/.github/workflows/publish-serverless-init-to-ghcr.yml @@ -126,4 +126,4 @@ jobs: fi echo "✅ Successfully published image to GHCR!" - echo "📍 View at: https://github.com/DataDog/datadog-lambda-extension/pkgs/container/datadog-lambda-extension%2Fserverless-init" \ No newline at end of file + echo "📍 View at: https://github.com/DataDog/datadog-lambda-extension/pkgs/container/datadog-lambda-extension%2Fserverless-init"