Skip to content

Remote configuration reconciliation via GitHub App token - #54

Merged
Nickfost merged 2 commits into
mainfrom
feat/remote-reconciliation
Jul 28, 2026
Merged

Remote configuration reconciliation via GitHub App token#54
Nickfost merged 2 commits into
mainfrom
feat/remote-reconciliation

Conversation

@Nickfost

@Nickfost Nickfost commented Jul 28, 2026

Copy link
Copy Markdown
Member

Summary

Add scripts/remote-reconcile.sh and scripts/github-app-token.sh so that the controller can fetch its desired-state configuration from a private desired-state configuration repository using short-lived GitHub App installation tokens — no PAT, no SSH, no inbound port.

What

  • scripts/github-app-token.sh — generates a JWT from the existing app private key (openssl + curl, no new deps), exchanges it for a short-lived installation token.
  • scripts/remote-reconcile.sh — fetches the default-branch HEAD of the desired-state repo, validates, checks drift, reconciles if changed, rolls back on failure. Supports --check-only and --no-op. Bounded retries (3). Sanitized logging (no keys/tokens in output).
  • host/systemd/ci-fleet-reconcile.{service,timer} — periodic reconciliation every 5 minutes.
  • scripts/install-worker-controller.sh — manages the new timer alongside existing health/cleanup/drift timers.
  • scripts/test_remote_reconcile.py — 14 regression tests (auth failure, missing state, secret redaction, unit integrity).
  • Docs updatedDESIRED-STATE.md and HOST-MAINTENANCE.md.

Design

┌──────────────────┐     HTTPS (JWT → install token)     ┌─────────────────────┐
│ Controller host  │ ──────────────────────────────────▶ │ github.com/api      │
│                  │                                     │                     │
│ remote-reconcile │     Authenticated git fetch         │ Private desired-    │
│ .sh              │ ──────────────────────────────────▶ │ state config repo   │
│                  │                                     │                     │
│                  │     validate + reconcile            │ fleet.json          │
│                  │ ◀────────────────────────────────── │                     │
└──────────────────┘                                     └─────────────────────┘
        │
        ▼
 /var/lib/ci-fleet/reconcile/state.json
 (desired_commit, applied_commit, health, status)

Prerequisite (blocking)

The controller's GitHub App needs contents: read on the private desired-state repository so the controller can fetch configuration over HTTPS. This is an org-level GitHub App permission change; exact installation details are tracked in the private configuration repository's rollout issue.

Testing

$ python3 -m unittest scripts.test_remote_reconcile -v
----------------------------------------------------------------------
Ran 14 tests in 2.3s
OK

… token

Add scripts/remote-reconcile.sh and scripts/github-app-token.sh that
enable the controller to fetch its desired-state configuration from the
private rd-delivery-config repository using short-lived GitHub App
installation tokens.

- scripts/github-app-token.sh: generates JWT from existing private key,
  exchanges it for a short-lived installation token via the GitHub API.
- scripts/remote-reconcile.sh: fetches default-branch HEAD, validates,
  checks drift, reconciles, reports state. Supports --check-only and
  --no-op modes. Bounded retries (3), sanitized logging.
- host/systemd/ci-fleet-reconcile.service + .timer: periodic
  reconciliation every 5 minutes.
- scripts/test_remote_reconcile.py: 14 regression tests for auth
  failure, missing state, secret redaction, systemd unit integrity.
- Updated install-worker-controller.sh to manage the new timer.
- Updated DESIRED-STATE.md and HOST-MAINTENANCE.md docs.

Prerequisite: the rd-ci-fleet-01 GitHub App needs contents:read
permission and rd-delivery-config repository access.
@Nickfost

Copy link
Copy Markdown
Member Author

@codex review

1 similar comment
@Nickfost

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a93459d6ce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/remote-reconcile.sh Outdated
Comment thread scripts/remote-reconcile.sh
Comment thread scripts/remote-reconcile.sh
Comment thread host/systemd/ci-fleet-reconcile.service Outdated
Comment thread scripts/remote-reconcile.sh Outdated
Comment thread scripts/install-worker-controller.sh
Comment thread scripts/remote-reconcile.sh Outdated
1. Use auth_url for authenticated private fetch (P1)
2. Retry token generation on transient failure (P2)
3. Preserve durable config_repo identity in install-state (P1)
4. Remove Requires=ci-fleet-drift.service, use After=Wants= (P1)
5. Backwards-compat: reconcile units are optional in unit_names (P1)
6. Pass log message via argv, not source interpolation (P1)
7. Rollback via LKG re-apply, not checkpoint-latest (P1)
@Nickfost

Copy link
Copy Markdown
Member Author

Addressed all 7 Codex findings in commit 589fb78:

  • P1: auth_url now used for authenticated fetch
  • P1: log_json passes message via argv (not source interpolation)
  • P1: systemd unit uses After/Wants instead of Requires (reconciler runs even when drift.service fails)
  • P1: durable config_repo identity preserved in install-state.json via fix_state_config_repo
  • P1: reconcile units are optional in unit_names — backwards compat with older engine refs
  • P1: rollback uses LKG direct re-apply, not checkpoint-latest (safe when no checkpoint was created)
  • P2: token generation retries on transient failure within the bounded retry loop

@codex review

@Nickfost

Copy link
Copy Markdown
Member Author

All 7 findings addressed in commit 589fb78 (head updated). All threads resolved. @codex review

@Nickfost
Nickfost merged commit d04b99d into main Jul 28, 2026
1 check failed
@Nickfost
Nickfost deleted the feat/remote-reconciliation branch July 28, 2026 01:06

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 589fb78651

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/remote-reconcile.sh
Comment thread scripts/remote-reconcile.sh
Comment thread scripts/install-worker-controller.sh
Comment thread scripts/install-worker-controller.sh
Comment thread scripts/remote-reconcile.sh
Comment thread scripts/remote-reconcile.sh
Comment thread scripts/remote-reconcile.sh

[Timer]
OnBootSec=10min
OnUnitActiveSec=5min

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add reconciliation failures to fleet health monitoring

This adds a controller-lifecycle timer, but a repo-wide check of health.py shows that collect_snapshot monitors only the health, cleanup, and drift timers and only cleanup and drift services, with no consumer for reconciliation state. Consequently, a missing/disabled reconcile timer or persistent token and fetch failures can leave ordinary health reports and external heartbeats healthy indefinitely while reviewed desired state is no longer being applied; register this timer, service result, or reconcile state in the health contract.

Useful? React with 👍 / 👎.

Comment thread scripts/install-worker-controller.sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants