Skip to content

Commit ee66471

Browse files
committed
Migrate remaining workflows to actions
1 parent 1d544ef commit ee66471

File tree

6 files changed

+305
-315
lines changed

6 files changed

+305
-315
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Flaky Test Report
2+
description: 'Generates a report of flaky tests from a specified GitHub Actions workflow and sends it to a Slack channel.'
3+
4+
inputs:
5+
repository:
6+
description: 'Repository name (e.g. metamask-extension)'
7+
required: true
8+
workflow-id:
9+
description: 'Workflow ID to analyze (e.g. main.yml)'
10+
required: true
11+
github-token:
12+
description: 'GitHub token with repo and actions:read access'
13+
required: true
14+
slack-webhook-flaky-tests:
15+
description: 'Slack webhook URL for flaky test reports'
16+
required: true
17+
18+
runs:
19+
using: composite
20+
steps:
21+
- name: Checkout github-tools repository
22+
uses: actions/checkout@v4
23+
with:
24+
repository: MetaMask/github-tools
25+
path: github-tools
26+
27+
- name: Set up Node.js
28+
uses: actions/setup-node@v4
29+
with:
30+
node-version-file: ./github-tools/.nvmrc
31+
cache-dependency-path: ./github-tools/yarn.lock
32+
cache: yarn
33+
34+
- name: Enable Corepack
35+
working-directory: ./github-tools
36+
shell: bash
37+
run: corepack enable
38+
39+
- name: Install dependencies
40+
working-directory: ./github-tools
41+
shell: bash
42+
run: yarn --immutable
43+
44+
- name: Run flaky test report script
45+
env:
46+
REPOSITORY: ${{ inputs.repository }}
47+
WORKFLOW_ID: ${{ inputs.workflow-id }}
48+
GITHUB_TOKEN: ${{ inputs.github-token }}
49+
SLACK_WEBHOOK_FLAKY_TESTS: ${{ inputs.slack-webhook-flaky-tests }}
50+
working-directory: ./github-tools
51+
shell: bash
52+
run: node .github/scripts/create-flaky-test-report.mjs
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Log Merge Group Failure
2+
3+
inputs:
4+
google-application-credentials:
5+
description: 'Path to Google application credentials JSON file.'
6+
required: true
7+
google-service-account:
8+
description: 'Base64 encoded Google service account JSON.'
9+
required: true
10+
spreadsheet-id:
11+
description: 'Google Spreadsheet ID.'
12+
required: true
13+
sheet-name:
14+
description: 'Sheet tab name.'
15+
required: true
16+
17+
runs:
18+
using: composite
19+
steps:
20+
- name: Download oauth2l
21+
shell: bash
22+
run: |
23+
curl --silent https://storage.googleapis.com/oauth2l/1.3.2/linux_amd64.tgz | tar xz
24+
echo "$PWD/linux_amd64" >> "$GITHUB_PATH"
25+
26+
- name: Create service_account.json
27+
env:
28+
GOOGLE_APPLICATION_CREDENTIALS: ${{ inputs.google-application-credentials }}
29+
GOOGLE_SERVICE_ACCOUNT: ${{ inputs.google-service-account }}
30+
shell: bash
31+
run: |
32+
echo "$GOOGLE_SERVICE_ACCOUNT" > "$GOOGLE_APPLICATION_CREDENTIALS"
33+
34+
- name: Write data to google sheets
35+
env:
36+
GOOGLE_APPLICATION_CREDENTIALS: ${{ inputs.google-application-credentials }}
37+
SPREADSHEET_ID: ${{ inputs.spreadsheet-id }}
38+
SHEET_NAME: ${{ inputs.sheet-name }}
39+
shell: bash
40+
run: |
41+
current_date=$(date +%Y-%m-%d)
42+
token=$(oauth2l fetch --scope https://www.googleapis.com/auth/spreadsheets)
43+
spreadsheet_data=$(curl --silent --header "Authorization: Bearer $token" https://sheets.googleapis.com/v4/spreadsheets/"$SPREADSHEET_ID"/values/"$SHEET_NAME"!A:B)
44+
current_date_index=$(echo "$spreadsheet_data" | jq --arg current_date "$current_date" '(.values | map(.[0])) | (index($current_date) | if . == null then null else . + 1 end)')
45+
current_number_of_prs=$(echo "$spreadsheet_data" | jq --arg current_date "$current_date" '(.values[] | select(.[0] == $current_date) | .[1] | tonumber) // null')
46+
if [ "$current_date_index" == "null" ]; then
47+
curl --silent --header "Authorization: Bearer $token" --header "Content-Type: application/json" --request POST --data "{\"values\":[[\"$current_date\", 1]]}" https://sheets.googleapis.com/v4/spreadsheets/"$SPREADSHEET_ID"/values/"$SHEET_NAME"!A:A:append?valueInputOption=USER_ENTERED
48+
else
49+
curl --silent --header "Authorization: Bearer $token" --header "Content-Type: application/json" --request PUT --data "{\"values\":[[\"$current_date\", $(("$current_number_of_prs" + 1))]]}" https://sheets.googleapis.com/v4/spreadsheets/"$SPREADSHEET_ID"/values/"$SHEET_NAME"!A"$current_date_index":B"$current_date_index"?valueInputOption=USER_ENTERED
50+
fi
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
name: Check PR Lines Changed
2+
description: 'Checks the number of lines changed in a PR and manages size labels accordingly.'
3+
4+
inputs:
5+
max-lines:
6+
description: 'Maximum allowed total lines changed'
7+
required: false
8+
default: '1000'
9+
base-ref:
10+
description: 'Default base branch to compare against (if not running on a PR)'
11+
required: false
12+
default: 'main'
13+
ignore-patterns:
14+
description: 'Regex pattern for files to ignore when calculating changes'
15+
required: false
16+
default: '(\.lock$)'
17+
xs-max-size:
18+
description: 'Maximum lines for XS size'
19+
required: false
20+
default: '10'
21+
s-max-size:
22+
description: 'Maximum lines for S size'
23+
required: false
24+
default: '100'
25+
m-max-size:
26+
description: 'Maximum lines for M size'
27+
required: false
28+
default: '500'
29+
l-max-size:
30+
description: 'Maximum lines for L size'
31+
required: false
32+
default: '1000'
33+
34+
runs:
35+
using: composite
36+
steps:
37+
- name: Checkout code
38+
uses: actions/checkout@v4
39+
40+
- name: Calculate changed lines
41+
id: line-count
42+
env:
43+
BASE_BRANCH: ${{ github.event.pull_request.base.ref || inputs.base-ref }}
44+
IGNORE_PATTERNS: ${{ inputs.ignore-patterns }}
45+
shell: bash
46+
run: |
47+
set -e
48+
49+
echo "Using base branch: $BASE_BRANCH"
50+
51+
# Instead of a full fetch, perform incremental fetches at increasing depth
52+
# until the merge-base between origin/<BASE_BRANCH> and HEAD is present.
53+
fetch_with_depth() {
54+
local depth=$1
55+
echo "Attempting to fetch with depth $depth..."
56+
git fetch --depth="$depth" origin "$BASE_BRANCH"
57+
}
58+
59+
depths=(1 10 100)
60+
merge_base_found=false
61+
62+
for d in "${depths[@]}"; do
63+
fetch_with_depth "$d"
64+
if git merge-base "origin/$BASE_BRANCH" HEAD > /dev/null 2>&1; then
65+
echo "Merge base found with depth $d."
66+
merge_base_found=true
67+
break
68+
else
69+
echo "Merge base not found with depth $d, increasing depth..."
70+
fi
71+
done
72+
73+
# If we haven't found the merge base with shallow fetches, unshallow the repo.
74+
if [ "$merge_base_found" = false ]; then
75+
echo "Could not find merge base with shallow fetches, fetching full history..."
76+
git fetch --unshallow origin "$BASE_BRANCH" || git fetch origin "$BASE_BRANCH"
77+
fi
78+
79+
# Calculate additions and deletions across all changes between the base and HEAD,
80+
# filtering out files matching the ignore pattern.
81+
additions=$(git diff "origin/$BASE_BRANCH"...HEAD --numstat | grep -Ev "$IGNORE_PATTERNS" | awk '{add += $1} END {print add+0}')
82+
deletions=$(git diff "origin/$BASE_BRANCH"...HEAD --numstat | grep -Ev "$IGNORE_PATTERNS" | awk '{del += $2} END {print del+0}')
83+
total=$((additions + deletions))
84+
85+
echo "Additions: $additions, Deletions: $deletions, Total: $total"
86+
{
87+
echo "lines-changed=$total"
88+
echo "additions=$additions"
89+
echo "deletions=$deletions"
90+
} >> "$GITHUB_OUTPUT"
91+
92+
- name: Check line count limit
93+
uses: actions/github-script@v7
94+
env:
95+
LINES_CHANGED: ${{ steps.line-count.outputs.lines-changed }}
96+
ADDITIONS: ${{ steps.line-count.outputs.additions }}
97+
DELETIONS: ${{ steps.line-count.outputs.deletions }}
98+
MAX_LINES: ${{ inputs.max-lines }}
99+
XS_MAX_SIZE: ${{ inputs.xs-max-size }}
100+
S_MAX_SIZE: ${{ inputs.s-max-size }}
101+
M_MAX_SIZE: ${{ inputs.m-max-size }}
102+
L_MAX_SIZE: ${{ inputs.l-max-size }}
103+
with:
104+
script: |
105+
const {
106+
LINES_CHANGED,
107+
ADDITIONS,
108+
DELETIONS,
109+
MAX_LINES,
110+
XS_MAX_SIZE,
111+
S_MAX_SIZE,
112+
M_MAX_SIZE,
113+
L_MAX_SIZE,
114+
} = process.env;
115+
116+
const total = parseInt(LINES_CHANGED, 10) || 0;
117+
const additions = parseInt(ADDITIONS, 10) || 0;
118+
const deletions = parseInt(DELETIONS, 10) || 0;
119+
120+
// Thresholds from inputs with fallback to defaults
121+
const maxLines = parseInt(MAX_LINES, 10) || 1000;
122+
const xsMaxSize = parseInt(XS_MAX_SIZE, 10) || 10;
123+
const sMaxSize = parseInt(S_MAX_SIZE, 10) || 100;
124+
const mMaxSize = parseInt(M_MAX_SIZE, 10) || 500;
125+
const lMaxSize = parseInt(L_MAX_SIZE, 10) || 1000;
126+
127+
// Print summary
128+
console.log('Summary:');
129+
console.log(` - Additions: ${additions}`);
130+
console.log(` - Deletions: ${deletions}`);
131+
console.log(` - Total: ${total}`);
132+
console.log(` - Limit: ${maxLines}`);
133+
134+
// Determine size label based on configured criteria
135+
let sizeLabel = '';
136+
if (total <= xsMaxSize) {
137+
sizeLabel = 'size-XS';
138+
} else if (total <= sMaxSize) {
139+
sizeLabel = 'size-S';
140+
} else if (total <= mMaxSize) {
141+
sizeLabel = 'size-M';
142+
} else if (total <= lMaxSize) {
143+
sizeLabel = 'size-L';
144+
} else {
145+
sizeLabel = 'size-XL';
146+
}
147+
148+
console.log(` - Size category: ${sizeLabel}`);
149+
150+
// Manage PR labels
151+
const owner = context.repo.owner;
152+
const repo = context.repo.repo;
153+
const issue_number = context.payload.pull_request.number;
154+
155+
try {
156+
const existingSizeLabels = ['size-XS', 'size-S', 'size-M', 'size-L', 'size-XL'];
157+
158+
// Get current labels
159+
const currentLabels = await github.rest.issues.listLabelsOnIssue({
160+
owner,
161+
repo,
162+
issue_number
163+
});
164+
165+
const currentLabelNames = currentLabels.data.map(l => l.name);
166+
167+
// Build new label set: keep non-size labels and add the new size label
168+
const newLabels = currentLabelNames
169+
.filter(name => !existingSizeLabels.includes(name)) // Remove all size labels
170+
.concat(sizeLabel); // Add the correct size label
171+
172+
// Check if labels need updating
173+
const currentSizeLabel = currentLabelNames.find(name => existingSizeLabels.includes(name));
174+
if (currentSizeLabel === sizeLabel && currentLabelNames.length === newLabels.length) {
175+
console.log(`✅ Correct label '${sizeLabel}' already present, no changes needed`);
176+
} else {
177+
// Update all labels in a single API call
178+
await github.rest.issues.setLabels({
179+
owner,
180+
repo,
181+
issue_number,
182+
labels: newLabels
183+
});
184+
185+
if (currentSizeLabel && currentSizeLabel !== sizeLabel) {
186+
console.log(` - Replaced '${currentSizeLabel}' with '${sizeLabel}'`);
187+
} else if (!currentSizeLabel) {
188+
console.log(`✅ Added '${sizeLabel}' label to PR #${issue_number}`);
189+
} else {
190+
console.log(`✅ Updated labels for PR #${issue_number}`);
191+
}
192+
}
193+
} catch (error) {
194+
console.log(`⚠️ Could not manage labels: ${error.message}`);
195+
}
196+
197+
// Check if exceeds limit
198+
if (total > maxLines) {
199+
console.log(`❌ Error: Total changed lines (${total}) exceed the limit of ${maxLines}.`);
200+
process.exit(1);
201+
} else {
202+
console.log(`✅ Success: Total changed lines (${total}) are within the limit of ${maxLines}.`);
203+
}

.github/workflows/flaky-test-report.yml

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)