Skip to content

Commit bc63947

Browse files
committed
Playground: Deploy Previews for Pull Requests
1 parent 47f7acc commit bc63947

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
name: Deploy Preview to Cloudflare Pages
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, closed]
6+
7+
concurrency:
8+
group: preview-${{ github.event.pull_request.number }}
9+
cancel-in-progress: true
10+
11+
jobs:
12+
build:
13+
if: github.event.action != 'closed'
14+
env:
15+
GH_TOKEN: ${{ github.token }}
16+
17+
runs-on: ubicloud-standard-2
18+
timeout-minutes: 10
19+
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- uses: actions/setup-node@v4
25+
with:
26+
node-version: 20
27+
cache: "yarn"
28+
29+
- name: Add LLVM apt Repo
30+
run: |-
31+
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
32+
sudo add-apt-repository "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-21 main"
33+
sudo apt update
34+
35+
- name: Install APT dependencies
36+
run: xargs sudo apt-get install -y --no-install-recommends < Aptfile
37+
38+
- name: Set up Ruby
39+
uses: ruby/setup-ruby@v1
40+
with:
41+
bundler-cache: true
42+
43+
- name: bundle install
44+
run: bundle install
45+
46+
- name: Render Templates
47+
run: bundle exec rake templates
48+
49+
- name: Compile Herb
50+
run: bundle exec rake make
51+
52+
- name: Yarn install
53+
run: yarn install --frozen-lockfile
54+
55+
- name: Build tailwind-class-sorter package
56+
run: yarn nx build @herb-tools/tailwind-class-sorter
57+
58+
- name: Build all JavaScript packages
59+
run: yarn build
60+
61+
- name: Build docs site
62+
run: cd docs && yarn build
63+
64+
- name: Upload docs artifact
65+
uses: actions/upload-artifact@v4
66+
with:
67+
name: docs-preview
68+
path: docs/.vitepress/dist
69+
retention-days: 1
70+
71+
deploy-preview:
72+
name: Deploy to Cloudflare Pages
73+
needs: build
74+
runs-on: ubuntu-latest
75+
76+
permissions:
77+
contents: read
78+
deployments: write
79+
pull-requests: write
80+
81+
steps:
82+
- name: Download docs artifact
83+
uses: actions/download-artifact@v4
84+
with:
85+
name: docs-preview
86+
path: dist
87+
88+
- name: Deploy to Cloudflare Pages
89+
id: deploy
90+
uses: cloudflare/pages-action@v1
91+
with:
92+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
93+
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
94+
projectName: herb-tools
95+
directory: dist
96+
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
97+
98+
- name: Add comment with preview URL
99+
uses: actions/github-script@v7
100+
with:
101+
script: |
102+
const previewUrl = '${{ steps.deploy.outputs.url }}';
103+
const comment = `## 🌿 Interactive Playground and Documentation Preview
104+
105+
A preview deployment has been built for this pull request. Try out the changes live in the interactive playground:
106+
107+
- **[Playground Preview](${previewUrl}/playground)**
108+
- **[Documentation Preview](${previewUrl})**
109+
- **[Website Preview](${previewUrl})**
110+
111+
---
112+
<sub>🌱 Grown from commit [\`${context.payload.pull_request.head.sha.substring(0, 7)}\`](https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${context.payload.pull_request.head.sha})</sub>`;
113+
114+
const { data: comments } = await github.rest.issues.listComments({
115+
owner: context.repo.owner,
116+
repo: context.repo.repo,
117+
issue_number: context.issue.number,
118+
});
119+
120+
const botComment = comments.find(comment =>
121+
comment.user.type === 'Bot' &&
122+
comment.body.includes('🌿 Interactive Playground and Documentation Preview')
123+
);
124+
125+
if (botComment) {
126+
await github.rest.issues.updateComment({
127+
owner: context.repo.owner,
128+
repo: context.repo.repo,
129+
comment_id: botComment.id,
130+
body: comment
131+
});
132+
} else {
133+
await github.rest.issues.createComment({
134+
owner: context.repo.owner,
135+
repo: context.repo.repo,
136+
issue_number: context.issue.number,
137+
body: comment
138+
});
139+
}
140+
141+
cleanup:
142+
name: Cleanup preview deployment
143+
if: github.event.action == 'closed'
144+
runs-on: ubuntu-latest
145+
146+
permissions:
147+
pull-requests: write
148+
149+
steps:
150+
- name: Delete Cloudflare Pages deployment
151+
run: |
152+
DEPLOYMENTS=$(curl -s -X GET \
153+
"https://api.cloudflare.com/client/v4/accounts/${{ secrets.CLOUDFLARE_ACCOUNT_ID }}/pages/projects/herb-tools/deployments" \
154+
-H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \
155+
-H "Content-Type: application/json")
156+
157+
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
158+
DEPLOYMENT_ID=$(echo "$DEPLOYMENTS" | jq -r ".result[] | select(.deployment_trigger.metadata.branch == \"$BRANCH_NAME\") | .id" | head -n 1)
159+
160+
if [ -n "$DEPLOYMENT_ID" ]; then
161+
echo "Deleting deployment $DEPLOYMENT_ID for branch $BRANCH_NAME"
162+
curl -X DELETE \
163+
"https://api.cloudflare.com/client/v4/accounts/${{ secrets.CLOUDFLARE_ACCOUNT_ID }}/pages/projects/herb-tools/deployments/$DEPLOYMENT_ID" \
164+
-H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \
165+
-H "Content-Type: application/json"
166+
else
167+
echo "No deployment found for branch $BRANCH_NAME"
168+
fi
169+
170+
- name: Update PR comment
171+
uses: actions/github-script@v7
172+
with:
173+
script: |
174+
const { data: comments } = await github.rest.issues.listComments({
175+
owner: context.repo.owner,
176+
repo: context.repo.repo,
177+
issue_number: context.issue.number,
178+
});
179+
180+
const botComment = comments.find(comment =>
181+
comment.user.type === 'Bot' &&
182+
comment.body.includes('🌿 Interactive Playground and Documentation Preview')
183+
);
184+
185+
if (botComment) {
186+
const updatedComment = botComment.body + '\n\n---\n\n✅ Preview deployment has been cleaned up.';
187+
await github.rest.issues.updateComment({
188+
owner: context.repo.owner,
189+
repo: context.repo.repo,
190+
comment_id: botComment.id,
191+
body: updatedComment
192+
});
193+
}

0 commit comments

Comments
 (0)