Skip to content

feat: declarative GitHub state in deploy/ (Crossplane, consumed by platform)#39

Merged
devantler merged 6 commits into
mainfrom
claude/github-crossplane-deploy
Jun 15, 2026
Merged

feat: declarative GitHub state in deploy/ (Crossplane, consumed by platform)#39
devantler merged 6 commits into
mainfrom
claude/github-crossplane-deploy

Conversation

@devantler

Copy link
Copy Markdown
Contributor

What

Adds a deploy/ directory holding the devantler-tech org's GitHub configuration as Crossplane managed resources, and a workflow to publish it as a cosign-signed OCI artifact. The platform cluster onboards this repo as the github-config tenant (platform#2039) — it verifies the signature, then Flux + Crossplane reconcile the live org to match these manifests (and revert out-of-band UI edits). Goal: manage GitHub declaratively instead of via the UI.

Contents

  • deploy/repositories/{platform,ksail}.yaml — the first managed repos as namespaced Repository resources (repo.github.m.upbound.io/v1alpha1), Observe-first (managementPolicies: [\"Observe\"]): read-only adoption that mirrors live state into status.atProvider and never writes — zero risk of recreating or deleting the real repos. Namespaced MRs have no deletionPolicy; "never delete" is later expressed by omitting Delete from managementPolicies.
  • .github/workflows/cd.yaml — on v* tags, publishes deploy/ as a cosign-signed OCI artifact to ghcr.io/devantler-tech/github-config/manifests (manifests-only — no container image). The OCI name is github-config because .github is an invalid OCI path component (leading dot); the platform's OCIRepository cosign-verifies this workflow's identity.

How it fits together

Desired state (this repo) deploy/ managed resources
Engine + tenant wiring (platform) Crossplane core + provider-upjet-github + the github-config namespace/SA/Role + namespaced ProviderConfig + cosign-verified OCIRepository/Kustomization
Credentials GitHub App in OpenBao (infrastructure/github/app), materialized via ESO

Namespaced (Crossplane v2) managed resources let the platform apply these with a namespace-scoped tenant ServiceAccount + plain Role — no cluster RBAC — so .github is a genuinely isolated tenant.

Adoption flow (after merge + platform setup)

  1. Tag a v* release → artifact published + signed.
  2. Platform's github-config tenant pulls + verifies it; the two repos reconcile in Observe mode; status.atProvider mirrors live GitHub.
  3. Backfill spec.forProvider, promote managementPolicies to all-except-Delete, then roll the rest of the org over incrementally.

See platform docs/github-management.md. Gated on the maintainer creating the org GitHub App + seeding its credentials (details in that doc / the platform PR).

🤖 Generated with Claude Code

…rtifact

Add deploy/ holding the devantler-tech org's GitHub configuration as
Crossplane managed resources (provider-upjet-github, namespaced v2
repo.github.m.upbound.io). The platform cluster onboards this repo as the
github-config tenant: it verifies the cosign signature and reconciles the
live org to match these manifests.

- deploy/repositories/{platform,ksail}.yaml — first repos, Observe-first
  (read-only adoption; no recreation/deletion risk)
- .github/workflows/cd.yaml — on v* tags, publishes deploy/ as a
  cosign-signed OCI artifact to ghcr.io/devantler-tech/github-config/manifests
  (manifests-only, no container image; name is github-config because .github
  is an invalid OCI path component)

See devantler-tech/platform docs/github-management.md for the architecture
and the GitHub App credential setup (maintainer-gated).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread .github/workflows/cd.yaml Fixed
Comment thread .github/workflows/cd.yaml Fixed
Comment thread .github/workflows/cd.yaml Fixed
- pin fluxcd/flux2/action to a commit SHA (v2.8.8) per the blanket
  hash-pinning policy (was @main)
- move github.ref_name/sha/repositoryUrl into step env so they are never
  expanded into the shell script body (template-injection finding)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the inline flux-push + cosign-sign implementation with a call to
devantler-tech/reusable-workflows/.github/workflows/publish-manifests.yaml,
the generic manifests-only OCI publish lifted into the shared library
(reusable-workflows#319). Keeps the github-config OCI name override and the
v* tag trigger; drops the duplicated checkout/flux/cosign/auth steps.

Signing now happens inside the reusable workflow, so the cosign OIDC
subject becomes the reusable workflow's path — the platform github-config
OCIRepository verifier is updated to match in platform#2039.

Pinned @main until reusable-workflows cuts a release including the new
workflow; then pin to the release SHA (Renovate-managed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread .github/workflows/cd.yaml Fixed
…policy)

The .github repo's zizmor blanket policy requires hash-pinned `uses:`, so
`@main` is rejected. Pin to the reusable-workflows#319 branch head SHA that
introduces publish-manifests.yaml. Re-pin to the release commit SHA once
#319 merges and cuts a release (Renovate-managed thereafter). The platform
verifier matches `@.+$`, so the ref does not affect cosign verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The org ruleset requires the `CI - Required Checks` status on every PR, but
this repo only had cd.yaml (tag-only), so nothing produced that context and
PRs stayed merge-BLOCKED. Add a CI workflow that validates the deploy/
kustomize build on pull_request/merge_group and ends with the required gate
job (aggregate-job-checks).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread .github/workflows/cd.yaml Fixed
…mit)

cd.yaml pinned the reusable workflow to 44742c4f — the pre-release branch
head of reusable-workflows#319. That PR is now merged and released (v5.6.1),
so the old SHA is unreachable from any branch/tag (zizmor impostor-commit
alert #15, and it would fail to resolve at runtime). Re-pin to the v5.6.1
release commit f974f62a, which is reachable from the tag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@devantler devantler merged commit 30aa19e into main Jun 15, 2026
7 checks passed
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