From 2b247c855007161fb1e216d39d27de5e4c85c07c Mon Sep 17 00:00:00 2001 From: philipp Date: Mon, 30 Mar 2026 17:39:15 +0200 Subject: [PATCH] feat: add standalone app deploy workflow --- .forgejo/workflows/deploy.yml | 125 ++++++++++++++++++++++++++++++++++ .gitignore | 2 + README.md | 19 ++---- 3 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 .forgejo/workflows/deploy.yml create mode 100644 .gitignore diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml new file mode 100644 index 0000000..812dca7 --- /dev/null +++ b/.forgejo/workflows/deploy.yml @@ -0,0 +1,125 @@ +name: deploy + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + deploy: + runs-on: linux-amd64 + env: + IMAGE_TAG: ${{ github.sha }} + REGISTRY_HOST: ${{ vars.REGISTRY_HOST }} + PROJECT_NAME: ${{ vars.PROJECT_NAME || 'unrip' }} + PROJECT_NAMESPACE: ${{ vars.PROJECT_NAMESPACE || vars.PROJECT_NAME || 'unrip' }} + PROJECT_DEPLOYMENTS: ${{ vars.PROJECT_DEPLOYMENTS || 'near-intents-ingest,dummy-reactor,dummy-executor,dummy-consumer' }} + PROJECT_REGISTRY_SECRET_NAME: ${{ vars.PROJECT_REGISTRY_SECRET_NAME || format('{0}-registry-creds', vars.PROJECT_NAME || 'unrip') }} + REPO_CLONE_URL: ${{ github.server_url }}/${{ github.repository }}.git + steps: + - name: Install tooling + run: | + apk add --no-cache git kubectl + + - name: Load kubeconfig + run: | + mkdir -p "$HOME/.kube" + printf '%s' '${{ secrets.KUBECONFIG_B64 }}' | base64 -d > "$HOME/.kube/config" + kubectl get ns + + - name: Checkout repo + env: + REPO_TOKEN: ${{ github.token }} + run: | + git -c credential.username=oauth2 -c http.extraHeader="Authorization: Bearer ${REPO_TOKEN}" clone --depth=1 "${REPO_CLONE_URL}" /workspace + cd /workspace + git -c credential.username=oauth2 -c http.extraHeader="Authorization: Bearer ${REPO_TOKEN}" fetch --depth=1 origin "${GITHUB_SHA}" + git checkout --detach "${GITHUB_SHA}" + + - name: Resolve deployment settings + run: | + IMAGE="$REGISTRY_HOST/$PROJECT_NAME:$IMAGE_TAG" + BUILD_JOB="image-build-${GITHUB_SHA:0:12}" + { + echo "IMAGE=$IMAGE" + echo "BUILD_JOB=$BUILD_JOB" + } >> "$GITHUB_ENV" + + - name: Apply manifests + run: | + kubectl apply -k /workspace/deploy/k8s/base + + - name: Build and push image in-cluster + env: + REPO_TOKEN: ${{ github.token }} + run: | + cat <- + git -c credential.username=oauth2 -c http.extraHeader="Authorization: Bearer ${REPO_TOKEN}" clone --depth=1 "${REPO_CLONE_URL}" /workspace && + cd /workspace && + git -c credential.username=oauth2 -c http.extraHeader="Authorization: Bearer ${REPO_TOKEN}" fetch --depth=1 origin "${GITHUB_SHA}" && + git checkout --detach "${GITHUB_SHA}" + volumeMounts: + - name: workspace + mountPath: /workspace + containers: + - name: kaniko + image: gcr.io/kaniko-project/executor:v1.23.2-debug + args: + - --context=/workspace + - --dockerfile=/workspace/Dockerfile + - --destination=${IMAGE} + - --cache=true + volumeMounts: + - name: workspace + mountPath: /workspace + - name: registry-creds + mountPath: /kaniko/.docker + EOF + kubectl -n "$PROJECT_NAMESPACE" wait --for=condition=Complete --timeout=20m "job/$BUILD_JOB" + kubectl -n "$PROJECT_NAMESPACE" logs "job/$BUILD_JOB" + + - name: Roll deployments to new image + run: | + IFS=',' read -r -a DEPLOYMENTS <<< "$PROJECT_DEPLOYMENTS" + + for deployment in "${DEPLOYMENTS[@]}"; do + deployment="$(echo "$deployment" | xargs)" + [ -n "$deployment" ] || continue + + kubectl -n "$PROJECT_NAMESPACE" set image "deployment/$deployment" app="$IMAGE" + kubectl -n "$PROJECT_NAMESPACE" rollout status "deployment/$deployment" --timeout=180s + done diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d7ec5c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +node_modules/ diff --git a/README.md b/README.md index a696f9f..79e957c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # unrip project -This directory contains the trading-system project code and project-specific deployment assets. -It is shaped so it can later become its own repository with minimal reshuffling. +This repository contains the unrip trading-system code and its project-specific deployment assets. ## Contents @@ -17,7 +16,6 @@ It is shaped so it can later become its own repository with minimal reshuffling. ## Local development ```bash -cd projects/unrip npm install cp .env.example .env # edit .env @@ -44,7 +42,6 @@ The app image is now built from this directory. Examples: ```bash -cd projects/unrip docker build -t unrip:dev . ``` @@ -52,15 +49,11 @@ docker build -t unrip:dev . Project manifests live under: -- `projects/unrip/deploy/k8s/base/` +- `deploy/k8s/base/` -They are consumed by the shared Hetzner overlay and bootstrap flow from the repo root. -The shared platform remains outside this directory. +The shared cluster/platform resources live in the separate infra repository. -## Shared platform docs +## Deployment -For cluster/platform/bootstrap details, see the repo-root docs: -- `docs/hetzner-k3s-bootstrap.md` -- `docs/hetzner-self-hosted-ci-runbook.md` -- `docs/k8s-observability.md` -- `deploy/k8s/README.md` +This repo includes `.forgejo/workflows/deploy.yml`. +On push to `main`, Forgejo builds the image from this repo root, pushes it to the shared registry, applies `deploy/k8s/base`, and rolls the app deployments in the `unrip` namespace.