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
54 changes: 11 additions & 43 deletions .github/workflows/catalog-health.yaml
Original file line number Diff line number Diff line change
@@ -1,53 +1,21 @@
name: Catalog health

# The catalog points at release assets that live in other repositories, which
# can be deleted, retagged, or re-cut after a plugin lands here. PR validation
# only catches breakage at merge time, so this re-verifies every plugin's
# download links and checksums on a schedule and opens an issue if the catalog
# has rotted — before a user hits it during `datumctl plugin install`.
on:
schedule:
- cron: "0 12 * * 1" # Mondays, 12:00 UTC
- cron: "0 12 * * 1"
workflow_dispatch:

permissions:
contents: read
issues: write

jobs:
verify-assets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

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

- name: Install tooling
run: pip install --quiet "jsonschema[format-nongpl]>=4" "PyYAML>=6"

- name: Verify every plugin's download links and checksums
run: python3 scripts/verify_manifests.py

- name: Open an issue if the catalog is unhealthy
if: failure()
env:
GH_TOKEN: ${{ github.token }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
gh label create catalog-health \
--color b60205 \
--description "A plugin download link or checksum is broken" 2>/dev/null || true

body=$(printf 'The scheduled catalog health check failed: one or more plugin download URLs no longer resolve, or their checksums no longer match the published release assets.\n\nUsers may be unable to install or verify the affected plugin(s) with datumctl until this is fixed. See the run log for the specific plugin and platform:\n\n%s\n' "$RUN_URL")

number=$(gh issue list --state open --label catalog-health --json number --jq '.[0].number // empty')
if [ -n "$number" ]; then
gh issue comment "$number" --body "$body"
else
gh issue create \
--title "Catalog health check is failing" \
--label catalog-health \
--body "$body"
fi
health:
uses: datum-cloud/actions/.github/workflows/plugin-catalog-health.yaml@v1.27.1
permissions:
contents: read
issues: write
with:
name: milo-os
description: Portable CLI plugins for the Milo platform
owner: milo-os
homepage: https://github.com/milo-os/cli-plugins
5 changes: 3 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ permissions:

jobs:
ci:
uses: datum-cloud/actions/.github/workflows/ci-basic.yaml@v1.26.0
uses: datum-cloud/actions/.github/workflows/plugin-catalog-validate.yaml@v1.27.1
with:
run: python3 -m venv "$RUNNER_TEMP/venv" && "$RUNNER_TEMP/venv/bin/pip" install --quiet 'jsonschema[format-nongpl]==4.26.0' 'PyYAML==6.0.3' && "$RUNNER_TEMP/venv/bin/python" scripts/verify_manifests.py
# The branch rules require the "ci / Build and test" check.
check-name: Build and test
52 changes: 0 additions & 52 deletions .github/workflows/generate-index.yaml

This file was deleted.

23 changes: 23 additions & 0 deletions .github/workflows/rebuild-index.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Rebuild index

on:
push:
branches: [main]
paths:
- "plugins/**"
workflow_dispatch:

permissions:
contents: read

jobs:
rebuild:
uses: datum-cloud/actions/.github/workflows/plugin-catalog-index.yaml@v1.27.1
with:
name: milo-os
description: Portable CLI plugins for the Milo platform
owner: milo-os
homepage: https://github.com/milo-os/cli-plugins
secrets:
app-id: ${{ secrets.PLUGIN_INDEX_APP_ID }}
app-private-key: ${{ secrets.PLUGIN_INDEX_APP_PRIVATE_KEY }}
28 changes: 28 additions & 0 deletions .github/workflows/scan-releases.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Scan releases

on:
schedule:
- cron: "17 6 * * *"
workflow_dispatch:
inputs:
dry-run:
description: Report which plugins are behind without opening pull requests
type: boolean
default: false
plugin:
description: Scan only this plugin, by name
type: string
default: ""

permissions:
contents: read

jobs:
scan:
uses: datum-cloud/actions/.github/workflows/plugin-catalog-scan.yaml@v1.27.1
with:
dry-run: ${{ inputs.dry-run || false }}
plugin: ${{ inputs.plugin || '' }}
secrets:
app-id: ${{ secrets.PLUGIN_INDEX_APP_ID }}
app-private-key: ${{ secrets.PLUGIN_INDEX_APP_PRIVATE_KEY }}
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ Milo services ship their own command-line experiences as plugins. This catalog i

| Name | Description |
|------|-------------|
| [assistant](plugins/assistant.yaml) | Chat with Patch, the Datum Cloud assistant, and browse your conversation history |
| [billing](plugins/billing.yaml) | View metered usage and spend for your organization or project |
| [ipam](plugins/ipam.yaml) | Manage IP address space (pools and prefixes) across the platform |
| [search](plugins/search.yaml) | Search for resources across the platform by kind, name, and project scope |
| [telemetry](plugins/telemetry.yaml) | Query logs for your Datum Cloud projects |

## Using this catalog
Expand Down Expand Up @@ -39,9 +41,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). That's the only file you edit.
2. Open a pull request adding `plugins/<your-plugin-name>.yaml`, following the [schema](https://github.com/datum-cloud/actions/blob/v1.27.1/scripts/plugin-catalog/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`.)
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.

## Plugin manifest format

Expand All @@ -66,3 +68,7 @@ spec:
### Binary naming

Plugins in this catalog use the portable **`milo-<name>`** binary convention (for example `milo-ipam`). `datumctl` recognizes both `milo-` and `datumctl-` prefixed plugins, so a single `milo-<name>` binary works as a `datumctl` subcommand and as a standalone tool on your `PATH`. The binary inside each archive must be named `milo-<name>` (or `milo-<name>.exe` on Windows).

## How this catalog runs

Validation, the index rebuild, a daily scan for newer plugin releases, and the weekly health check all come from the shared [plugin catalog workflows](https://github.com/datum-cloud/actions/blob/main/docs/plugin-catalog/README.md) in `datum-cloud/actions`.
Loading
Loading