This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack-cloudmonkey.git
The following commit(s) were added to refs/heads/main by this push:
new 17afc27 Checkout base branch instead of PR head in build workflow
(#204)
17afc27 is described below
commit 17afc27c87e80c433d955fa391d4d6dbc3865a82
Author: Pearl Dsilva <[email protected]>
AuthorDate: Tue Feb 17 08:54:32 2026 -0500
Checkout base branch instead of PR head in build workflow (#204)
---
.github/workflows/build-pr-cmk.yml | 55 +----------
.github/workflows/comment-pr-build.yml | 165 +++++++++++++++++++++++++++++++++
2 files changed, 167 insertions(+), 53 deletions(-)
diff --git a/.github/workflows/build-pr-cmk.yml
b/.github/workflows/build-pr-cmk.yml
index c95d59a..d6f97d0 100644
--- a/.github/workflows/build-pr-cmk.yml
+++ b/.github/workflows/build-pr-cmk.yml
@@ -18,7 +18,7 @@
name: Build cmk binaries on PR
on:
- pull_request_target:
+ pull_request:
types: [opened, synchronize, reopened]
concurrency:
@@ -36,10 +36,9 @@ jobs:
outcome: ${{ steps.meta.outputs.outcome }}
artifact_url: ${{ steps.meta.outputs.artifact_url }}
steps:
- - name: Checkout PR HEAD
+ - name: Checkout PR code
uses: actions/checkout@v4
with:
- ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Set up Go
@@ -68,53 +67,3 @@ jobs:
run: |
echo "outcome=${{ steps.build.outcome }}" >> $GITHUB_OUTPUT
echo "artifact_url=${{ steps.upload_artifact.outputs.artifact-url
}}" >> $GITHUB_OUTPUT
-
- comment:
- if: always()
- needs: build
- permissions:
- contents: read
- issues: write
- pull-requests: write
- runs-on: ubuntu-24.04
- steps:
- - name: Comment or update cmk build artifact on PR
- uses: actions/github-script@v7
- with:
- script: |
- const { execSync } = require('child_process');
-
- const issue_number = context.payload.pull_request.number;
- const identifier = "cmk-build-artifact-comment";
-
- const owner = context.payload.repository.owner.login; // base repo
(pull_request_target)
- const repo = context.payload.repository.name;
-
- const buildOutcome = "${{ needs.build.outputs.outcome }}";
- const artifactUrl = "${{ needs.build.outputs.artifact_url }}";
- const runId = "${{ github.run_id }}";
-
- core.info(`Will comment on ${owner}/${repo}#${issue_number}`);
- core.info(`Outcome=${buildOutcome || '(empty)'}
Artifact=${artifactUrl || '(none)'}`);
-
- let body = `<!-- ${identifier} -->\n`;
- if (buildOutcome === 'success' && artifactUrl) {
- const expiryDate = execSync("date -d '+10 days' '+%B %d,
%Y'").toString().trim();
- body += `✅ Build complete for PR #${issue_number}.\n\n`;
- body += `🔗 Download the [cmk binaries](${artifactUrl}) (expires
on ${expiryDate})`;
- } else {
- body += `❌ Build failed for PR #${issue_number}.\n\n`;
- body += `See the run:
https://github.com/${owner}/${repo}/actions/runs/${runId}`;
- }
-
- const { data: comments } = await github.rest.issues.listComments({
owner, repo, issue_number });
- const existing = comments.find(c => c.user.login ===
'github-actions[bot]' && c.body.includes(identifier));
-
- if (existing) {
- core.info(`Updating comment id ${existing.id}`);
- await github.rest.issues.updateComment({ owner, repo,
comment_id: existing.id, body });
- } else {
- core.info(`Creating new comment`);
- await github.rest.issues.createComment({ owner, repo,
issue_number, body });
- }
-
diff --git a/.github/workflows/comment-pr-build.yml
b/.github/workflows/comment-pr-build.yml
new file mode 100644
index 0000000..661cdef
--- /dev/null
+++ b/.github/workflows/comment-pr-build.yml
@@ -0,0 +1,165 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Comment on PR build results
+
+on:
+ workflow_run:
+ workflows: ["Build cmk binaries on PR"]
+ types:
+ - completed
+
+permissions:
+ contents: read
+ issues: write
+ pull-requests: write
+ actions: read
+
+jobs:
+ comment:
+ runs-on: ubuntu-24.04
+ if: >
+ github.event.workflow_run.event == 'pull_request'
+ steps:
+ - name: Download artifact metadata
+ uses: actions/github-script@v7
+ id: artifact-metadata
+ with:
+ script: |
+ const artifacts = await
github.rest.actions.listWorkflowRunArtifacts({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: context.payload.workflow_run.id,
+ });
+
+ const prArtifact = artifacts.data.artifacts.find(a =>
a.name.startsWith('cmk-binaries.pr'));
+
+ if (prArtifact) {
+ const prNumber = prArtifact.name.match(/pr(\d+)/)?.[1];
+ return {
+ artifact_url: prArtifact.archive_download_url,
+ pr_number: prNumber,
+ conclusion: context.payload.workflow_run.conclusion
+ };
+ }
+
+ return {
+ pr_number: null,
+ conclusion: context.payload.workflow_run.conclusion
+ };
+
+ - name: Get PR number from workflow run
+ id: get-pr
+ uses: actions/github-script@v7
+ env:
+ METADATA: ${{ steps.artifact-metadata.outputs.result }}
+ with:
+ script: |
+ // Primary source: PRs attached to the workflow_run (for
pull_request-triggered runs)
+ const runPRs = context.payload.workflow_run.pull_requests;
+ if (runPRs && runPRs.length > 0) {
+ return runPRs[0].number;
+ }
+ // Fallback 1: PR number discovered from artifact metadata
+ let metadata = {};
+ if (process.env.METADATA) {
+ try {
+ metadata = JSON.parse(process.env.METADATA);
+ } catch (e) {
+ core.warning(`Failed to parse artifact metadata:
${e.message}`);
+ }
+ }
+ if (metadata.pr_number) {
+ return metadata.pr_number;
+ }
+ // Fallback 2: look up PRs associated with the workflow run head
SHA
+ const associated = await
github.rest.repos.listPullRequestsAssociatedWithCommit({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ commit_sha: context.payload.workflow_run.head_sha,
+ });
+ if (associated.data.length > 0) {
+ return associated.data[0].number;
+ }
+ return null;
+
+ - name: Comment or update build result on PR
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const { execSync } = require('child_process');
+ const prNumber = ${{ steps.get-pr.outputs.result }};
+
+ if (!prNumber) {
+ core.warning('Could not determine PR number, skipping comment');
+ return;
+ }
+
+ const identifier = "cmk-build-artifact-comment";
+ const owner = context.repo.owner;
+ const repo = context.repo.repo;
+ const conclusion = '${{ github.event.workflow_run.conclusion }}';
+ const runId = '${{ github.event.workflow_run.id }}';
+ const runUrl =
`https://github.com/${owner}/${repo}/actions/runs/${runId}`;
+
+ core.info(`Commenting on PR #${prNumber}`);
+ core.info(`Build conclusion: ${conclusion}`);
+
+ let body = `<!-- ${identifier} -->\n`;
+
+ if (conclusion === 'success') {
+ const expiryDate = execSync("date -d '+10 days' '+%B %d,
%Y'").toString().trim();
+ body += `✅ Build complete for PR #${prNumber}.\n\n`;
+ body += `📦 Binary artifacts are available in the [workflow
run](${runUrl}) (expires on ${expiryDate}).\n\n`;
+ body += `> **Note:** Download artifacts by clicking on the
workflow run link above, then scroll to the "Artifacts" section.\n`;
+ body += `> _Artifacts from PR builds are for testing only and
may contain unreviewed, malicious code._`;
+ } else if (conclusion === 'failure') {
+ body += `❌ Build failed for PR #${prNumber}.\n\n`;
+ body += `See the [workflow run](${runUrl}) for details.`;
+ } else {
+ body += `⚠️ Build ${conclusion} for PR #${prNumber}.\n\n`;
+ body += `See the [workflow run](${runUrl}) for details.`;
+ }
+
+ const { data: comments } = await github.rest.issues.listComments({
+ owner,
+ repo,
+ issue_number: prNumber
+ });
+
+ const existing = comments.find(c =>
+ c.user.login === 'github-actions[bot]' &&
+ c.body.includes(identifier)
+ );
+
+ if (existing) {
+ core.info(`Updating existing comment id ${existing.id}`);
+ await github.rest.issues.updateComment({
+ owner,
+ repo,
+ comment_id: existing.id,
+ body
+ });
+ } else {
+ core.info(`Creating new comment`);
+ await github.rest.issues.createComment({
+ owner,
+ repo,
+ issue_number: prNumber,
+ body
+ });
+ }