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
61 changes: 61 additions & 0 deletions .github/workflows/generate-index.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Regenerate index.yaml

# index.yaml is what datumctl reads, and it is fully derived from plugins/*.yaml.
# Rather than asking every contributor (and the release bot) to regenerate and
# commit it in their PR, it is reconciled here on merge: when plugins/ changes on
# main, regenerate the index and commit it straight back to main.
#
# main is not a protected branch, so the built-in GITHUB_TOKEN can push directly
# — no app token needed. The commit touches only index.yaml (not plugins/**) and
# GITHUB_TOKEN pushes don't retrigger workflows, so this never loops.
on:
push:
branches: [main]
paths:
- "plugins/**"
workflow_dispatch:

# Serialize so two quick merges can't race to push index.yaml.
concurrency:
group: regenerate-index
cancel-in-progress: false

permissions:
contents: write

jobs:
regenerate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Install tooling
run: pip install --quiet "PyYAML>=6"

- name: Regenerate index.yaml
run: python3 scripts/generate_index.py

- name: Commit and push if index.yaml changed
run: |
if git diff --quiet -- index.yaml; then
echo "index.yaml already in sync; nothing to do."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add index.yaml
git commit -m "chore: regenerate index.yaml"
# Rebase onto any commits that landed while this ran, then push.
for attempt in 1 2 3; do
if git pull --rebase origin main && git push; then
echo "Pushed regenerated index.yaml."
exit 0
fi
echo "Push attempt $attempt failed; retrying."
done
echo "::error::Failed to push regenerated index.yaml after 3 attempts."
exit 1
11 changes: 4 additions & 7 deletions .github/workflows/validate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,10 @@ jobs:
- name: Install tooling
run: pip install --quiet "jsonschema[format-nongpl]>=4" "PyYAML>=6"

# index.yaml is what datumctl reads, and it is fully derived from
# plugins/*.yaml. Fail if the committed index doesn't match what the
# generator produces, so main's index can never drift from the manifests.
- name: Check index.yaml is in sync with plugins/
run: python3 scripts/generate_index.py --check

# Schema-validate every manifest and prove every advertised download
# actually resolves and matches its checksum.
# actually resolves and matches its checksum. index.yaml is a generated
# artifact reconciled on merge (see generate-index.yaml), so it is not
# reviewed or gated here — contributors and the release bot only ever touch
# plugins/*.yaml.
- name: Validate manifests and verify release assets
run: python3 scripts/verify_manifests.py
12 changes: 3 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,9 @@ datumctl ipam pool list
## Submitting a plugin

1. Add the `datumctl-plugin` topic to your plugin's GitHub repository.
2. Open a pull request adding `plugins/<your-plugin-name>.yaml`, following the [schema](schema/plugin-v1alpha1.json).
3. Regenerate the index and commit it alongside your manifest:

```sh
python3 scripts/generate_index.py
```

[`index.yaml`](index.yaml) — the file `datumctl` actually reads — is derived entirely from `plugins/*.yaml`, and CI fails if the two drift.
4. CI validates every manifest: schema conformance, that each download URL resolves, and that each SHA256 matches the published archive. A weekly [health check](.github/workflows/catalog-health.yaml) re-verifies the whole catalog so a plugin's links can't rot unnoticed.
2. Open a pull request adding `plugins/<your-plugin-name>.yaml`, following the [schema](schema/plugin-v1alpha1.json). That's the only file you edit.
3. CI validates every manifest: schema conformance, that each download URL resolves, and that each SHA256 matches the published archive. A weekly [health check](.github/workflows/catalog-health.yaml) re-verifies the whole catalog so a plugin's links can't rot unnoticed.
4. On merge, [`index.yaml`](index.yaml) — the file `datumctl` actually reads — is regenerated from `plugins/*.yaml` and committed automatically. You never edit it by hand. (To preview locally: `python3 scripts/generate_index.py`.)

## Plugin manifest format

Expand Down
Loading