From 6a7a20db4e2a96c9a318ff607898dd33b995078f Mon Sep 17 00:00:00 2001 From: Robusta Runner Date: Thu, 25 Dec 2025 11:55:29 +0000 Subject: [PATCH 1/7] Fix Docker build notification to comment on PRs instead of commits Add pull_request trigger so we get direct access to PR number via context.payload.pull_request. This ensures notifications link to the PR comment page rather than the commit comment page. Also adds concurrency control to prevent duplicate runs when both push and pull_request events fire for the same change. Signed-off-by: Robusta Runner --- .github/workflows/docker-dev-images.yaml | 41 ++++++++++++++++++------ 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docker-dev-images.yaml b/.github/workflows/docker-dev-images.yaml index 2e1e85286f..0004054958 100644 --- a/.github/workflows/docker-dev-images.yaml +++ b/.github/workflows/docker-dev-images.yaml @@ -4,6 +4,13 @@ on: push: branches: - '**' # Trigger on push to any branch + pull_request: + types: [opened, synchronize, reopened] + +# Prevent duplicate runs - cancel in-progress runs for the same ref +concurrency: + group: docker-build-${{ github.head_ref || github.ref }} + cancel-in-progress: true jobs: build: @@ -61,7 +68,6 @@ jobs: script: | const owner = context.repo.owner; const repo = context.repo.repo; - const branch = context.ref.replace('refs/heads/', ''); const sha = context.sha; const shortSha = `${{ steps.short_sha.outputs.sha_short }}`; @@ -100,15 +106,29 @@ jobs: '```', ].join('\n'); - const prs = await github.paginate(github.rest.pulls.list, { - owner, - repo, - state: 'open', - head: `${owner}:${branch}`, - }); + // Get PR number - either from pull_request event context or by searching + let issue_number = null; + + // If triggered by pull_request event, we have direct access to PR number + if (context.payload.pull_request) { + issue_number = context.payload.pull_request.number; + core.info(`Using PR number from pull_request event: #${issue_number}`); + } else { + // For push events, search for an open PR with matching head branch + const branch = context.ref.replace('refs/heads/', ''); + const prs = await github.paginate(github.rest.pulls.list, { + owner, + repo, + state: 'open', + head: `${owner}:${branch}`, + }); + if (prs.length > 0) { + issue_number = prs[0].number; + core.info(`Found PR by branch search: #${issue_number}`); + } + } - if (prs.length > 0) { - const issue_number = prs[0].number; + if (issue_number) { const existingComments = await github.paginate(github.rest.issues.listComments, { owner, repo, @@ -134,6 +154,7 @@ jobs: core.info(`Commented on PR #${issue_number}`); } } else { + // No PR found - fall back to commit comment (e.g., direct push to main) const commitComments = await github.paginate(github.rest.repos.listCommentsForCommit, { owner, repo, @@ -156,6 +177,6 @@ jobs: commit_sha: sha, body: message, }); - core.info('Commented on commit'); + core.info('Commented on commit (no PR found)'); } } From 9e7b75c49d8a1414055113fac1e0a8c04386d366 Mon Sep 17 00:00:00 2001 From: Robusta Runner Date: Thu, 25 Dec 2025 12:00:45 +0000 Subject: [PATCH 2/7] Remove push trigger, only build Docker images for PRs Simplify workflow to only trigger on pull_request events. This ensures notifications always go to the PR and removes the complex fallback logic for commit comments. Signed-off-by: Robusta Runner --- .github/workflows/docker-dev-images.yaml | 90 +++++------------------- 1 file changed, 19 insertions(+), 71 deletions(-) diff --git a/.github/workflows/docker-dev-images.yaml b/.github/workflows/docker-dev-images.yaml index 0004054958..151fd3f9e4 100644 --- a/.github/workflows/docker-dev-images.yaml +++ b/.github/workflows/docker-dev-images.yaml @@ -1,15 +1,12 @@ -name: Docker Build on Commit +name: Docker Build on PR on: - push: - branches: - - '**' # Trigger on push to any branch pull_request: types: [opened, synchronize, reopened] -# Prevent duplicate runs - cancel in-progress runs for the same ref +# Cancel in-progress runs for the same PR concurrency: - group: docker-build-${{ github.head_ref || github.ref }} + group: docker-build-${{ github.head_ref }} cancel-in-progress: true jobs: @@ -68,7 +65,6 @@ jobs: script: | const owner = context.repo.owner; const repo = context.repo.repo; - const sha = context.sha; const shortSha = `${{ steps.short_sha.outputs.sha_short }}`; const shortTag = `us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:${shortSha}`; @@ -106,77 +102,29 @@ jobs: '```', ].join('\n'); - // Get PR number - either from pull_request event context or by searching - let issue_number = null; + const issue_number = context.payload.pull_request.number; - // If triggered by pull_request event, we have direct access to PR number - if (context.payload.pull_request) { - issue_number = context.payload.pull_request.number; - core.info(`Using PR number from pull_request event: #${issue_number}`); - } else { - // For push events, search for an open PR with matching head branch - const branch = context.ref.replace('refs/heads/', ''); - const prs = await github.paginate(github.rest.pulls.list, { - owner, - repo, - state: 'open', - head: `${owner}:${branch}`, - }); - if (prs.length > 0) { - issue_number = prs[0].number; - core.info(`Found PR by branch search: #${issue_number}`); - } - } + const existingComments = await github.paginate(github.rest.issues.listComments, { + owner, + repo, + issue_number, + }); + const existing = existingComments.find(c => c.body?.includes(marker)); - if (issue_number) { - const existingComments = await github.paginate(github.rest.issues.listComments, { + if (existing) { + await github.rest.issues.updateComment({ owner, repo, - issue_number, + comment_id: existing.id, + body: message, }); - const existing = existingComments.find(c => c.body?.includes(marker)); - - if (existing) { - await github.rest.issues.updateComment({ - owner, - repo, - comment_id: existing.id, - body: message, - }); - core.info(`Updated existing PR comment #${existing.id}`); - } else { - await github.rest.issues.createComment({ - owner, - repo, - issue_number, - body: message, - }); - core.info(`Commented on PR #${issue_number}`); - } + core.info(`Updated existing PR comment #${existing.id}`); } else { - // No PR found - fall back to commit comment (e.g., direct push to main) - const commitComments = await github.paginate(github.rest.repos.listCommentsForCommit, { + await github.rest.issues.createComment({ owner, repo, - commit_sha: sha, + issue_number, + body: message, }); - const existing = commitComments.find(c => c.body?.includes(marker)); - - if (existing) { - await github.rest.repos.updateCommitComment({ - owner, - repo, - comment_id: existing.id, - body: message, - }); - core.info(`Updated existing commit comment #${existing.id}`); - } else { - await github.rest.repos.createCommitComment({ - owner, - repo, - commit_sha: sha, - body: message, - }); - core.info('Commented on commit (no PR found)'); - } + core.info(`Commented on PR #${issue_number}`); } From a01cee77af07b32d76542ac585769e5106432c0c Mon Sep 17 00:00:00 2001 From: Robusta Runner Date: Thu, 25 Dec 2025 15:40:35 +0000 Subject: [PATCH 3/7] Add build progress updates and duration to Docker image comments - Post "Building..." comment when build starts with link to logs - Update same comment when build completes with success/failure status - Show build duration (e.g., "built in 5m 32s") - Collapse copy commands in a
section for cleaner UX - Handle build failures with error message and link to logs Signed-off-by: Robusta Runner --- .github/workflows/docker-dev-images.yaml | 154 +++++++++++++++++------ 1 file changed, 115 insertions(+), 39 deletions(-) diff --git a/.github/workflows/docker-dev-images.yaml b/.github/workflows/docker-dev-images.yaml index 151fd3f9e4..a601e59ba6 100644 --- a/.github/workflows/docker-dev-images.yaml +++ b/.github/workflows/docker-dev-images.yaml @@ -21,6 +21,58 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Get short SHA + id: short_sha + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: Record start time + id: start_time + run: echo "start=$(date +%s)" >> $GITHUB_OUTPUT + + - name: Comment build started + uses: actions/github-script@v7 + with: + script: | + const owner = context.repo.owner; + const repo = context.repo.repo; + const shortSha = `${{ steps.short_sha.outputs.sha_short }}`; + const runUrl = `https://github.com/${owner}/${repo}/actions/runs/${{ github.run_id }}`; + const marker = ''; + + const message = [ + marker, + `🔨 **Building Docker image for \`${shortSha}\`...**`, + '', + `[View build logs](${runUrl})`, + ].join('\n'); + + const issue_number = context.payload.pull_request.number; + + const existingComments = await github.paginate(github.rest.issues.listComments, { + owner, + repo, + issue_number, + }); + const existing = existingComments.find(c => c.body?.includes(marker)); + + if (existing) { + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: existing.id, + body: message, + }); + core.info(`Updated existing PR comment #${existing.id}`); + } else { + await github.rest.issues.createComment({ + owner, + repo, + issue_number, + body: message, + }); + core.info(`Commented on PR #${issue_number}`); + } + - uses: google-github-actions/auth@v2 with: project_id: 'robusta-development' @@ -37,10 +89,6 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Get short SHA - id: short_sha - run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - - name: Build and push Docker image uses: docker/build-push-action@v6 with: @@ -60,47 +108,75 @@ jobs: echo " us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:${{ steps.short_sha.outputs.sha_short }}" - name: Comment with image details + if: always() uses: actions/github-script@v7 with: script: | const owner = context.repo.owner; const repo = context.repo.repo; const shortSha = `${{ steps.short_sha.outputs.sha_short }}`; - - const shortTag = `us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:${shortSha}`; - const registryLink = 'https://console.cloud.google.com/artifacts/docker/robusta-development/us-central1/temporary-builds/holmes?project=robusta-development'; - const marker = 'Dev Docker images are ready for this commit:'; - - const message = [ - marker, - '', - `- [${shortTag}](${registryLink})`, - '', - 'Use this tag to pull the image for testing.', - '', - '⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:', - '```bash', - 'gcloud auth configure-docker us-central1-docker.pkg.dev', - `docker pull ${shortTag}`, - `docker tag ${shortTag} me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:${shortSha}`, - `docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:${shortSha}`, - '```', - '', - 'Patch Helm values in one line (choose the chart you use):', - '- HolmesGPT chart:', - '```bash', - 'helm upgrade --install holmesgpt ./helm/holmes \\', - ' --set registry=me-west1-docker.pkg.dev/robusta-development/development \\', - ` --set image=holmes-dev:${shortSha}`, - '```', - '- Robusta wrapper chart:', - '```bash', - 'helm upgrade --install robusta robusta/robusta \\', - ' --reuse-values \\', - ' --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \\', - ` --set holmes.image=holmes-dev:${shortSha}`, - '```', - ].join('\n'); + const jobStatus = `${{ job.status }}`; + const runUrl = `https://github.com/${owner}/${repo}/actions/runs/${{ github.run_id }}`; + const marker = ''; + + // Calculate build duration + const startTime = parseInt(`${{ steps.start_time.outputs.start }}`); + const endTime = Math.floor(Date.now() / 1000); + const durationSecs = endTime - startTime; + const minutes = Math.floor(durationSecs / 60); + const seconds = durationSecs % 60; + const duration = minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`; + + let message; + if (jobStatus === 'success') { + const shortTag = `us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:${shortSha}`; + const registryLink = 'https://console.cloud.google.com/artifacts/docker/robusta-development/us-central1/temporary-builds/holmes?project=robusta-development'; + + message = [ + marker, + `✅ **Docker image ready for \`${shortSha}\`** (built in ${duration})`, + '', + `- [${shortTag}](${registryLink})`, + '', + 'Use this tag to pull the image for testing.', + '', + '
', + '📋 Copy commands', + '', + '⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:', + '```bash', + 'gcloud auth configure-docker us-central1-docker.pkg.dev', + `docker pull ${shortTag}`, + `docker tag ${shortTag} me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:${shortSha}`, + `docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:${shortSha}`, + '```', + '', + 'Patch Helm values in one line (choose the chart you use):', + '', + '**HolmesGPT chart:**', + '```bash', + 'helm upgrade --install holmesgpt ./helm/holmes \\', + ' --set registry=me-west1-docker.pkg.dev/robusta-development/development \\', + ` --set image=holmes-dev:${shortSha}`, + '```', + '', + '**Robusta wrapper chart:**', + '```bash', + 'helm upgrade --install robusta robusta/robusta \\', + ' --reuse-values \\', + ' --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \\', + ` --set holmes.image=holmes-dev:${shortSha}`, + '```', + '
', + ].join('\n'); + } else { + message = [ + marker, + `❌ **Docker build failed for \`${shortSha}\`** (after ${duration})`, + '', + `[View build logs](${runUrl})`, + ].join('\n'); + } const issue_number = context.payload.pull_request.number; From aa96027378279f3109503cef0fa1ec4f9ec2c4e2 Mon Sep 17 00:00:00 2001 From: Robusta Runner Date: Thu, 25 Dec 2025 16:18:01 +0000 Subject: [PATCH 4/7] Keep previous image visible during rebuilds When a new commit triggers a rebuild, preserve the previous image tag in the comment so users can still copy it while the new build runs. Signed-off-by: Robusta Runner --- .github/workflows/docker-dev-images.yaml | 32 ++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docker-dev-images.yaml b/.github/workflows/docker-dev-images.yaml index a601e59ba6..18e3f6e372 100644 --- a/.github/workflows/docker-dev-images.yaml +++ b/.github/workflows/docker-dev-images.yaml @@ -38,13 +38,7 @@ jobs: const shortSha = `${{ steps.short_sha.outputs.sha_short }}`; const runUrl = `https://github.com/${owner}/${repo}/actions/runs/${{ github.run_id }}`; const marker = ''; - - const message = [ - marker, - `🔨 **Building Docker image for \`${shortSha}\`...**`, - '', - `[View build logs](${runUrl})`, - ].join('\n'); + const registryLink = 'https://console.cloud.google.com/artifacts/docker/robusta-development/us-central1/temporary-builds/holmes?project=robusta-development'; const issue_number = context.payload.pull_request.number; @@ -55,6 +49,30 @@ jobs: }); const existing = existingComments.find(c => c.body?.includes(marker)); + // Extract previous image tag from existing comment if present + let previousImageSection = ''; + if (existing) { + const tagMatch = existing.body.match(/holmes:([a-f0-9]{7})/); + if (tagMatch && tagMatch[1] !== shortSha) { + const prevSha = tagMatch[1]; + const prevTag = `us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:${prevSha}`; + previousImageSection = [ + '', + '---', + `📦 **Previous image (\`${prevSha}\`)** - still available while building:`, + `- [${prevTag}](${registryLink})`, + ].join('\n'); + } + } + + const message = [ + marker, + `🔨 **Building Docker image for \`${shortSha}\`...**`, + '', + `[View build logs](${runUrl})`, + previousImageSection, + ].join('\n'); + if (existing) { await github.rest.issues.updateComment({ owner, From 5b273fa880c5972bd05c096908c84124654a2af6 Mon Sep 17 00:00:00 2001 From: Robusta Runner Date: Thu, 25 Dec 2025 16:20:41 +0000 Subject: [PATCH 5/7] Remove misleading text from previous image label Signed-off-by: Robusta Runner --- .github/workflows/docker-dev-images.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-dev-images.yaml b/.github/workflows/docker-dev-images.yaml index 18e3f6e372..cb39d38ec9 100644 --- a/.github/workflows/docker-dev-images.yaml +++ b/.github/workflows/docker-dev-images.yaml @@ -59,7 +59,7 @@ jobs: previousImageSection = [ '', '---', - `📦 **Previous image (\`${prevSha}\`)** - still available while building:`, + `📦 **Previous image (\`${prevSha}\`):**`, `- [${prevTag}](${registryLink})`, ].join('\n'); } From 2e1d361d0b29b4acf04933fc5d0c70820caaeeaa Mon Sep 17 00:00:00 2001 From: Robusta Runner Date: Thu, 25 Dec 2025 16:35:34 +0000 Subject: [PATCH 6/7] Reduce contents permission to read (least privilege) Signed-off-by: Robusta Runner --- .github/workflows/docker-dev-images.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-dev-images.yaml b/.github/workflows/docker-dev-images.yaml index cb39d38ec9..444857d720 100644 --- a/.github/workflows/docker-dev-images.yaml +++ b/.github/workflows/docker-dev-images.yaml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest permissions: - contents: 'write' + contents: 'read' id-token: 'write' pull-requests: 'write' From 0956a1a375148ac1b65626d78a591540bedab399 Mon Sep 17 00:00:00 2001 From: Robusta Runner Date: Thu, 25 Dec 2025 22:41:00 +0200 Subject: [PATCH 7/7] fix Signed-off-by: Robusta Runner --- .github/workflows/docker-dev-images.yaml | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/docker-dev-images.yaml b/.github/workflows/docker-dev-images.yaml index 444857d720..9791abdf36 100644 --- a/.github/workflows/docker-dev-images.yaml +++ b/.github/workflows/docker-dev-images.yaml @@ -61,6 +61,35 @@ jobs: '---', `📦 **Previous image (\`${prevSha}\`):**`, `- [${prevTag}](${registryLink})`, + '', + '
', + '📋 Copy commands', + '', + '⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:', + '```bash', + 'gcloud auth configure-docker us-central1-docker.pkg.dev', + `docker pull ${prevTag}`, + `docker tag ${prevTag} me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:${prevSha}`, + `docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:${prevSha}`, + '```', + '', + 'Patch Helm values in one line (choose the chart you use):', + '', + '**HolmesGPT chart:**', + '```bash', + 'helm upgrade --install holmesgpt ./helm/holmes \\\\', + ' --set registry=me-west1-docker.pkg.dev/robusta-development/development \\\\', + ` --set image=holmes-dev:${prevSha}`, + '```', + '', + '**Robusta wrapper chart:**', + '```bash', + 'helm upgrade --install robusta robusta/robusta \\\\', + ' --reuse-values \\\\', + ' --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \\\\', + ` --set holmes.image=holmes-dev:${prevSha}`, + '```', + '
', ].join('\n'); } }