This app is built for a GitOps flow: Conventional Commits → release-please →
semver release → CI builds the image → Flux rolls it out, with secrets
hand-applied (SOPS optional) and quote/skit content served from ConfigMaps for
live !reload.
- Releases. Every commit here uses Conventional Commits + DCO sign-off.
release-please(.github/workflows/release.yml) keeps a release PR open; merging it tags a semver release. - Image. On release, CI builds and pushes
ghcr.io/iammrcupp/annoybots:<version>(+latest). - Rollout. Flux's
ImagePolicy(semver range,image-automation.yaml) picks up the new version andImageUpdateAutomationcommits the new tag into the overlay'simages:marker, which theKustomizationthen applies.
These manifests are examples for your cluster-management repo (the one Flux
already reconciles). You likely already have a GitRepository and possibly an
ImageUpdateAutomation; reuse them and adjust names.
kustomizations.yaml— one FluxKustomizationper bot + Redis. They settargetNamespace: annoybotsand pointpath:at this repo's overlays. (Flux's kustomize-controller builds with the load restrictor disabled, so the overlays'../../../../configs/datareferences resolve.) Secrets are hand-applied by default — add adecryption:block only if you opt into SOPS (below).image-automation.yaml—ImageRepository+ImagePolicy(+ an exampleImageUpdateAutomation).
Default — hand-applied (nothing secret in Git). Each bot reads its tokens
from a Secret named <bot>-bot-secrets. Copy the template, fill it in, and apply
it out-of-band — deploy/k8s/overlays/<bot>/secret.example.yaml lists the keys:
kubectl -n annoybots create secret generic echo-bot-secrets \
--from-literal=ECHO_TWITCH_TOKEN='...' --from-literal=ECHO_DISCORD_TOKEN='...'
# ...repeat for mimic-bot-secrets (MIMIC_* keys). Omit a key to disable a network.The bot pod stays ContainerCreating until its Secret exists.
Optional — SOPS-encrypted secrets-in-Git (for a fully declarative GitOps flow). Set up once:
# Generate a cluster age key (private key goes into flux-system as `sops-age`):
age-keygen -o age.agekey
kubectl -n flux-system create secret generic sops-age --from-file=age.agekey
# Put the PUBLIC key in .sops.yaml (replace the example recipient). Create a
# secret.sops.yaml from the .example template, then encrypt it:
sops --encrypt --in-place deploy/k8s/overlays/echo/secret.sops.yaml
sops --encrypt --in-place deploy/k8s/overlays/mimic/secret.sops.yaml
git commit -s -am "chore: encrypt bot secrets"Then add secret.sops.yaml to that overlay's resources: (dropping the
secretRef patch) and give the bot's Flux Kustomization a decryption: block.
Flux decrypts at apply time using the sops-age Secret.
Quote packs (data/quotes/*.txt) and skits (data/skits.yaml) are mounted from
fixed-name ConfigMaps. Edit them in Git → Flux updates the ConfigMap → the
kubelet syncs the files into the running pods → DM a bot !reload and the new
content is live. No image rebuild, no restart. (Changing configs/<bot>.yaml
— networks/personality — still rolls the pod, which is what you want.)