From c930f64e78e673885cf54bf70ad0d86e3fe27485 Mon Sep 17 00:00:00 2001 From: Raul Lugo Date: Thu, 29 Jan 2026 00:22:15 +0100 Subject: [PATCH] first commit --- .github/actions/build-push-bump/action.yml | 90 +++++++++++++++ README.md | 126 +++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 .github/actions/build-push-bump/action.yml create mode 100644 README.md diff --git a/.github/actions/build-push-bump/action.yml b/.github/actions/build-push-bump/action.yml new file mode 100644 index 0000000..02bc8ae --- /dev/null +++ b/.github/actions/build-push-bump/action.yml @@ -0,0 +1,90 @@ +name: build-push-bump +description: Build and push an OCI image to Gitea registry, then bump resuely/infra stack.env to trigger deploy. + +inputs: + registry: + description: Registry host (e.g. git.rlugo.dev) + required: true + image: + description: Full image name without tag (e.g. git.rlugo.dev/resuely/auth) + required: true + infraRepo: + description: HTTPS clone URL without credentials (e.g. git.rlugo.dev/resuely/infra.git) + required: true + stackEnvPath: + description: Path in infra repo to env file (e.g. stacks/resuely/prod/stack.env) + required: true + stackEnvKey: + description: Env key to bump (e.g. AUTH_IMAGE_TAG) + required: true + + registryUsername: + description: Registry username + required: true + registryToken: + description: Registry token/password + required: true + infraPushToken: + description: Token with write access to infra repo + required: true + +outputs: + tag: + description: The built image tag + value: ${{ steps.meta.outputs.tag }} + +runs: + using: composite + steps: + - name: Compute tag + id: meta + shell: bash + run: | + set -euo pipefail + SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) + TAG="${SHORT_SHA}-$(date +%s)" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + + - name: Login to registry + shell: bash + run: | + set -euo pipefail + echo "${{ inputs.registryToken }}" | docker login "${{ inputs.registry }}" \ + -u "${{ inputs.registryUsername }}" \ + --password-stdin + + - name: Build and push image + shell: bash + run: | + set -euo pipefail + TAG="${{ steps.meta.outputs.tag }}" + docker build -t "${{ inputs.image }}:${TAG}" . + docker push "${{ inputs.image }}:${TAG}" + + - name: Bump infra stack + shell: bash + run: | + set -euo pipefail + + TAG="${{ steps.meta.outputs.tag }}" + + git config --global user.name "resuely-bot" + git config --global user.email "bot@resuely.com" + + rm -rf infra + git clone "https://resuely-bot:${{ inputs.infraPushToken }}@${{ inputs.infraRepo }}" infra + cd infra + + FILE="${{ inputs.stackEnvPath }}" + KEY="${{ inputs.stackEnvKey }}" + + if ! grep -q "^${KEY}=" "$FILE"; then + echo "Missing ${KEY} in ${FILE}" >&2 + exit 1 + fi + + sed -i "s/^${KEY}=.*/${KEY}=${TAG}/" "$FILE" + + git add "$FILE" + git commit -m "deploy(${KEY}): ${TAG}" + git push origin main diff --git a/README.md b/README.md new file mode 100644 index 0000000..41b41eb --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ +# Resuely CI Actions + +Shared CI building blocks for Resuely repositories running on Gitea Actions. + +This repo centralizes deployment automation so each application repo only needs a thin workflow wrapper. + +## What this repo provides + +### `build-push-bump` + +Path: `.github/actions/build-push-bump/action.yml` + +Builds and pushes a Docker image to the Gitea registry and then bumps a variable in `resuely/infra` (GitOps style) to trigger a production deploy. + +Flow: + +1) Compute a unique image tag: `-` +2) `docker login` to the Gitea registry +3) `docker build` and `docker push` the image +4) Clone the infra repo, update `stack.env`, commit, and push to `main` + +This keeps production state versioned in the infra repo while allowing fast iteration on every push. + +## Requirements + +- Gitea Actions runner capable of running Docker commands. +- The target registry must be reachable from the runner. +- A bot account/token with write access to the infra repo. + +## Usage + +In an application repo, create `.github/workflows/deploy.yaml` like this: + +```yaml +name: Build & Deploy (prod) + +"on": + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build, push, bump infra + uses: https://git.rlugo.dev/resuely/ci-actions/.github/actions/build-push-bump@main + with: + registry: git.rlugo.dev + image: git.rlugo.dev/resuely/handy + infraRepo: git.rlugo.dev/resuely/infra.git + stackEnvPath: stacks/resuely/prod/stack.env + stackEnvKey: HANDY_IMAGE_TAG + registryUsername: ${{ secrets.REGISTRY_USERNAME }} + registryToken: ${{ secrets.REGISTRY_TOKEN }} + infraPushToken: ${{ secrets.INFRA_PUSH_TOKEN }} +``` + +## Inputs + +### Required + +- `registry` + - Registry host. + - Example: `git.rlugo.dev` + +- `image` + - Full image name without tag. + - Example: `git.rlugo.dev/resuely/auth` + +- `infraRepo` + - HTTPS clone URL (no credentials in the value). + - Example: `git.rlugo.dev/resuely/infra.git` + +- `stackEnvPath` + - Path inside infra repo to the env file that holds image tags. + - Example: `stacks/resuely/prod/stack.env` + +- `stackEnvKey` + - The variable name inside `stack.env` to bump. + - Examples: `AUTH_IMAGE_TAG`, `HANDY_IMAGE_TAG` + +- `registryUsername` + - Username used for `docker login`. + +- `registryToken` + - Token/password used for `docker login`. + +- `infraPushToken` + - Token with write access to `resuely/infra`. + - The action uses the username `resuely-bot` when cloning/pushing. + +## Outputs + +- `tag` + - The computed tag that was pushed. + +## Secrets to configure (recommended) + +In each application repo: + +- `REGISTRY_USERNAME` +- `REGISTRY_TOKEN` +- `INFRA_PUSH_TOKEN` + +## Notes and best practices + +- This action tags images immutably (`-`). The infra repo decides what is running. +- Production secrets should not live in `resuely/infra`. Keep them on the server (e.g. `/srv/resuely/secrets/*.env`). +- Rollback is a `git revert` in `resuely/infra` (or manually setting the image tag back). + +## Troubleshooting + +- Action fetch fails: + - Ensure Gitea Actions is configured to allow fetching actions from your instance. + - Prefer the absolute `uses: https://...` URL (supported by Gitea) to avoid default action URL restrictions. + +- Push to infra fails: + - Confirm `INFRA_PUSH_TOKEN` has write permission to `resuely/infra`. + - Confirm the bot user exists (or adjust the clone URL username in the action). + +- Docker login fails: + - Verify `REGISTRY_USERNAME`/`REGISTRY_TOKEN` and that the token has package push access.