Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 39 additions & 83 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,48 @@
# Shared GitHub Actions

Reusable GitHub workflows for organization-owned and personal repositories.
Shared scripts stay here; each repository keeps its configuration and pins
the workflow to a reviewed commit.
Each repository keeps its project configuration and pins the shared workflows
to a reviewed commit.

## Available workflows
## Node dependency maintenance

| Workflow | What it does | Get started |
| --- | --- | --- |
| Node maintenance | Fix security advisories, propose dependency upgrades, validate the project, and open one PR for review. | [Setup guide](docs/node-maintenance.md) |

## One maintenance PR per project

**Security fixes and routine upgrades, together in one PR.** Choose security-only
maintenance or limit routine upgrades to patch, minor, or major versions. Reruns
update the same PR, so each audit does not add another PR to review.

- **Combined review:** security fixes and routine upgrades in one maintenance PR. [Comparison](docs/node-maintenance.md#supported-projects).
- **Validation evidence:** a frozen install and selected project checks before review.
- **Clear decisions:** see what was fixed, which pins need review, and what is blocked.

The Node workflow follows your declared Node and npm/pnpm versions within its
[tested combinations](docs/node-maintenance.md#toolchain-selection). It requires a
standalone Node project. Project pins and deployment remain under your control.
The built-in GitHub token works; a GitHub App is optional.
Version 6 replaces the Docusaurus interface. Existing installations must follow
the [migration checklist and rollout order](docs/node-migration.md).
The [setup guide](docs/node-maintenance.md#set-it-up) includes a pinned caller workflow,
local validation checks, and steps for the first audit.

## Shared defaults for multiple installations

Integration version 6 lets many projects follow one authoritative JSON defaults
file in any public GitHub repository. Each project keeps local overrides and its
own validation/deployment setup. Conflicting declarations fail preflight and update
one reusable configuration issue; nothing is migrated automatically.

See [shared defaults setup and fleet updates](docs/shared-defaults.md). The
[recommended defaults](defaults/node-maintenance.json) select Node 24, pnpm 11.21.0 or npm 11.9.0,
and a minimum ten-day cooldown.
Maintain dependencies for a standalone Node application, library, or website
using npm or pnpm. The workflow attempts compatible security fixes, optionally
proposes routine upgrades, and validates the result with a frozen install and
your project's checks.

## Default schedule and overrides
All audit kinds maintain **one open dependency PR per repository**. Reruns update
that PR rather than opening a PR for each dependency. Reports show the proposed
versions, validation results, and any blocked findings. Nothing merges automatically.

With **integration version 6**, projects that follow the
[recommended defaults](defaults/node-maintenance.json) inherit this schedule:
**[Set up Node maintenance](docs/node-maintenance.md)** for supported versions,
complete npm and pnpm instructions, and your first audit.

```json
{
"maintenance": {"mode": "security-and-maintenance"},
"schedule": {
"security": ["0 2 * * 1"],
"upgrades": ["0 2 1 */3 *"]
}
}
```
## Choose your maintenance policy

Security checks run every Monday at 02:00 UTC. Routine upgrades run at 02:00 UTC
on the first day of January, April, July, and October. Upgrade runs also check
security. All runs maintain the same dependency PR.

To change the default for your projects, edit `schedule` in your shared defaults
file. To override one project, set `schedule.security` or `schedule.upgrades` in
that project's `.github/node-maintenance.json`. Each local list replaces the inherited
list of the same name; omitted lists continue to inherit.

For example, these local fields keep inherited security checks and make routine
upgrades manual-only:

```json
{
"maintenance": {"mode": "security-only"},
"schedule": {"upgrades": []}
}
```

Keep the caller workflow's `on.schedule` cron entries equal to the combined
resolved lists. A shared-defaults edit does not rewrite installed workflow files;
preflight reports a mismatch until their triggers are updated. The
[scheduling guide](docs/audit-schedules.md) covers caller setup, other cadences,
manual runs, and cron-list shorthand. Existing explicit local schedules keep
overriding shared defaults.

## Reference

- [Setup, first run, and updates](docs/node-maintenance.md)
- [Maintenance policy](node/maintenance.md)
- [Caller template](node/caller.yml)
- [Integration contract](node/contract.json)

Currently supports GitHub.com. The Node implementation retains its
BSD 3-Clause license.
| Setup | Automatic security checks | Automatic routine upgrades |
| --- | --- | --- |
| Basic setup in the guide | Weekly | Disabled; run upgrades manually |
| Follow this repository's shared defaults | Weekly | Every three months |

Both setups use a ten-day release cooldown. The basic setup follows your
supported project toolchain. The [shared defaults](defaults/node-maintenance.json)
require Node 24 and pnpm 11.21.0 or npm 11.9.0. Local settings can override
inherited defaults; conflicts with project declarations fail preflight and
update one reusable configuration issue.

For several installations, [share defaults from a public GitHub JSON file](docs/shared-defaults.md).
To change cadence, disable automatic upgrades, or run an audit on demand, use
the [scheduling guide](docs/audit-schedules.md). GitHub cron entries remain in
each repository's caller workflow and must match its resolved configuration.

## Documentation

- [Setup, first run, updates, and troubleshooting](docs/node-maintenance.md)
- [Schedules and manual audits](docs/audit-schedules.md)
- [Shared defaults for multiple installations](docs/shared-defaults.md)
- [Maintenance behavior, reports, and permissions](node/maintenance.md)
- [Migrate an earlier Docusaurus installation](docs/node-migration.md)
- [Caller template](node/caller.yml) and [integration contract](node/contract.json)

Supports GitHub.com. The Node implementation retains its BSD 3-Clause license.
191 changes: 102 additions & 89 deletions docs/audit-schedules.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# Security and upgrade schedules
# Schedules and manual audits

Integration contract **version 6** supports separate automatic cadences and a
manual choice of audit work. The [recommended shared defaults](../defaults/node-maintenance.json)
check security weekly and propose routine upgrades quarterly. A security-only
run proposes dependency changes only
when before/after audit evidence confirms a security fix. Blocked findings and
reports remain available in the Actions run summary and artifacts.
Each installation keeps its policy in `.github/node-maintenance.json` and its
GitHub triggers in `.github/workflows/dependency-audit.yml`. **Update both when
you change cadence.** Shared defaults do not rewrite workflow files.

The [basic setup](node-maintenance.md#set-it-up) checks security weekly and leaves
routine upgrades manual. The [recommended shared defaults](../defaults/node-maintenance.json)
check security weekly and propose routine upgrades every three months. Both use
integration version 6 and maintain the same dependency PR.

## Weekly security, quarterly upgrades

Set these fields in the installation's `.github/node-maintenance.json`, keeping its
directory, toolchain, shared defaults source, and other settings:
For local policy, set these fields in `.github/node-maintenance.json`. Keep your
existing directory, validation script, and other project settings:

```json
{
"directory": "project",
"toolchain": {},
"maintenance": {
"mode": "security-and-maintenance",
"upgradeScope": "major"
Expand All @@ -27,26 +27,15 @@ directory, toolchain, shared defaults source, and other settings:
}
```

This checks security every Monday at 02:00 UTC. Routine upgrades run at 02:00 UTC
on the first day of January, April, July, and October. An upgrade run also checks
security. The ten-day release delay and selected upgrade scope still apply.

For weekly security and **manual-only upgrades**, use
`"maintenance": {"mode": "security-only"}` and `"upgrades": []`. To run both
kinds of audit manually only, use `"schedule": {"security": [], "upgrades": []}`.
An omitted list in the schedule object is empty. Routine scheduled upgrades need
both an upgrades cadence and `maintenance.mode=security-and-maintenance`.
If you inherit the recommended shared defaults, these fields are already supplied;
leave them out locally unless you want to override them.

## Update the caller too
Security checks run every Monday at 02:00 UTC. Upgrade runs check security and
routine upgrades at 02:00 UTC on the first day of January, April, July, and
October. Both kinds obey the release cooldown and project constraints. Routine
upgrades also obey `maintenance.upgradeScope`.

Choose a reviewed revision whose `node/contract.json` declares version 6 or
later. Start from that revision's [caller template](../node/caller.yml).
Replace both repository and revision markers with the shared repository name and
the same full commit SHA. Earlier Docusaurus workflow paths do not implement the Node interface;
follow the [migration checklist](node-migration.md).

Replace the template's schedule marker with the unique cron entries from both
lists. For the weekly/quarterly example:
In the [setup guide's caller](node-maintenance.md#3-add-the-caller-workflow), use:

```yaml
'on':
Expand All @@ -64,78 +53,102 @@ lists. For the weekly/quarterly example:
- upgrades
```

Keep the template's audit input forwarding:
Keep the remaining caller jobs, permissions, SHA pins, and audit input forwarding:

```yaml
with:
audit-kind: ${{ inputs.audit-kind || 'auto' }}
```

GitHub reads cron entries from the caller workflow. Keep its entries identical
to the resolved JSON lists, including any inherited schedule; preflight rejects
a mismatch before dependency changes. If
both lists contain the same cron expression, include it once in the workflow;
that event runs one combined audit. Different expressions that happen to fire
at the same time can enqueue separate runs. They still update the same PR.
When both lists are empty, omit `on.schedule` from the workflow.
## Change or disable a cadence

GitHub uses the exact triggering cron expression to select the work. Scheduling
can be delayed by GitHub; this policy does not infer cadence from the current
clock or require an external scheduler. See [GitHub's schedule and manual input
reference](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax).
Each list accepts one or more five-field cron expressions. Replace a list to
change that cadence. For example, `"upgrades": ["0 2 1 * *"]` selects monthly
upgrades. Add the same expression to the caller's `on.schedule`.

## Run upgrades on demand
To keep weekly security and make upgrades **manual-only**, merge these fields
into the local configuration:

Open **Actions → Node dependency audit → Run workflow** on the default
branch. Choose **security** for security fixes only, or **upgrades** for security
plus routine upgrades. The choice applies to this run and does not change your
automatic policy. It still obeys `maintenance.upgradeScope`, cooldown, project
constraints, frozen install, and the selected project checks.
```json
{
"maintenance": {"mode": "security-only"},
"schedule": {
"security": ["0 2 * * 1"],
"upgrades": []
}
}
```

Remove the quarterly cron entry from the caller. Setting the mode alone is not
enough: a nonempty upgrades list requires `security-and-maintenance` mode.

For **manual-only audits of both kinds**, set:

```json
{"schedule": {"security": [], "upgrades": []}}
```

From the CLI:
Remove `on.schedule` from the caller and keep `workflow_dispatch`.

When shared defaults are involved, local lists replace inherited lists per kind:

| Local setting | With an inherited cadence | Without an inherited cadence |
| --- | --- | --- |
| List omitted | Keeps the inherited list | Uses an empty list |
| `[]` | Disables that cadence | Disables that cadence |
| Nonempty list | Replaces that cadence | Defines that cadence |

An empty schedule object inherits both lists when available. Use explicit empty
lists to disable inherited cadences. These rules apply to the schedule object;
the older cron-list form is described below.

## Keep GitHub triggers aligned

The caller's `on.schedule` must contain the unique cron entries from **both
resolved lists**, including inherited values. Preflight checks this even for
manual dispatch. A mismatch fails before dependency changes and updates the
single configuration issue. Fix the caller or local overrides, then rerun.

If both lists contain the same expression, include it once in the caller; that
event runs a combined security and upgrade audit. Different expressions that
happen to fire at the same time can enqueue separate runs. They still maintain
the same PR.

GitHub selects work using the exact triggering cron expression. Runs can be
delayed; selection does not depend on the time the runner starts. See
[GitHub's scheduling reference](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onschedule).

## Run an audit on demand

Open **Actions → Node dependency audit → Run workflow** on your repository's
default branch. Choose **security** for security fixes only, or **upgrades** for
security plus routine upgrades. The choice applies only to this run and does not
change automatic policy. The cooldown, upgrade scope, and validation still apply.

From a checkout of the repository, you can also use:

```sh
gh workflow run dependency-audit.yml --ref main -f audit-kind=security
gh workflow run dependency-audit.yml --ref main -f audit-kind=upgrades
```

Use your repository's default branch if it is not `main`.

## One maintained PR

All audit kinds use the same `maintenance/dependency-audit` branch and open PR.
An outdated proposal updates that PR. If the files, report, base branch, and
validation result are unchanged, a rerun creates no commit, push, or PR edit.
Run timestamps and workflow links alone do not count as changes. New report
findings update the same PR body without another dependency commit.
If validation now fails for the same files, the workflow
updates the report and marks the existing PR as a draft without another push.
A run with no qualifying changes creates no PR and leaves an
existing proposal intact; read that run's summary for current findings. After a
PR is merged or closed, a later qualifying proposal can open the next PR.

The report leads with proposed dependency changes and installation and project validation.
Routine-only headlines show the update count and validation status; security proposals
also show confirmed fix counts. Existing blocked, unchanged findings appear as
neutral background, with severities and constraints in expandable details.
Newly reported findings remain visible. Passing project checks alone does not establish
that a security finding was fixed. See [reports and PRs](../node/maintenance.md#reports-and-prs).

## Shared defaults and existing installations

`maintenance.mode`, `maintenance.upgradeScope` and schedule lists can come from
[shared defaults](shared-defaults.md); local fields override them. Each local
`schedule.security` or `schedule.upgrades` list replaces that inherited list;
an omitted list inherits, and `[]` disables that cadence. An empty object
inherits both lists. The recommended file selects weekly security and quarterly
upgrades. GitHub still requires matching cron entries in each consumer workflow.
A live schedule change can therefore require updates to those local triggers;
until then, preflight reports the mismatch in the reusable configuration issue.

A cron-list shorthand (`"schedule": ["..."]`) is also accepted. It uses one
configured maintenance mode rather than selecting separate kinds per cron.
Without an explicit mode it uses `security-and-maintenance`. Use the schedule
object shown above for separate cadences and the quieter security-only default.
Omitted schedules do not add GitHub triggers; define the schedule explicitly.

Public installation and execution use only the checked-in caller, actions,
and runtime. No private tooling is required.
Run the command for the kind you want. Replace `main` if your default branch has
another name. Other dispatch branches are rejected.

All kinds maintain the same `maintenance/dependency-audit` branch and open PR.
A run without qualifying dependency changes leaves an existing proposal untouched;
read the current run summary for its findings. After that PR is merged or closed,
a later qualifying proposal can open the next PR. See
[reports and PR behavior](../node/maintenance.md#reports-and-prs).

## Existing cron-list configurations

The runtime also accepts `"schedule": ["0 2 * * 1"]`. This form runs the same
configured maintenance mode on every cron event; it does not select a kind per
expression. Without an explicit or inherited mode, it uses
`security-and-maintenance`. A local cron list replaces an inherited schedule
object entirely.

Omitting `schedule` also retains that mode default and an internal January 30
cron fallback. It does not create a GitHub trigger. For new installations, use
the explicit schedule object above so cadence and manual-only policy are clear.
Loading
Loading