Skip to content
Open
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
76 changes: 57 additions & 19 deletions .github/workflows/notify-umbrella.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# notify-umbrella — tell the umbrella a repo's docs changed, so it rebuilds within minutes
# instead of waiting for its daily cron (MIP-0070 §5.5). Modelled on h0ffmann/nix-config's
# profile-ping.yml reusable workflow — a plain repository_dispatch, no checkout needed on either
# side.
# notify-umbrella — tell the umbrella every push to main (`submodule-updated`), so
# pointer-sync.yml can move pointers on event instead of its daily cron, and that a repo's docs
# changed too (`submodule-docs-updated`) when the push touches README.md or docs/**, so
# docs.yml rebuilds within minutes (MIP-0070 §5.5, MIP-0076 §5.5 step 1). Modelled on
# h0ffmann/nix-config's profile-ping.yml reusable workflow — a plain repository_dispatch, no
# checkout needed on either side: the docs check reads the compare API instead of git.
#
# A consumer adds about three lines:
# A consumer adds about three lines, no `paths:` filter — this workflow decides for itself which
# event types a given push earns:
#
# on:
# push:
# branches: [main]
# paths: [README.md, docs/**]
# jobs:
# notify:
# uses: marola-dev/marola-devkit/.github/workflows/notify-umbrella.yml@v0.5.0
Expand All @@ -28,9 +30,9 @@ on:
type: string
default: marola-dev/marola
event-type:
description: "repository_dispatch event_type the umbrella's docs workflow listens for."
description: "Deprecated, ignored (MIP-0076): every call now sends submodule-updated, plus submodule-docs-updated on a docs change. Kept declared so a caller still passing it doesn't fail GitHub's reusable-workflow input check."
type: string
default: submodule-docs-updated
default: ""
runner:
description: "Runner label for the dispatch job — a reusable workflow's runs-on resolves in the caller's repository."
type: string
Expand All @@ -47,26 +49,62 @@ jobs:
runs-on: ${{ inputs.runner }}
timeout-minutes: 2
steps:
- name: repository_dispatch ${{ inputs.event-type }} -> ${{ inputs.umbrella }}
# A reusable workflow can only keep or lower the caller's permissions, and every caller sets
# permissions: {} — so this reads the compare API instead of checking the repo out. Even a
# token with no declared scope can read a public repo's API.
- name: Did this push touch README.md or docs/**?
id: docs
env:
TOKEN: ${{ github.token }}
BEFORE: ${{ github.event.before }}
SHA: ${{ github.sha }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
changed=false
if [ -z "${BEFORE:-}" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
changed=true # first push on the branch: no prior ref to compare against
else
resp="$RUNNER_TEMP/notify-umbrella-compare.json"
code="$(curl -sS -o "$resp" -w '%{http_code}' \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/$REPO/compare/$BEFORE...$SHA")"
if [ "$code" != 200 ]; then
changed=true # before unknown to the API (e.g. a force-push): take the conservative path
elif [ "$(jq '(.files // []) | length' "$resp")" -ge 300 ]; then
changed=true # the compare API caps its file list at 300: the list may be truncated
elif jq -e '(.files // []) | any(.[]; .filename == "README.md" or (.filename | startswith("docs/")))' "$resp" >/dev/null; then
changed=true
fi
fi
echo "changed=$changed" >>"$GITHUB_OUTPUT"

- name: repository_dispatch -> ${{ inputs.umbrella }}
env:
TOKEN: ${{ secrets.token }}
UMBRELLA: ${{ inputs.umbrella }}
EVENT_TYPE: ${{ inputs.event-type }}
REPO: ${{ github.repository }}
SHA: ${{ github.sha }}
DOCS_CHANGED: ${{ steps.docs.outputs.changed }}
run: |
set -euo pipefail
if [ -z "$TOKEN" ]; then
echo "::notice::no umbrella-dispatch token set in $REPO — skipping; the umbrella's daily cron still picks this up"
exit 0
fi
body="$(jq -nc --arg repo "$REPO" --arg sha "$SHA" --arg event "$EVENT_TYPE" \
'{event_type: $event, client_payload: {repo: $repo, sha: $sha}}')"
code="$(curl -sS -o "$RUNNER_TEMP/notify-umbrella-response.txt" -w '%{http_code}' -X POST \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/$UMBRELLA/dispatches" -d "$body")"
if [ "$code" != 204 ]; then
echo "::warning::dispatch to $UMBRELLA answered HTTP $code: $(head -c 300 "$RUNNER_TEMP/notify-umbrella-response.txt")"
exit 0
events=(submodule-updated)
if [ "$DOCS_CHANGED" = true ]; then
events+=(submodule-docs-updated)
fi
echo "dispatched $EVENT_TYPE for $REPO@$SHA to $UMBRELLA"
for event in "${events[@]}"; do
body="$(jq -nc --arg repo "$REPO" --arg sha "$SHA" --arg event "$event" \
'{event_type: $event, client_payload: {repo: $repo, sha: $sha}}')"
code="$(curl -sS -o "$RUNNER_TEMP/notify-umbrella-response.txt" -w '%{http_code}' -X POST \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/$UMBRELLA/dispatches" -d "$body")"
if [ "$code" != 204 ]; then
echo "::warning::dispatch of $event to $UMBRELLA answered HTTP $code: $(head -c 300 "$RUNNER_TEMP/notify-umbrella-response.txt")"
else
echo "dispatched $event for $REPO@$SHA to $UMBRELLA"
fi
done
18 changes: 13 additions & 5 deletions docs/4-reference_workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,20 @@ No secrets.

## notify-umbrella

Tells the umbrella a repo's docs changed via `repository_dispatch`, so it rebuilds within minutes
instead of at its next daily cron (MIP-0070 §5.5). Modelled on h0ffmann/nix-config's
`profile-ping.yml` — no checkout on either side, ~3 lines to call.
Tells the umbrella every push to `main` via `repository_dispatch` (`submodule-updated`), so
pointer-sync.yml can move pointers on the event instead of waiting for its daily cron, and that a
repo's docs changed too (`submodule-docs-updated`) when the push touched `README.md` or `docs/**`,
so docs.yml rebuilds within minutes (MIP-0070 §5.5, MIP-0076 §5.5 step 1). Modelled on
h0ffmann/nix-config's `profile-ping.yml` — no checkout on either side. The caller needs no
`paths:` filter: this workflow reads the compare API itself to decide which event types a given
push earns (every caller sets `permissions: {}`, which a reusable workflow can only keep or
lower, so it can't check its own repo out).

```yaml
name: notify umbrella
on:
push:
branches: [main]
paths: [README.md, docs/**]
jobs:
notify:
uses: marola-dev/marola-devkit/.github/workflows/notify-umbrella.yml@v0.5.0
Expand All @@ -134,14 +138,18 @@ jobs:
| Input | Default | Notes |
|---|---|---|
| `umbrella` | `marola-dev/marola` | MAROLA_UMBRELLA, MIP-0070 §5.6 |
| `event-type` | `submodule-docs-updated` | what the umbrella's docs workflow listens for |
| `event-type` | `""` | deprecated, ignored (MIP-0076) — kept so a caller still passing it doesn't fail GitHub's input check |
| `runner` | `ubuntu-latest` | resolved in the *caller's* repo |

**Secret** `token` (optional): every repo passes the org secret `MAROLA_CROSS_REPO_PAT`, a
fine-grained PAT with Contents: read & write on the umbrella (`repository_dispatch` needs it;
`GITHUB_TOKEN` cannot reach another repo). Unset is a notice, not a failure — the umbrella's daily
cron still catches the change.

A zero `github.event.before` (a branch's first push), a compare API call that doesn't answer 200
(e.g. `before` unknown to it after a force-push), or a truncated compare (the API caps its file
list at 300) all count as a docs change too, so both events go rather than silently dropping one.

## labels-sync

Reconciles the caller repo's labels against `scripts/issues.sh labels sync`'s own default manifest
Expand Down
Loading