mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
4cfe6b59ba
security.yml, lint-prettier.yml and the release workflows still ran actions built for Node 20 (checkout and setup-node v4, github-script v7, the docker actions v3/v5, create-github-app-token v1), which GitHub now forces onto Node 24 with a deprecation warning on every run. They move to the Node 24 majors test.yml already uses (download-artifact to v7, since v6 is still Node 20). Third-party actions, several of which hold the Docker Hub and GitHub App secrets, are pinned by commit with the tag in a comment. ubuntu-latest moves to a new Ubuntu release on 10-19, so every job names ubuntu-24.04 and the switch happens in a PR. Every setup-node reads .nvmrc; publish-plugin-sdk leaves 22, which it ran under a comment claiming it matched the server. security.yml gains an npm audit job over the lockfile, on PRs and pushes into dev as well as main. It covers what the image installs and the plugin SDK, takes seconds, and would have flagged the brace-expansion regression the ORM squash brought in the day it landed. Scout keeps its image scan on main. Neither becomes a required check: a CVE published overnight would turn every open PR red, including the ones that cannot fix it. The scout job now also skips PRs into dev, which the trigger change would otherwise hand it. .github/dependabot.yml adds weekly version updates into dev for the root workspace, plugin-sdk, the actions and the Docker base images, minor and patch grouped per ecosystem, majors one PR each. The Node major in the Dockerfile is left to a hand-made change together with .nvmrc.
172 lines
6.5 KiB
YAML
172 lines
6.5 KiB
YAML
name: Enforce PR Target Branch
|
|
|
|
on:
|
|
pull_request_target:
|
|
types: [opened, reopened, edited, synchronize]
|
|
|
|
jobs:
|
|
check-target:
|
|
if: github.repository == 'liketrek/TREK'
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 45
|
|
permissions:
|
|
pull-requests: write
|
|
issues: write
|
|
contents: read
|
|
|
|
steps:
|
|
- name: Flag or clear wrong base branch
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const base = context.payload.pull_request.base.ref;
|
|
const labels = context.payload.pull_request.labels.map(l => l.name);
|
|
const prNumber = context.payload.pull_request.number;
|
|
|
|
// bypass-branch-check label skips all enforcement
|
|
if (labels.includes('bypass-branch-check')) {
|
|
console.log('bypass-branch-check label present, skipping enforcement.');
|
|
return;
|
|
}
|
|
|
|
// Wiki-only PRs are exempt from branch enforcement
|
|
const files = [];
|
|
for (let page = 1; ; page++) {
|
|
const { data } = await github.rest.pulls.listFiles({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: prNumber,
|
|
per_page: 100,
|
|
page,
|
|
});
|
|
files.push(...data);
|
|
if (data.length < 100) break;
|
|
}
|
|
const allWiki = files.length > 0 && files.every(f => f.filename.startsWith('wiki/'));
|
|
if (allWiki) {
|
|
console.log('All changed files are under wiki/ — skipping enforcement.');
|
|
if (labels.includes('wrong-base-branch')) {
|
|
await github.rest.issues.removeLabel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
name: 'wrong-base-branch',
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
|
|
// If the base was fixed, remove the label and let it through
|
|
if (base !== 'main') {
|
|
if (labels.includes('wrong-base-branch')) {
|
|
await github.rest.issues.removeLabel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
name: 'wrong-base-branch',
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Dependabot's security updates cannot be pointed at dev. `target-branch`
|
|
// in .github/dependabot.yml applies to version updates only; security
|
|
// updates always open against the default branch. Labelling them meant
|
|
// close-stale-wrong-branch shut them 24 hours later, which is how 13 of
|
|
// them died. Retarget instead: a bot cannot click "Edit" the way the
|
|
// comment below asks a human to.
|
|
if (context.payload.pull_request.user.login === 'dependabot[bot]') {
|
|
try {
|
|
await github.rest.pulls.update({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: prNumber,
|
|
base: 'dev',
|
|
});
|
|
if (labels.includes('wrong-base-branch')) {
|
|
await github.rest.issues.removeLabel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
name: 'wrong-base-branch',
|
|
});
|
|
}
|
|
console.log('Retargeted the Dependabot PR onto dev.');
|
|
return;
|
|
} catch (err) {
|
|
// Retargeting can fail when the branch was cut from main and dev has
|
|
// moved on. Fall through to the normal path so a human sees it rather
|
|
// than the check passing on a PR that is still aimed at main.
|
|
console.log(`Could not retarget the Dependabot PR: ${err.message}`);
|
|
}
|
|
}
|
|
|
|
// Base is main — check if this user is a maintainer
|
|
let permission = 'none';
|
|
try {
|
|
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
username: context.payload.pull_request.user.login,
|
|
});
|
|
permission = data.permission;
|
|
} catch (_) {
|
|
// User is not a collaborator — treat as 'none'
|
|
}
|
|
|
|
if (['admin', 'write'].includes(permission)) {
|
|
console.log(`User has '${permission}' permission, skipping.`);
|
|
return;
|
|
}
|
|
|
|
// Already labeled — avoid spamming on every push
|
|
if (labels.includes('wrong-base-branch')) {
|
|
core.setFailed("PR must target `dev`, not `main`.");
|
|
return;
|
|
}
|
|
|
|
// Ensure the label exists
|
|
try {
|
|
await github.rest.issues.getLabel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
name: 'wrong-base-branch',
|
|
});
|
|
} catch (err) {
|
|
if (err.status === 404) {
|
|
await github.rest.issues.createLabel({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
name: 'wrong-base-branch',
|
|
color: 'd73a4a',
|
|
description: 'PR is targeting the wrong base branch',
|
|
});
|
|
}
|
|
}
|
|
|
|
await github.rest.issues.addLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
labels: ['wrong-base-branch'],
|
|
});
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
body: [
|
|
'## Wrong target branch',
|
|
'',
|
|
'This PR targets `main`, but contributions must go through `dev` first.',
|
|
'',
|
|
'To fix this, click **Edit** next to the PR title and change the base branch to `dev`.',
|
|
'',
|
|
'**This PR will be automatically closed in 24 hours if the base branch has not been updated.**',
|
|
'',
|
|
'> _If you need to merge directly to `main`, contact a maintainer._',
|
|
].join('\n'),
|
|
});
|
|
|
|
core.setFailed("PR must target `dev`, not `main`.");
|