Skip to content

Commit c4f64e2

Browse files
committed
Improve notification card for Vercel deployment action workflow
1 parent 0a25ea8 commit c4f64e2

1 file changed

Lines changed: 104 additions & 9 deletions

File tree

.github/workflows/deployment.yml

Lines changed: 104 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,30 +75,125 @@ jobs:
7575
with:
7676
script: |
7777
const previewUrl = '${{ steps.vercel-preview.outputs.preview-url }}';
78-
const pr = context.payload.workflow_run.pull_requests && context.payload.workflow_run.pull_requests[0];
79-
if (!pr) {
80-
core.warning('No pull request metadata available; skipping preview comment.');
78+
const workflowRun = context.payload.workflow_run;
79+
const pr = workflowRun?.pull_requests?.[0];
80+
if (!pr || !previewUrl) {
81+
core.warning('Missing pull request metadata or preview URL; skipping preview success comment.');
8182
return;
8283
}
83-
await github.rest.issues.createComment({
84-
issue_number: pr.number,
84+
85+
const commentTag = '<!-- vercel-preview-card -->';
86+
const branch = workflowRun.head_branch ?? 'unknown-branch';
87+
const sha = workflowRun.head_sha ?? '';
88+
const shortSha = sha ? sha.slice(0, 7) : 'unknown';
89+
const commitUrl = sha
90+
? `https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${sha}`
91+
: `https://github.com/${context.repo.owner}/${context.repo.repo}`;
92+
const actor = workflowRun.actor ?? 'workflow_run';
93+
94+
const body = [
95+
commentTag,
96+
'✅ **Preview deployment ready**',
97+
'',
98+
'| Field | Value |',
99+
'| --- | --- |',
100+
`| Branch | \`${branch}\` |`,
101+
`| Commit | [${shortSha}](${commitUrl}) |`,
102+
`| Preview | [Open preview](${previewUrl}) |`,
103+
'',
104+
`_Triggered by @${actor}_`
105+
].join('\n');
106+
107+
const comments = await github.paginate(github.rest.issues.listComments, {
85108
owner: context.repo.owner,
86109
repo: context.repo.repo,
87-
body: `✅ Tests passed! Preview deployment ready:\n\n🔗 ${previewUrl}`
110+
issue_number: pr.number,
111+
per_page: 100
88112
});
113+
const existingComment = comments.find((comment) => comment.body?.includes(commentTag));
114+
115+
if (existingComment) {
116+
await github.rest.issues.updateComment({
117+
owner: context.repo.owner,
118+
repo: context.repo.repo,
119+
comment_id: existingComment.id,
120+
body
121+
});
122+
} else {
123+
await github.rest.issues.createComment({
124+
owner: context.repo.owner,
125+
repo: context.repo.repo,
126+
issue_number: pr.number,
127+
body
128+
});
129+
}
89130
90131
- name: Comment preview failure on PR
91132
if: always() && steps.vercel-preview.outcome != 'success'
92133
uses: actions/github-script@v8
134+
env:
135+
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
136+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
137+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
93138
with:
94139
script: |
95140
const previewUrl = '${{ steps.vercel-preview.outputs.preview-url }}';
96-
const pr = context.payload.workflow_run.pull_requests && context.payload.workflow_run.pull_requests[0];
141+
const workflowRun = context.payload.workflow_run;
142+
const pr = workflowRun?.pull_requests?.[0];
97143
if (!pr) {
98144
core.warning('No pull request metadata available; skipping preview failure comment.');
99145
return;
100146
}
101-
const linkLine = previewUrl ? `\n\n🔗 ${previewUrl}` : '\n\n🔗 View the failed deployment in Vercel.';
147+
148+
const fallbackRunUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
149+
const fetchDeploymentUrl = async () => {
150+
if (!process.env.VERCEL_TOKEN || !process.env.VERCEL_PROJECT_ID) {
151+
core.info('Missing Vercel credentials; cannot query deployment API.');
152+
return null;
153+
}
154+
const query = new URLSearchParams({
155+
projectId: process.env.VERCEL_PROJECT_ID,
156+
'meta-githubCommitSha': workflowRun?.head_sha ?? '',
157+
limit: '1'
158+
});
159+
if (process.env.VERCEL_ORG_ID) {
160+
query.set('teamId', process.env.VERCEL_ORG_ID);
161+
}
162+
if (typeof fetch !== 'function') {
163+
core.info('Fetch API unavailable in this runtime.');
164+
return null;
165+
}
166+
const response = await fetch(`https://api.vercel.com/v6/deployments?${query.toString()}`, {
167+
headers: {
168+
Authorization: `Bearer ${process.env.VERCEL_TOKEN}`
169+
}
170+
});
171+
if (!response.ok) {
172+
core.warning(`Unable to fetch deployment info (status ${response.status}).`);
173+
return null;
174+
}
175+
const data = await response.json();
176+
const deployment = data?.deployments?.[0];
177+
if (deployment?.url) {
178+
return `https://${deployment.url}`;
179+
}
180+
if (deployment?.inspectorUrl) {
181+
return deployment.inspectorUrl.startsWith('http')
182+
? deployment.inspectorUrl
183+
: `https://${deployment.inspectorUrl}`;
184+
}
185+
return null;
186+
};
187+
188+
let failedDeploymentUrl = previewUrl || await fetchDeploymentUrl();
189+
if (!failedDeploymentUrl) {
190+
failedDeploymentUrl = fallbackRunUrl;
191+
}
192+
193+
const linkText = failedDeploymentUrl === fallbackRunUrl
194+
? 'View the workflow logs'
195+
: 'Open the failed Vercel deployment';
196+
const linkLine = `\n\n🔗 [${linkText}](${failedDeploymentUrl})`;
102197
await github.rest.issues.createComment({
103198
issue_number: pr.number,
104199
owner: context.repo.owner,
@@ -147,7 +242,7 @@ jobs:
147242
const targetUrl = '${{ steps.vercel-production.outputs.preview-url }}';
148243
const body = targetUrl
149244
? `❌ Production deployment failed.\n\n🔗 ${targetUrl}\n\nPlease review the Vercel logs.`
150-
: '❌ Production deployment failed. Please review the Vercel logs.'
245+
: '❌ Production deployment failed. Please review the Vercel logs.';
151246
await github.rest.repos.createCommitComment({
152247
owner: context.repo.owner,
153248
repo: context.repo.repo,

0 commit comments

Comments
 (0)