feat: add standalone app deploy workflow

This commit is contained in:
philipp 2026-03-30 17:39:15 +02:00
parent 03ce6546a4
commit 2b247c8550
3 changed files with 133 additions and 13 deletions

View file

@ -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 <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
name: ${BUILD_JOB}
namespace: ${PROJECT_NAMESPACE}
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 3600
template:
spec:
restartPolicy: Never
volumes:
- name: workspace
emptyDir: {}
- name: registry-creds
secret:
secretName: ${PROJECT_REGISTRY_SECRET_NAME}
items:
- key: .dockerconfigjson
path: config.json
initContainers:
- name: checkout
image: alpine/git:2.47.2
env:
- name: REPO_TOKEN
value: ${REPO_TOKEN}
- name: REPO_CLONE_URL
value: ${REPO_CLONE_URL}
- name: GITHUB_SHA
value: ${GITHUB_SHA}
command: ["/bin/sh", "-lc"]
args:
- >-
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

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.env
node_modules/

View file

@ -1,7 +1,6 @@
# unrip project # unrip project
This directory contains the trading-system project code and project-specific deployment assets. This repository contains the unrip trading-system code and its project-specific deployment assets.
It is shaped so it can later become its own repository with minimal reshuffling.
## Contents ## Contents
@ -17,7 +16,6 @@ It is shaped so it can later become its own repository with minimal reshuffling.
## Local development ## Local development
```bash ```bash
cd projects/unrip
npm install npm install
cp .env.example .env cp .env.example .env
# edit .env # edit .env
@ -44,7 +42,6 @@ The app image is now built from this directory.
Examples: Examples:
```bash ```bash
cd projects/unrip
docker build -t unrip:dev . docker build -t unrip:dev .
``` ```
@ -52,15 +49,11 @@ docker build -t unrip:dev .
Project manifests live under: 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 cluster/platform resources live in the separate infra repository.
The shared platform remains outside this directory.
## Shared platform docs ## Deployment
For cluster/platform/bootstrap details, see the repo-root docs: This repo includes `.forgejo/workflows/deploy.yml`.
- `docs/hetzner-k3s-bootstrap.md` 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.
- `docs/hetzner-self-hosted-ci-runbook.md`
- `docs/k8s-observability.md`
- `deploy/k8s/README.md`