Skip to content

Commit 9abebe1

Browse files
arbrandesclaude
andcommitted
feat: add workflows to publish PR packages for testing
When a PR is labeled "package-pr", the CI workflow uploads the npm pack tarball as an artifact. A separate workflow_run-triggered workflow then attaches it to a GitHub release tagged pr-<number> and updates the PR description with the download link. A cleanup workflow deletes the release when the PR is closed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7e13eb9 commit 9abebe1

3 files changed

Lines changed: 120 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,9 @@ jobs:
3333
run: npm run test
3434
- name: Build Test Site
3535
run: cd test-site; npm run build
36+
- name: Upload package artifact
37+
if: contains(github.event.pull_request.labels.*.name, 'package-pr')
38+
uses: actions/upload-artifact@v4
39+
with:
40+
name: npm-package
41+
path: 'pack/*.tgz'
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Package PR Cleanup
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
7+
jobs:
8+
cleanup:
9+
if: contains(github.event.pull_request.labels.*.name, 'package-pr')
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Delete PR release
14+
env:
15+
GH_TOKEN: ${{ github.token }}
16+
run: |
17+
TAG="pr-${{ github.event.pull_request.number }}"
18+
gh release delete "$TAG" --repo "${{ github.repository }}" --yes --cleanup-tag || true

.github/workflows/package-pr.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Package PR
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Default CI"]
6+
types: [completed]
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
actions: read
12+
13+
jobs:
14+
package:
15+
if: github.event.workflow_run.conclusion == 'success'
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Get PR number
20+
id: pr
21+
env:
22+
GH_TOKEN: ${{ github.token }}
23+
run: |
24+
PR_NUMBER=$(gh api \
25+
"repos/${{ github.repository }}/commits/${{ github.event.workflow_run.head_sha }}/pulls" \
26+
--jq '.[0].number // empty')
27+
if [ -z "$PR_NUMBER" ]; then
28+
echo "Not a PR, skipping"
29+
fi
30+
echo "number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
31+
32+
- name: Check for package label
33+
id: label
34+
if: steps.pr.outputs.number
35+
env:
36+
GH_TOKEN: ${{ github.token }}
37+
run: |
38+
HAS_LABEL=$(gh api \
39+
"repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}" \
40+
--jq '[.labels[].name] | any(. == "package-pr")')
41+
echo "has_label=${HAS_LABEL}" >> "$GITHUB_OUTPUT"
42+
43+
- name: Download artifact
44+
if: steps.label.outputs.has_label == 'true'
45+
uses: actions/download-artifact@v4
46+
with:
47+
name: npm-package
48+
run-id: ${{ github.event.workflow_run.id }}
49+
github-token: ${{ github.token }}
50+
51+
- name: Upload package to a temporary release
52+
if: steps.label.outputs.has_label == 'true'
53+
env:
54+
GH_TOKEN: ${{ github.token }}
55+
run: |
56+
TAG="pr-${{ steps.pr.outputs.number }}"
57+
gh release delete "$TAG" --repo "${{ github.repository }}" --yes --cleanup-tag || true
58+
gh release create "$TAG" *.tgz \
59+
--repo "${{ github.repository }}" \
60+
--target "${{ github.event.workflow_run.head_sha }}" \
61+
--prerelease \
62+
--title "PR #${{ steps.pr.outputs.number }}" \
63+
--notes "Test package for PR #${{ steps.pr.outputs.number }}"
64+
65+
- name: Update PR description with package link
66+
if: steps.label.outputs.has_label == 'true'
67+
env:
68+
GH_TOKEN: ${{ github.token }}
69+
run: |
70+
TAG="pr-${{ steps.pr.outputs.number }}"
71+
ASSET_URL=$(gh release view "$TAG" --repo "${{ github.repository }}" --json assets --jq '.assets[0].url')
72+
73+
BODY=$(gh pr view "${{ steps.pr.outputs.number }}" --repo "${{ github.repository }}" --json body --jq '.body // ""')
74+
75+
MARKER_START="<!-- package-link-start -->"
76+
MARKER_END="<!-- package-link-end -->"
77+
PACKAGE_BLOCK="${MARKER_START}
78+
### Latest PR package
79+
80+
${ASSET_URL}
81+
${MARKER_END}"
82+
83+
if echo "$BODY" | grep -q "$MARKER_START"; then
84+
BODY=$(echo "$BODY" | awk -v start="$MARKER_START" -v block="$PACKAGE_BLOCK" '
85+
$0 ~ start { print block; skip=1; next }
86+
skip && /<!-- package-link-end -->/ { skip=0; next }
87+
!skip { print }
88+
')
89+
else
90+
BODY="${BODY}
91+
92+
${PACKAGE_BLOCK}"
93+
fi
94+
95+
echo "$BODY" > /tmp/pr_body.txt
96+
gh pr edit "${{ steps.pr.outputs.number }}" --repo "${{ github.repository }}" --body-file /tmp/pr_body.txt

0 commit comments

Comments
 (0)