Skip to content

Commit 3936fbc

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 3936fbc

3 files changed

Lines changed: 123 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: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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 pr list \
25+
--repo "${{ github.repository }}" \
26+
--head "${{ github.event.workflow_run.head_branch }}" \
27+
--state open \
28+
--json number \
29+
--jq '.[0].number // empty')
30+
if [ -z "$PR_NUMBER" ]; then
31+
echo "Not a PR, skipping"
32+
fi
33+
echo "number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
34+
35+
- name: Check for package label
36+
id: label
37+
if: steps.pr.outputs.number
38+
env:
39+
GH_TOKEN: ${{ github.token }}
40+
run: |
41+
HAS_LABEL=$(gh api \
42+
"repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}" \
43+
--jq '[.labels[].name] | any(. == "package-pr")')
44+
echo "has_label=${HAS_LABEL}" >> "$GITHUB_OUTPUT"
45+
46+
- name: Download artifact
47+
if: steps.label.outputs.has_label == 'true'
48+
uses: actions/download-artifact@v4
49+
with:
50+
name: npm-package
51+
run-id: ${{ github.event.workflow_run.id }}
52+
github-token: ${{ github.token }}
53+
54+
- name: Upload package to a temporary release
55+
if: steps.label.outputs.has_label == 'true'
56+
env:
57+
GH_TOKEN: ${{ github.token }}
58+
run: |
59+
TAG="pr-${{ steps.pr.outputs.number }}"
60+
gh release delete "$TAG" --repo "${{ github.repository }}" --yes --cleanup-tag || true
61+
gh release create "$TAG" *.tgz \
62+
--repo "${{ github.repository }}" \
63+
--target "${{ github.event.workflow_run.head_sha }}" \
64+
--prerelease \
65+
--title "PR #${{ steps.pr.outputs.number }}" \
66+
--notes "Test package for PR #${{ steps.pr.outputs.number }}"
67+
68+
- name: Update PR description with package link
69+
if: steps.label.outputs.has_label == 'true'
70+
env:
71+
GH_TOKEN: ${{ github.token }}
72+
run: |
73+
TAG="pr-${{ steps.pr.outputs.number }}"
74+
ASSET_URL=$(gh release view "$TAG" --repo "${{ github.repository }}" --json assets --jq '.assets[0].url')
75+
76+
BODY=$(gh pr view "${{ steps.pr.outputs.number }}" --repo "${{ github.repository }}" --json body --jq '.body // ""')
77+
78+
MARKER_START="<!-- package-link-start -->"
79+
MARKER_END="<!-- package-link-end -->"
80+
PACKAGE_BLOCK="${MARKER_START}
81+
### Latest PR package
82+
83+
${ASSET_URL}
84+
${MARKER_END}"
85+
86+
if echo "$BODY" | grep -q "$MARKER_START"; then
87+
BODY=$(echo "$BODY" | awk -v start="$MARKER_START" -v block="$PACKAGE_BLOCK" '
88+
$0 ~ start { print block; skip=1; next }
89+
skip && /<!-- package-link-end -->/ { skip=0; next }
90+
!skip { print }
91+
')
92+
else
93+
BODY="${BODY}
94+
95+
${PACKAGE_BLOCK}"
96+
fi
97+
98+
echo "$BODY" > /tmp/pr_body.txt
99+
gh pr edit "${{ steps.pr.outputs.number }}" --repo "${{ github.repository }}" --body-file /tmp/pr_body.txt

0 commit comments

Comments
 (0)