Skip to content

Commit 1d544ef

Browse files
authored
refactor!: Migrate release management workflows to actions (#166)
* Move workflows to actions folder * Update workflows to actions * Update get release timelines test * Fix Slack action
1 parent be06c31 commit 1d544ef

File tree

12 files changed

+431
-447
lines changed

12 files changed

+431
-447
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Get Release Timelines
2+
description: 'Get release timelines from Runway and upload as artifact.'
3+
4+
inputs:
5+
version:
6+
required: true
7+
description: The version of the release.
8+
github-token:
9+
required: true
10+
description: The GitHub token used for authentication.
11+
runway-app-id:
12+
required: true
13+
description: The Runway application ID.
14+
runway-api-key:
15+
required: true
16+
description: The Runway API key.
17+
github-tools-repository:
18+
description: 'The GitHub repository containing the GitHub tools. Defaults to the GitHub tools action repositor, and usually does not need to be changed.'
19+
required: false
20+
default: ${{ github.action_repository }}
21+
github-tools-ref:
22+
description: 'The SHA of the action to use. Defaults to the current action ref, and usually does not need to be changed.'
23+
required: false
24+
default: ${{ github.action_ref }}
25+
26+
runs:
27+
using: composite
28+
steps:
29+
- name: Checkout GitHub tools repository
30+
uses: actions/checkout@v5
31+
with:
32+
repository: ${{ inputs.github-tools-repository }}
33+
ref: ${{ inputs.github-tools-ref }}
34+
path: ./github-tools
35+
36+
- name: Get release timelines
37+
env:
38+
OWNER: ${{ github.repository_owner }}
39+
REPOSITORY: ${{ github.event.repository.name }}
40+
VERSION: ${{ inputs.version }}
41+
RUNWAY_APP_ID: ${{ inputs.runway-app-id }}
42+
RUNWAY_API_KEY: ${{ inputs.runway-api-key }}
43+
GH_TOKEN: ${{ inputs.github-token }}
44+
shell: bash
45+
run: ./github-tools/.github/scripts/get-release-timelines.sh
46+
47+
- name: Upload artifact release-timelines-${{ inputs.version }}.csv
48+
uses: actions/upload-artifact@v4
49+
with:
50+
name: release-timelines-${{ inputs.version }}.csv
51+
path: release-timelines-${{ inputs.version }}.csv
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
name: Post RCA Form
2+
description: 'Posts a Google Form link for RCA on issues with specific labels.'
3+
4+
inputs:
5+
google-form-base-url:
6+
description: Base URL of the Google Form.
7+
default: 'https://docs.google.com/forms/d/e/1FAIpQLSeLOVVUy7mO1j-5Isb04OAWk3dM0b1NY1R8kf0tiEBs9elcEg/viewform?usp=pp_url'
8+
repo-owner:
9+
description: The repo owner
10+
required: true
11+
repo-name:
12+
description: The repo name
13+
required: true
14+
issue-number:
15+
description: The number of the closed issue
16+
required: true
17+
issue-labels:
18+
description: JSON-stringified array of labels that should trigger the RCA prompt
19+
required: true
20+
entry-issue:
21+
description: The entry ID for the issue field in the Google Form
22+
default: 'entry.1417567074'
23+
entry-regression:
24+
description: The entry ID for the regression field in the Google Form
25+
default: 'entry.1470697156'
26+
entry-team:
27+
description: The entry ID for the team field in the Google Form
28+
default: 'entry.1198657478'
29+
entry-repo-name:
30+
description: The entry ID for the repository name field
31+
default: 'entry.1085838323'
32+
entry-issue-url:
33+
description: The entry ID for the GitHub issue URL field
34+
default: 'entry.516762472'
35+
github-token:
36+
description: GitHub token for authentication
37+
required: true
38+
39+
runs:
40+
using: composite
41+
steps:
42+
- name: Post RCA Form Link
43+
uses: actions/github-script@v8
44+
env:
45+
GOOGLE_FORM_BASE_URL: ${{ inputs.google-form-base-url }}
46+
ISSUE_LABELS: ${{ inputs.issue-labels }}
47+
OWNER_NAME: ${{ inputs.repo-owner }}
48+
REPO_NAME: ${{ inputs.repo-name }}
49+
ISSUE_NUMBER: ${{ inputs.issue-number }}
50+
ENTRY_ISSUE: ${{ inputs.entry-issue }}
51+
ENTRY_REGRESSION: ${{ inputs.entry-regression }}
52+
ENTRY_TEAM: ${{ inputs.entry-team }}
53+
ENTRY_REPO_NAME: ${{ inputs.entry-repo-name }}
54+
ENTRY_ISSUE_URL: ${{ inputs.entry-issue-url }}
55+
with:
56+
github-token: ${{ inputs.github-token }}
57+
script: |
58+
const {
59+
GOOGLE_FORM_BASE_URL: baseUrl,
60+
ENTRY_ISSUE,
61+
ENTRY_REGRESSION,
62+
ENTRY_TEAM,
63+
ENTRY_REPO_NAME,
64+
ENTRY_ISSUE_URL,
65+
OWNER_NAME: owner,
66+
REPO_NAME: repo,
67+
ISSUE_NUMBER: issueNumStr,
68+
} = process.env;
69+
70+
const issue_number = parseInt(issueNumStr, 10);
71+
const allowedLabels = JSON.parse(process.env.ISSUE_LABELS);
72+
73+
// Fetch issue details to get the assignees
74+
const { data: issue } = await github.rest.issues.get({
75+
owner,
76+
repo,
77+
issue_number: issue_number,
78+
});
79+
80+
const hasAllowedLabel = issue.labels.some(label =>
81+
allowedLabels.includes(label.name)
82+
);
83+
84+
if (!hasAllowedLabel) {
85+
console.log(`❌ Issue #${issue_number} skipped — no matching label.`);
86+
return;
87+
}
88+
89+
// if it's a sev1-high or sev0-high, lets grab team and regression labels, if there's any
90+
// if there's none, an empty value will be sent, which is what we want
91+
const teamLabels = issue.labels
92+
.map(l => l.name)
93+
.filter(n => n.startsWith('team-'));
94+
95+
const regressionLabels = issue.labels
96+
.map(l => l.name)
97+
.filter(n => n.startsWith('regression-'));
98+
99+
const formUrl = new URL(baseUrl);
100+
formUrl.searchParams.set(ENTRY_ISSUE, issue_number);
101+
formUrl.searchParams.set(
102+
ENTRY_REGRESSION,
103+
regressionLabels.length ? regressionLabels.join(',') : ''
104+
);
105+
formUrl.searchParams.set(
106+
ENTRY_TEAM,
107+
teamLabels.length ? teamLabels.join(',') : ''
108+
);
109+
110+
formUrl.searchParams.set(ENTRY_REPO_NAME, repo);
111+
formUrl.searchParams.set(ENTRY_ISSUE_URL, `https://github.com/${owner}/${repo}/issues/${issue_number}`);
112+
113+
const assignees = issue.assignees.map(u=>`@${u.login}`).join(', ');
114+
const body = `Hi ${assignees},
115+
116+
This issue has been closed. Please complete this RCA form:
117+
${formUrl.toString()}
118+
119+
<!-- AUTO-FORM -->`;
120+
121+
await github.rest.issues.createComment({
122+
owner, repo, issue_number, body
123+
});
124+
console.log(`✅ Comment posted on issue #${issue_number}`);
125+
126+
// Add the RCA-needed label
127+
try {
128+
await github.rest.issues.addLabels({
129+
owner,
130+
repo,
131+
issue_number: issue_number,
132+
labels: ['RCA-needed']
133+
});
134+
console.log(`✅ Added 'RCA-needed' label on issue #${issue_number}`);
135+
} catch (error) {
136+
console.log(`⚠️ Could not add label: ${error.message}`);
137+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Publish Slack Release Testing Status
2+
description: 'Publish the release testing status to Slack channels based on a Google Document.'
3+
4+
inputs:
5+
platform:
6+
description: 'The platform for which the release testing status is being published (e.g., mobile, extension).'
7+
required: true
8+
google-document-id:
9+
description: 'The ID of the Google Document containing the release testing status.'
10+
required: true
11+
test-only:
12+
description: 'If set to true, the action will only run in test mode and not publish to production Slack channels.'
13+
required: false
14+
default: 'false'
15+
slack-api-key:
16+
description: 'The API key for Slack to post the release testing status.'
17+
required: true
18+
github-token:
19+
description: 'The GitHub token for authentication.'
20+
required: true
21+
google-application-creds-base64:
22+
description: 'Base64 encoded Google application credentials for accessing Google Docs.'
23+
required: true
24+
github-tools-repository:
25+
description: 'The GitHub repository containing the GitHub tools. Defaults to the GitHub tools action repositor, and usually does not need to be changed.'
26+
required: false
27+
default: ${{ github.action_repository }}
28+
github-tools-ref:
29+
description: 'The SHA of the action to use. Defaults to the current action ref, and usually does not need to be changed.'
30+
required: false
31+
default: ${{ github.action_ref }}
32+
33+
runs:
34+
using: composite
35+
steps:
36+
- name: Checkout GitHub tools repository
37+
uses: actions/checkout@v5
38+
with:
39+
repository: ${{ inputs.github-tools-repository }}
40+
ref: ${{ inputs.github-tools-ref }}
41+
path: ./github-tools
42+
43+
- name: Set up Node.js
44+
uses: actions/setup-node@v4
45+
with:
46+
node-version-file: ./github-tools/.nvmrc
47+
cache-dependency-path: ./github-tools/yarn.lock
48+
cache: yarn
49+
50+
- name: Enable Corepack
51+
run: corepack enable
52+
shell: bash
53+
working-directory: ./github-tools
54+
55+
- name: Install dependencies
56+
run: yarn --immutable
57+
shell: bash
58+
working-directory: ./github-tools
59+
60+
- name: Publish Slack Release Testing Status
61+
id: publish-slack-release-testing-status
62+
shell: bash
63+
env:
64+
GITHUB_TOKEN: ${{ inputs.github-token }}
65+
SLACK_API_KEY: ${{ inputs.slack-api-key }}
66+
GOOG_DOCUMENT_ID: ${{ inputs.google-document-id }}
67+
GOOGLE_APPLICATION_CREDENTIALS_BASE64: ${{ inputs.google-application-creds-base64 }}
68+
TEST_ONLY: ${{ inputs.test-only }}
69+
PLATFORM: ${{ inputs.platform }}
70+
working-directory: ./github-tools
71+
run: |
72+
yarn run slack:release-testing
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Remove RCA-needed Label
2+
description: 'Removes the RCA-needed label from issues listed in a Google Sheet.'
3+
4+
inputs:
5+
dry-run:
6+
description: 'Run in dry-run mode (no changes made)'
7+
required: false
8+
default: 'false'
9+
spreadsheet-id:
10+
description: 'Google Spreadsheet ID (must be provided by consuming repository)'
11+
required: true
12+
sheet-name:
13+
description: 'Sheet tab name (uses default if not provided)'
14+
required: false
15+
default: 'Form Responses 1'
16+
github-token:
17+
description: 'Github token with issues write permissions'
18+
required: true
19+
google-application-creds-base64:
20+
description: 'Base64 encoded Google application service account credentials'
21+
required: true
22+
github-tools-repository:
23+
description: 'The GitHub repository containing the GitHub tools. Defaults to the GitHub tools action repositor, and usually does not need to be changed.'
24+
required: false
25+
default: ${{ github.action_repository }}
26+
github-tools-ref:
27+
description: 'The SHA of the action to use. Defaults to the current action ref, and usually does not need to be changed.'
28+
required: false
29+
default: ${{ github.action_ref }}
30+
31+
runs:
32+
using: composite
33+
steps:
34+
- name: Checkout consuming repository
35+
uses: actions/checkout@v5
36+
with:
37+
token: ${{ inputs.github-token }}
38+
39+
- name: Checkout GitHub tools repository
40+
uses: actions/checkout@v5
41+
with:
42+
repository: ${{ inputs.github-tools-repository }}
43+
ref: ${{ inputs.github-tools-ref }}
44+
path: ./github-tools
45+
46+
- name: Setup Node.js
47+
uses: actions/setup-node@v6
48+
with:
49+
node-version: '20'
50+
51+
- name: Run RCA Google Sheets check
52+
shell: bash
53+
run: |
54+
# Move to github-tools directory where our script lives
55+
cd github-tools/.github/scripts
56+
57+
# Create a simple package.json for npm to work with
58+
echo '{}' > package.json
59+
60+
# Install exact versions of required packages locally
61+
npm install --no-save --no-package-lock \
62+
@actions/[email protected] \
63+
@actions/[email protected] \
64+
65+
66+
67+
# Run the script with tsx
68+
npx tsx remove-rca-needed-label-sheets.ts
69+
env:
70+
GITHUB_TOKEN: ${{ inputs.github-token }}
71+
GOOGLE_SHEETS_CREDENTIALS: ${{ inputs.google-application-creds-base64 }}
72+
DRY_RUN: ${{ inputs.dry-run }}
73+
SPREADSHEET_ID: ${{ inputs.spreadsheet-id }}
74+
SHEET_NAME: ${{ inputs.sheet-name }}

0 commit comments

Comments
 (0)