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
83 changes: 83 additions & 0 deletions .github/workflows/node-fleet-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Node fleet setup
'on':
workflow_call:
inputs:
inventory-repository:
type: string
default: ''
description: Repository containing the inventory; empty selects the caller.
inventory-path:
type: string
default: defaults/node-repositories.json
description: JSON inventory next to the shared defaults.
inventory-ref:
type: string
default: ''
description: Branch, tag or SHA; empty selects the default branch.
secrets:
read-token:
required: false
description: Optional token with Contents and Actions read access to private listed repositories.
workflow_dispatch:
inputs:
inventory-repository:
type: string
default: ''
description: Repository containing the inventory; empty selects this repository.
inventory-path:
type: string
default: defaults/node-repositories.json
description: JSON inventory path.
inventory-ref:
type: string
default: ''
description: Branch, tag or SHA; empty selects the default branch.
permissions:
contents: read
concurrency:
group: node-fleet-setup-${{ github.repository }}
cancel-in-progress: false
jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
actions: read
steps:
- name: Check listed installations
uses: $/node/fleet-check
env:
GH_TOKEN: ${{ secrets.read-token || github.token }}
with:
inventory-repository: ${{ inputs.inventory-repository }}
inventory-path: ${{ inputs.inventory-path }}
inventory-ref: ${{ inputs.inventory-ref }}
- name: Retain the setup report
if: ${{ always() && !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: node-fleet-report
path: ${{ runner.temp }}/node-fleet-report.json
if-no-files-found: warn
report:
needs: check
if: ${{ always() && !cancelled() }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
actions: read
issues: write
steps:
- name: Read the report
id: report
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with:
name: node-fleet-report
path: ${{ runner.temp }}/node-fleet-report
- name: Maintain the central setup issue
if: ${{ steps.report.outcome == 'success' }}
uses: $/node/fleet-report
env:
GH_TOKEN: ${{ github.token }}
67 changes: 40 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,61 @@
# Shared GitHub Actions

Reusable GitHub workflows for organization-owned and personal repositories.
Each repository keeps its project configuration and pins the shared workflows
to a reviewed commit.
Reusable workflows for organization-owned and personal repositories. Each
installation keeps its configuration and pins shared workflow code to a reviewed
commit. Supports GitHub.com.

## Node dependency maintenance
## Available workflows

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.
| Workflow | Use it to | Get started |
| --- | --- | --- |
| Node dependency maintenance | Attempt compatible security fixes, optionally propose routine upgrades, validate the project, and maintain one dependency PR. | [Setup guide](docs/node-maintenance.md) |
| Node fleet setup | Check a list of maintenance installations for broken setup or configuration drift, and maintain one central issue per list. | [Fleet setup guide](docs/node-fleet-setup.md) |

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.
The workflows are independent. Install maintenance in each Node repository you
want to maintain. Run the fleet checker from one repository to monitor those
installations. Fleet checks do not audit dependencies, install packages, or run
project scripts. Nothing merges or repairs configuration automatically.

**[Set up Node maintenance](docs/node-maintenance.md)** for supported versions,
complete npm and pnpm instructions, and your first audit.
## Node dependency maintenance

## Choose your maintenance policy
Supports standalone Node applications, libraries, and websites using npm or pnpm.
A maintenance run validates its proposal with a frozen install and your project's
checks. All audit kinds maintain **one open dependency PR per repository**;
reruns update that PR rather than opening one PR per dependency. Reports show
proposed versions, validation, and blocked findings.

| Setup | Automatic security checks | Automatic routine upgrades |
| Maintenance 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
Both examples 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.
require Node 24 and pnpm 11.21.0 or npm 11.9.0. Local overrides remain valid;
conflicting declarations fail preflight and update the repository's reusable
configuration issue. See the [setup guide](docs/node-maintenance.md) and
[scheduling guide](docs/audit-schedules.md).

## Manage several installations

Keep an authoritative [defaults file](docs/shared-defaults.md) in any public
GitHub repository. Optionally keep a [repository inventory](defaults/node-repositories.json)
beside it. The inventory names the expected defaults source and the repositories
that should follow it. You do not need to register either file here.

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.
The [fleet checker](docs/node-fleet-setup.md) inspects each default branch, honors
local overrides, and reports failed or unverifiable setup in the host repository.
It reuses one issue per inventory, closes it when every static check passes, and
reopens it on recurrence. Run it manually or add your own caller schedule.

## Documentation

- [Setup, first run, updates, and troubleshooting](docs/node-maintenance.md)
- [Schedules and manual audits](docs/audit-schedules.md)
- [Node maintenance: setup, first run, updates, and troubleshooting](docs/node-maintenance.md)
- [Fleet setup checks: inventory, caller, results, and limits](docs/node-fleet-setup.md)
- [Maintenance 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)
- [Maintenance caller template](node/caller.yml) and [integration contract](node/contract.json)

Supports GitHub.com. The Node implementation retains its BSD 3-Clause license.
The Node implementation retains its BSD 3-Clause license.
11 changes: 11 additions & 0 deletions defaults/node-repositories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"defaults": {
"repository": "hydra-ecosystem/github-actions",
"path": "defaults/node-maintenance.json",
"ref": "main"
},
"repositories": [
"hydra-ecosystem/hydra",
"hydra-ecosystem/omegaconf"
]
}
2 changes: 1 addition & 1 deletion docs/audit-schedules.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Schedules and manual audits
# Node maintenance schedules and manual audits

Each installation keeps its policy in `.github/node-maintenance.json` and its
GitHub triggers in `.github/workflows/dependency-audit.yml`. **Update both when
Expand Down
190 changes: 190 additions & 0 deletions docs/node-fleet-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# Check Node maintenance setup across repositories

Run one workflow to check whether several Node maintenance installations still
have a valid setup. It reads configuration and workflow files as data. It never
installs dependencies, executes project code, audits vulnerabilities, opens
repair PRs, or changes the listed repositories.

Use this alongside [Node dependency maintenance](node-maintenance.md). The two
workflows have separate callers and schedules. A fleet check creates or updates
one central issue in the repository running the checker.

## 1. Keep an inventory beside your defaults

For example, keep these files in your configuration repository:

```text
defaults/node-maintenance.json
defaults/node-repositories.json
```

The inventory contains the expected defaults source and 1 to 25 distinct
`owner/repository` names:

```json
{
"defaults": {
"repository": "owner/settings",
"path": "defaults/node-maintenance.json",
"ref": "main"
},
"repositories": [
"owner/application",
"owner/library",
"owner/website"
]
}
```

Change the source to your authoritative public defaults file. A listed
installation must inherit that repository/path/ref, either directly or through
another defaults source. Explicit local overrides remain valid and are checked
against that installation's project declarations. A repository that stops
following the expected source fails even if its current versions happen to match.

Use a branch ref for live defaults or a full commit SHA for fixed policy.
The inventory ref used to fetch this list is independent of the defaults ref
inside it. See [shared defaults](shared-defaults.md) for inheritance rules.

This repository's [inventory](../defaults/node-repositories.json) lists Hydra
and OmegaConf. Other maintainers can own their own files in their own repositories;
no registration here is required.

## 2. Choose where the checker and issue run

To check this repository's inventory, use **Actions → Node fleet setup → Run
workflow** after the workflow is merged. Its default inputs select
`defaults/node-repositories.json` on this repository's default branch. Set
`inventory-repository`, `inventory-path`, and `inventory-ref` to read another list.
An empty repository selects the host; an empty ref selects the inventory
repository's default branch.

To host the check elsewhere, add `.github/workflows/node-fleet-setup.yml` to that
repository's default branch:

```yaml
name: Node fleet setup
'on':
workflow_dispatch:
permissions:
contents: read
jobs:
setup:
permissions:
contents: read
actions: read
issues: write
uses: hydra-ecosystem/github-actions/.github/workflows/node-fleet-check.yml@REVIEWED_FULL_COMMIT_SHA
with:
inventory-repository: owner/settings
inventory-path: defaults/node-repositories.json
inventory-ref: main
```

Replace `REVIEWED_FULL_COMMIT_SHA` with a reviewed full SHA that contains
`node-fleet-check.yml`. Use your inventory location. Enable issues in the host
repository. Only the host needs issue-write permission; listed repositories do
not need a new workflow, extra write permission, or an issue opened in them.
Reports have the host repository's visibility.

For public repositories, the built-in token is sufficient. To read private
listed repositories or a private inventory in another repository, add a host
Actions secret `NODE_FLEET_READ_TOKEN` with **Contents: read** and **Actions: read**
access to the required repositories, then add this to the calling job:

```yaml
secrets:
read-token: ${{ secrets.NODE_FLEET_READ_TOKEN }}
```

The optional token goes only to the scanner. The reporter uses the host's
built-in token. Shared defaults sources remain public, as required by the
maintenance resolver. No private key or secret content is inspected.

## 3. Run and inspect results

Open **Actions → Node fleet setup → Run workflow** in the host. From a checkout
of that repository, you can also run:

```sh
gh workflow run node-fleet-setup.yml --ref main
```

Use your host's default branch name. For a direct run of this repository's
workflow, the filename is `node-fleet-check.yml` instead.

The run summary and `node-fleet-report` artifact contain one result per repository,
its exact checked default-branch commit, and an actionable diagnostic:

| Result | Meaning |
| --- | --- |
| `ok` | All supported static setup checks passed. |
| `failed` | Setup violates a checked requirement, such as mismatched Node policy or caller schedules. |
| `unverified` | A required observation was unavailable, such as inaccessible repository data, API limits, or an incomplete tree. It is not a pass. |

The scan continues after an individual repository fails. Any failed or unverified
result fails the scanner job and opens or updates one **Node fleet setup** issue
in the host. The reporter still runs after scan failures. A fully passing scan
closes that issue; recurrence reopens it. Repeated failures update the body
without per-run comments. An invalid or unreadable inventory also reports against
that list when its repository/path identity is valid.

Issue identity uses the inventory repository and path, so changing its contents
or ref keeps the same issue. Different paths have separate issues. Runs are
serialized in the host to avoid competing issue creation. Existing ambiguous
duplicate marked issues cause a reporting error instead of another issue.
Invalid inventory location inputs that cannot identify a safe list fail the
workflow without opening an issue.

## What the checker verifies

- Config exists at `.github/node-maintenance.json`; shared defaults resolve and
include the inventory's expected source.
- The project is standalone, has a supported Node and exact npm/pnpm declaration,
a compatible `engines.node` range, and an existing validation script.
- Lockfile format, mixed-lockfile restrictions, and pnpm release cooldown satisfy
the resolved configuration.
- The maintenance caller pins audit and publisher workflows from one repository
at the same full SHA. That revision declares Node integration version 6 and
contains both reusable workflows and supports the resolved toolchain. It does
not have to be the latest revision.
- Caller schedules match resolved policy, including bounds for the supported
numeric, range, list, step, and month/day name forms. The original cron text
is retained for event matching. Required job permissions, audit input
forwarding, publisher dependency/validation forwarding, manual choices, and
concurrency are present.
- The caller's audit and publisher jobs are unconditionally enabled. The
checker does not evaluate arbitrary GitHub expressions; a conditional job is
outside the supported caller contract and fails static setup.
The audit has no prerequisite jobs; the publisher depends only on the audit.
- Pinned reusable workflows have callable jobs, and every required input and
secret has an explicit caller mapping. Secret contents and effective
publication access are not tested.
- The maintenance workflow is enabled in GitHub Actions.

Each repository is read at one immutable default-branch commit. Shared defaults
reads are cached for the scan. Remote files are never executed or imported, and
symlinks/submodules are rejected for checked files. Files are bounded: inventory
and ordinary configuration files are at most 64 KiB, lockfiles at most 2 MB;
truncated or oversized repository trees cannot receive a passing verdict.

A static pass is not an end-to-end audit run. Installed Node/package-manager
versions, credential contents, effective PR-creation permissions, dependency
health, and project builds are labeled **not tested**. Use a manual maintenance
run to exercise installation, project checks, and publication.

## Optional: schedule the fleet check

There is no automatic fleet-check schedule by default. To check weekly, add a
schedule alongside `workflow_dispatch` in the host caller:

```yaml
'on':
schedule:
- cron: '0 3 * * 1'
workflow_dispatch:
```

This runs Mondays at 03:00 UTC. It is independent of the security and upgrade
cadences in each maintenance installation; do not add the fleet cron to those
installations' maintenance configuration.
3 changes: 3 additions & 0 deletions docs/node-maintenance.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Use these workflows for a standalone Node application, library, or website.
They attempt compatible security fixes, optionally propose routine upgrades,
and validate the result before opening or updating one maintenance PR.

This guide installs maintenance in one repository. To monitor setup across several
installations, use the separate [fleet setup checker](node-fleet-setup.md).

Already using the earlier Docusaurus workflows? Follow the
[migration checklist](node-migration.md) instead.

Expand Down
Loading
Loading