Skip to content

Commit 547b8a3

Browse files
authored
github-action: add pr builder for easier testing (#178)
Adds a Github action to build binaries for easier testing of PRs. A comment will be added in the PR. Workflow runs on `pull_request_target` and has two jobs - build, comment. `comment` job needs issues:write permission due to which the workflow can run only when it is present on main. `build` job only has read permission to prevent insecure permissions Tested here: shwstppr#3 Signed-off-by: Abhishek Kumar <[email protected]>
1 parent 4673829 commit 547b8a3

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

.github/workflows/build-pr-cmk.yml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
name: Build cmk binaries on PR
19+
20+
on:
21+
pull_request_target:
22+
types: [opened, synchronize, reopened]
23+
24+
concurrency:
25+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
26+
cancel-in-progress: true
27+
28+
jobs:
29+
build:
30+
permissions:
31+
contents: read
32+
runs-on: ubuntu-24.04
33+
env:
34+
GITHUB_TOKEN: ""
35+
outputs:
36+
outcome: ${{ steps.meta.outputs.outcome }}
37+
artifact_url: ${{ steps.meta.outputs.artifact_url }}
38+
steps:
39+
- name: Checkout PR HEAD
40+
uses: actions/checkout@v4
41+
with:
42+
ref: ${{ github.event.pull_request.head.sha }}
43+
persist-credentials: false
44+
45+
- name: Set up Go
46+
uses: actions/setup-go@v5
47+
with:
48+
go-version: '1.22'
49+
50+
- name: Build dist
51+
id: build
52+
run: make dist
53+
continue-on-error: true
54+
55+
- name: Upload zipped dist artifact
56+
id: upload_artifact
57+
if: ${{ steps.build.outcome == 'success' }} # gate on build outcome
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: cmk-binaries.pr${{ github.event.pull_request.number }}
61+
path: dist/
62+
if-no-files-found: error
63+
retention-days: 10
64+
65+
- name: Expose build outcome & artifact link
66+
id: meta
67+
if: always()
68+
run: |
69+
echo "outcome=${{ steps.build.outcome }}" >> $GITHUB_OUTPUT
70+
echo "artifact_url=${{ steps.upload_artifact.outputs.artifact-url }}" >> $GITHUB_OUTPUT
71+
72+
comment:
73+
if: always()
74+
needs: build
75+
permissions:
76+
contents: read
77+
issues: write
78+
pull-requests: write
79+
runs-on: ubuntu-24.04
80+
steps:
81+
- name: Comment or update cmk build artifact on PR
82+
uses: actions/github-script@v7
83+
with:
84+
script: |
85+
const { execSync } = require('child_process');
86+
87+
const issue_number = context.payload.pull_request.number;
88+
const identifier = "cmk-build-artifact-comment";
89+
90+
const owner = context.payload.repository.owner.login; // base repo (pull_request_target)
91+
const repo = context.payload.repository.name;
92+
93+
const buildOutcome = "${{ needs.build.outputs.outcome }}";
94+
const artifactUrl = "${{ needs.build.outputs.artifact_url }}";
95+
const runId = "${{ github.run_id }}";
96+
97+
core.info(`Will comment on ${owner}/${repo}#${issue_number}`);
98+
core.info(`Outcome=${buildOutcome || '(empty)'} Artifact=${artifactUrl || '(none)'}`);
99+
100+
let body = `<!-- ${identifier} -->\n`;
101+
if (buildOutcome === 'success' && artifactUrl) {
102+
const expiryDate = execSync("date -d '+10 days' '+%B %d, %Y'").toString().trim();
103+
body += `✅ Build complete for PR #${issue_number}.\n\n`;
104+
body += `🔗 Download the [cmk binaries](${artifactUrl}) (expires on ${expiryDate})`;
105+
} else {
106+
body += `❌ Build failed for PR #${issue_number}.\n\n`;
107+
body += `See the run: https://github.com/${owner}/${repo}/actions/runs/${runId}`;
108+
}
109+
110+
const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number });
111+
const existing = comments.find(c => c.user.login === 'github-actions[bot]' && c.body.includes(identifier));
112+
113+
if (existing) {
114+
core.info(`Updating comment id ${existing.id}`);
115+
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
116+
} else {
117+
core.info(`Creating new comment`);
118+
await github.rest.issues.createComment({ owner, repo, issue_number, body });
119+
}
120+

0 commit comments

Comments
 (0)