Add workflow to prevent quick changes to website dependencies, update website handbook page (#44765)

Changes:
- Added a new Github workflow that runs on branches that change the
website's dependencies (website/package-lock.json or
website/package.json), and fails for 72 hours after a change to those
files have been made. After 72 hours, if the workflow has not run again
on a pull request, the workflow can be rerun to give a PR a passing
status.
- Updated the website handbook page to document this process.


@lukeheath After this is merged, I will need help setting up a branch
protection rule to require a passing status from this workflow to merge
pull requests that change the website's dependencies

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Added an automated workflow to enforce a wait period before website
dependency updates can proceed, preventing premature merges.
* Added scheduled and manual re-triggering for recent failed workflow
runs to ensure dependency checks are retried without manual
intervention.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Eric
2026-05-08 14:10:03 -05:00
committed by GitHub
parent 1318418444
commit 0ce19b4578
2 changed files with 94 additions and 0 deletions
@@ -0,0 +1,89 @@
name: Incubate website dependency changes
on:
pull_request:
branches: [main]
paths:
- 'website/package.json'
- 'website/package-lock.json'
schedule:
- cron: '0 7 * * *' # 7am UTC nightly
workflow_dispatch:
permissions:
contents: read
actions: write # needed for `gh run rerun`
concurrency:
group: incubate-website-deps-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: false
jobs:
check:
runs-on: ubuntu-22.04
env:
INCUBATION_HOURS: 72
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
if: github.event_name == 'pull_request'
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with:
fetch-depth: 0 # full history needed to compute commit timestamp
- name: Verify 72-hour incubation
if: github.event_name == 'pull_request'
shell: bash
run: |
set -euo pipefail
git fetch --no-tags origin "${GITHUB_BASE_REF}"
THRESHOLD_SECONDS=$(( INCUBATION_HOURS * 3600 ))
# Confirm this PR branch actually touches the dep files.
HAS_DEP_CHANGE=$(git log -1 --format=%H \
"origin/${GITHUB_BASE_REF}..HEAD" \
-- website/package.json website/package-lock.json || true)
if [ -z "${HAS_DEP_CHANGE}" ]; then
echo "No website dependency changes on this branch relative to ${GITHUB_BASE_REF}."
exit 0
fi
# Use the wall-clock creation time of the *earliest* run for this workflow
# on this PR — unaffected by force-pushed commit timestamps.
EARLIEST_RUN_TS=$(gh run list \
--repo "${GITHUB_REPOSITORY}" \
--workflow "${{ github.workflow }}" \
--event pull_request \
--branch "${{ github.head_ref }}" \
--limit 100 \
--json databaseId,createdAt \
--jq 'sort_by(.createdAt) | .[0].createdAt' )
EARLIEST_RUN_EPOCH=$(date -d "${EARLIEST_RUN_TS}" +%s)
AGE=$(( $(date +%s) - EARLIEST_RUN_EPOCH ))
AGE_HOURS=$(( AGE / 3600 ))
if [ "${AGE}" -lt "${THRESHOLD_SECONDS}" ]; then
REMAINING=$(( (THRESHOLD_SECONDS - AGE + 3599) / 3600 ))
echo "::error::Website dependency files were changed ${AGE_HOURS}h ago. Incubation period is ${INCUBATION_HOURS}h. Wait ~${REMAINING}h, then re-run this check."
exit 1
fi
echo "Incubation complete: last website dep change was ${AGE_HOURS}h ago."
- name: Re-run previously-failed PR checks (nightly)
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
shell: bash
run: |
set -euo pipefail
# Find recent failed runs of THIS workflow on pull_request events and re-trigger them.
# As wall-clock time advances, the git-log age in each rerun grows past the 72h threshold
# and the run passes — flipping the required check green without requiring a force-push.
gh run list \
--repo "${GITHUB_REPOSITORY}" \
--workflow "${{ github.workflow }}" \
--event pull_request \
--status failure \
--created ">$(date -u -d '7 days ago' '+%Y-%m-%dT%H:%M:%SZ')" \
--limit 100 \
--json databaseId \
--jq '.[].databaseId' \
| while read -r run_id; do
echo "Re-running failed run ${run_id}"
gh run rerun "${run_id}" --repo "${GITHUB_REPOSITORY}" || true
done
+5
View File
@@ -134,6 +134,11 @@ Every week, the website maintainer looks for any new [code scanning alerts](http
- If the alert is for a dependency that runs in production, the maintainer will upgrade it to a version that is not affected by the vulnerability.
- If the alert is for a devDependency or a dependency of a devDependency, the maintainer will dismiss the alert as a false-positive, because it does not affect the production environment.
## Incubate website dependency changes
Pull requests that modify `website/package.json` or `website/package-lock.json` must wait 72 hours after the most recent commit to either file before they can merge to `main`. This incubation period gives the maintainer time to spot regressions or supply-chain concerns introduced by a dependency bump before it reaches the website's production environment.
The `Incubate website dependency changes` GitHub Actions workflow enforces this as a required status check. The check runs on every PR that touches those files and re-evaluates open PRs nightly, once 72 hours have elapsed the check turns green automatically. Pushing a new commit to either file resets the clock.
<meta name="maintainedBy" value="lukeheath">