Skip to content

Commit b2b4822

Browse files
authored
ci: create script to update preview comments (#48)
1 parent d165cbb commit b2b4822

File tree

4 files changed

+204
-31
lines changed

4 files changed

+204
-31
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
name: "Publish Fern Documentation"
2+
description: "Generates and publishes Fern documentation with deployment tracking"
3+
4+
inputs:
5+
github-token:
6+
description: "GitHub token for creating deployments"
7+
required: true
8+
fern-token:
9+
description: "Fern API token for publishing docs"
10+
required: true
11+
environment:
12+
description: "Deployment environment name (e.g. docs-preview, docs-production)"
13+
required: true
14+
ref:
15+
description: "Git ref to create deployment for"
16+
required: true
17+
preview:
18+
description: "Whether to generate preview or production docs"
19+
required: false
20+
default: "false"
21+
22+
outputs:
23+
url:
24+
description: "The URL where the Ferns site was published"
25+
value: ${{ steps.generate-docs.outputs.url }}
26+
27+
runs:
28+
using: "composite"
29+
steps:
30+
- name: Install Fern
31+
shell: bash
32+
run: npm install -g fern-api
33+
34+
- name: Start deployment
35+
uses: bobheadxi/deployments@v1
36+
id: start-deploy
37+
with:
38+
step: start
39+
token: ${{ inputs.github-token }}
40+
env: ${{ inputs.environment }}
41+
ref: ${{ inputs.ref }}
42+
43+
- name: Generate documentation
44+
id: generate-docs
45+
shell: bash
46+
env:
47+
FERN_TOKEN: ${{ inputs.fern-token }}
48+
run: |
49+
if [[ "${{ inputs.preview }}" == "true" ]]; then
50+
OUTPUT=$(fern generate --docs --preview 2>&1) || true
51+
else
52+
OUTPUT=$(fern generate --docs --log-level debug 2>&1) || true
53+
fi
54+
echo "$OUTPUT"
55+
URL=$(echo "$OUTPUT" | grep -oP 'Published docs to \K.*(?= \()')
56+
echo "url=$URL" >> $GITHUB_OUTPUT
57+
58+
- name: Update deployment status
59+
uses: bobheadxi/deployments@v1
60+
if: always()
61+
with:
62+
step: finish
63+
token: ${{ inputs.github-token }}
64+
status: ${{ job.status }}
65+
deployment_id: ${{ steps.start-deploy.outputs.deployment_id }}
66+
env_url: ${{ steps.generate-docs.outputs.url }}
67+
env: ${{ inputs.environment }}

.github/workflows/preview-docs.yml

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,47 @@ on: pull_request
55
jobs:
66
run:
77
runs-on: ubuntu-22.04
8-
permissions: write-all
8+
permissions:
9+
contents: read
10+
deployments: write
11+
pull-requests: write
912
steps:
1013
- name: Checkout repository
1114
uses: actions/checkout@v4
1215

13-
# TODO: Uncomment this once new docs dir in aa-sdk is merged
14-
# - name: Download aa-sdk docs
15-
# run: |
16-
# mkdir -p account-kit
17-
# curl -L https://api.github.com/repos/alchemyplatform/aa-sdk/tarball/main -o aa-sdk.tar.gz
18-
# tar xzf aa-sdk.tar.gz --strip-components=2 -C account-kit "*/docs"
19-
# rm aa-sdk.tar.gz
16+
- name: Set Build Comment to In Progress
17+
uses: actions/github-script@v7
18+
with:
19+
script: |
20+
const workspace = process.env.GITHUB_WORKSPACE;
21+
const { updatePreviewComment } = await import(`${workspace}/scripts/preview-comment.js`);
2022
21-
- name: Install Fern
22-
run: npm install -g fern-api
23+
await updatePreviewComment({
24+
github,
25+
context,
26+
status: 'building',
27+
});
2328
24-
- name: Generate preview URL
25-
id: generate-docs
26-
env:
27-
FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
28-
run: |
29-
OUTPUT=$(fern generate --docs --preview 2>&1) || true
30-
echo "$OUTPUT"
31-
URL=$(echo "$OUTPUT" | grep -oP 'Published docs to \K.*(?= \()')
32-
echo "preview_url=$URL" >> $GITHUB_OUTPUT
29+
- name: Generate Preview
30+
uses: ./.github/actions/publish-fern
31+
id: preview
32+
with:
33+
github-token: ${{ github.token }}
34+
fern-token: ${{ secrets.FERN_TOKEN }}
35+
environment: docs-preview
36+
ref: ${{ github.head_ref }}
37+
preview: "true"
3338

3439
- name: Comment Preview URL in PR
3540
uses: actions/github-script@v7
3641
with:
3742
script: |
38-
github.rest.issues.createComment({
39-
issue_number: context.issue.number,
40-
owner: context.repo.owner,
41-
repo: context.repo.repo,
42-
body: '## 🌿 Documentation Preview\n\n| Name | Preview | Updated (UTC) |\n| :--- | :------ | :------ |\n| **Alchemy Docs** | [🔗 Visit Preview](${{ steps.generate-docs.outputs.preview_url }}) | ' + new Date().toLocaleString('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }) + ' |\n\n>'
43+
const workspace = process.env.GITHUB_WORKSPACE;
44+
const { updatePreviewComment } = await import(`${workspace}/scripts/preview-comment.js`);
45+
46+
await updatePreviewComment({
47+
github,
48+
context,
49+
previewUrl: '${{ steps.preview.outputs.url }}',
50+
status: '${{ steps.preview.outcome }}',
4351
});

.github/workflows/publish-docs.yml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ jobs:
99
run:
1010
runs-on: ubuntu-22.04
1111
if: ${{ github.event_name == 'push' && contains(github.ref, 'refs/heads/main') && github.run_number > 1 }}
12+
permissions:
13+
contents: read
14+
deployments: write
1215
steps:
1316
- name: Checkout repository
1417
uses: actions/checkout@v4
1518

16-
- name: Install Fern
17-
run: npm install -g fern-api
18-
19-
- name: Publish Docs
20-
env:
21-
FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
22-
run: fern generate --docs --log-level debug
19+
- name: Publish Documentation
20+
uses: ./.github/actions/publish-fern
21+
id: publish
22+
with:
23+
github-token: ${{ github.token }}
24+
fern-token: ${{ secrets.FERN_TOKEN }}
25+
environment: docs-production
26+
ref: ${{ github.ref }}

scripts/preview-comment.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Typescript not supported in actions/github-script@v7
2+
// https://github.com/actions/github-script/issues/294
3+
const commentTitle = "🌿 Documentation Preview";
4+
5+
/**
6+
* Generates the body of a PR comment for a documentation preview
7+
* @param {string} status - The outcome of the preview step - `success`, `failure`, `building`, `cancelled`, or `skipped`
8+
* @param {string} previewUrl - The URL of the documentation preview
9+
* @param {string} previousUrl - The URL of the previous successful preview build
10+
*/
11+
const getCommentBody = (status = "success", previewUrl = "") => {
12+
const timeUTC = new Date().toLocaleString("en-US", {
13+
month: "short",
14+
day: "numeric",
15+
year: "numeric",
16+
hour: "numeric",
17+
minute: "2-digit",
18+
hour12: true,
19+
});
20+
21+
const statusDisplay = {
22+
success: "✅ Ready",
23+
failure: "❌ Failed",
24+
building: "⌛ In Progress",
25+
cancelled: "⚠️ Cancelled",
26+
skipped: "⏭️ Skipped",
27+
};
28+
29+
const previewDisplay = {
30+
success: `[🔗 Visit Preview](${previewUrl})`,
31+
failure: "",
32+
building: "🏗️ Building...",
33+
cancelled: "",
34+
skipped: "",
35+
};
36+
37+
const statusMessage = statusDisplay[status];
38+
const previewLink = previewDisplay[status];
39+
40+
const headerRow = `## ${commentTitle}\n\n`;
41+
const tableHeader = `| Name | Status | Preview | Updated (UTC) |\n`;
42+
const tableDivider = `| :--- | :------ | :------ | :------ |\n`;
43+
const tableContent = `| **Alchemy Docs** | ${statusMessage} | ${previewLink} | ${timeUTC} |\n\n>`;
44+
const commentBody = headerRow + tableHeader + tableDivider + tableContent;
45+
46+
return commentBody;
47+
};
48+
49+
/**
50+
* Updates or creates a comment on a GitHub pull request with a documentation preview link
51+
* @param {object} params - The parameters object
52+
* @param {object} params.github - The GitHub API client instance
53+
* @param {object} params.context - The GitHub Actions context object
54+
* @param {string} params.previewUrl - The URL of the documentation preview
55+
* @param {string} params.status - The outcome of the preview step - `success`, `failure`, `building`, `cancelled`, or `skipped`
56+
*/
57+
const updatePreviewComment = async ({
58+
github,
59+
context,
60+
status = "success",
61+
previewUrl,
62+
}) => {
63+
const { repo, issue } = context;
64+
65+
const allComments = await github.rest.issues.listComments({
66+
owner: repo.owner,
67+
repo: repo.repo,
68+
issue_number: issue.number,
69+
});
70+
71+
const existingComment = allComments.data.find((comment) =>
72+
comment.body.includes(commentTitle),
73+
);
74+
75+
const commentBody = getCommentBody(status, previewUrl);
76+
77+
if (existingComment) {
78+
await github.rest.issues.updateComment({
79+
owner: repo.owner,
80+
repo: repo.repo,
81+
comment_id: existingComment.id,
82+
body: commentBody,
83+
});
84+
} else {
85+
await github.rest.issues.createComment({
86+
owner: repo.owner,
87+
repo: repo.repo,
88+
issue_number: issue.number,
89+
body: commentBody,
90+
});
91+
}
92+
};
93+
94+
export { updatePreviewComment };

0 commit comments

Comments
 (0)