Add script for validating PR title (#4050)
This commit is contained in:
2
.github/labeler.yml
vendored
2
.github/labeler.yml
vendored
@@ -6,7 +6,7 @@ iOS:
|
||||
- any-glob-to-any-file:
|
||||
- 'platform/ios/**/*'
|
||||
- 'platform/darwin/**/*'
|
||||
cpp-core:
|
||||
core:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'src/**/*'
|
||||
|
||||
30
.github/scripts/validate-pr-title.test.ts
vendored
Normal file
30
.github/scripts/validate-pr-title.test.ts
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import test from "node:test";
|
||||
import { validateTitle } from "./validate-pr-title.ts";
|
||||
|
||||
test("validateTitle - missing Android label", (t) => {
|
||||
t.assert.deepEqual(validateTitle({
|
||||
labels: new Set(["android"]),
|
||||
title: "make a change"
|
||||
}), {
|
||||
mismatches: ["android"],
|
||||
ok: false
|
||||
});
|
||||
});
|
||||
|
||||
test("validateTitle - android required and title contains Android", (t) => {
|
||||
t.assert.deepEqual(validateTitle({
|
||||
labels: new Set(["android"]),
|
||||
title: "make change to Android"
|
||||
}), {
|
||||
ok: true
|
||||
});
|
||||
});
|
||||
|
||||
test("validateTitle - only core required when label contains core", (t) => {
|
||||
t.assert.deepEqual(validateTitle({
|
||||
labels: new Set(["core", "android"]),
|
||||
title: "core: make some change"
|
||||
}), {
|
||||
ok: true
|
||||
});
|
||||
});
|
||||
68
.github/scripts/validate-pr-title.ts
vendored
Normal file
68
.github/scripts/validate-pr-title.ts
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// This script validates that a PR title also contains its labels
|
||||
// in the title. This is a requirement, because this makes it easier
|
||||
// to parse commit messages. For example, for generating a changelog
|
||||
// for a particular platform.
|
||||
// Usage:
|
||||
// PR_TITLE="Make some changes to Android" PR_LABELS="android" node validate-pr-title.ts
|
||||
|
||||
export function validateTitle({
|
||||
title,
|
||||
labels
|
||||
}: {
|
||||
title: string,
|
||||
labels: Set<string>
|
||||
}): { ok: true } | { ok: false, mismatches: string[] } {
|
||||
// these labels are the ones we care about
|
||||
const keywords = new Set(['node', 'core', 'ios', 'android', 'qt']);
|
||||
|
||||
// when labels includes core, only 'core' is required
|
||||
const requiredKeyWords = labels.has('core')
|
||||
? new Set(['core'])
|
||||
: labels.intersection(keywords);
|
||||
|
||||
title = title.toLocaleLowerCase();
|
||||
|
||||
const actualKeywords = new Set();
|
||||
for (const keyword of requiredKeyWords) {
|
||||
if (title.includes(keyword)) actualKeywords.add(keyword);
|
||||
}
|
||||
|
||||
const mismatches = requiredKeyWords.difference(actualKeywords);
|
||||
|
||||
if (mismatches.size === 0) return { ok: true };
|
||||
return { ok: false, mismatches: [...mismatches] };
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
if (!process.env.PR_TITLE) {
|
||||
console.log('::error::PR_TITLE environment variable is not set');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!process.env.PR_LABELS) {
|
||||
console.log('::error::PR_LABELS environment variable is not set');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const title = process.env.PR_TITLE;
|
||||
const labelsString = process.env.PR_LABELS.toLowerCase();
|
||||
const labels = new Set(labelsString.split(',').map(l => l.trim()).filter(l => l));
|
||||
|
||||
const result = validateTitle({
|
||||
title,
|
||||
labels
|
||||
});
|
||||
if (result.ok) {
|
||||
console.log('✅ PR labels match the title');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!result.ok) {
|
||||
if (result.mismatches.length > 0) {
|
||||
console.log(`::error::PR title does not match PR labels. Mismatched: ${result.mismatches.join(', ')}. Title: "${process.env.PR_TITLE}". Labels: "${process.env.PR_LABELS}"`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
.github/workflows/android-ci.yml
vendored
2
.github/workflows/android-ci.yml
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: npm install
|
||||
run: npm install --ignore-scripts
|
||||
run: npm ci --ignore-scripts
|
||||
working-directory: .
|
||||
shell: bash
|
||||
|
||||
|
||||
18
.github/workflows/typecheck-scripts.yml
vendored
18
.github/workflows/typecheck-scripts.yml
vendored
@@ -1,18 +0,0 @@
|
||||
name: typecheck-scripts
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
typecheck-scripts:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- run: |
|
||||
npm install
|
||||
npx tsc -p tsconfig.json
|
||||
22
.github/workflows/validate-pr-title.yml
vendored
Normal file
22
.github/workflows/validate-pr-title.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Validate PR title
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled, unlabeled, opened, edited]
|
||||
|
||||
jobs:
|
||||
validate-tags-match-title:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Check if labels match PR title
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_LABELS: ${{ join(github.event.pull_request.labels.*.name, ',') }}
|
||||
run: node .github/scripts/validate-pr-title.ts
|
||||
26
.github/workflows/validate-scripts.yml
vendored
Normal file
26
.github/workflows/validate-scripts.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: validate-scripts
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
validate-scripts:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v4
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Typecheck
|
||||
run: |
|
||||
npm install
|
||||
npx tsc -p tsconfig.json
|
||||
|
||||
- name: Run tests
|
||||
run: node --test .github/scripts/**.test.ts
|
||||
Reference in New Issue
Block a user