# CD: every push to main builds images once, deploys them to Test, runs # the smoke suite against the live Test stage, and promotes the identical # images to Int on success (ADR 0014). Prod deploys are a separate, # manually gated release workflow (issue #89). name: CD on: push: branches: [main] env: IMAGE_BASE: gitea.101010.cloud/stwaidele/dorfteich DEPLOY_HOST: one.101010.cloud jobs: build-push: name: Build and push images runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v4 - name: Log in to the Gitea registry run: printf '%s' "${{ secrets.REGISTRY_TOKEN }}" | tr -d '[:space:]' | docker login gitea.101010.cloud -u fable-5 --password-stdin # Tags: the immutable SHA (promotion + rollback target) and the # moving `test` tag that the Test stage's compose file pulls. - name: Build and push web image run: | docker build -f apps/web/Dockerfile --build-arg APP_VERSION=${{ github.sha }} \ -t $IMAGE_BASE-web:${{ github.sha }} -t $IMAGE_BASE-web:test . docker push $IMAGE_BASE-web:${{ github.sha }} docker push $IMAGE_BASE-web:test - name: Build and push api image run: | docker build -f apps/api/Dockerfile --build-arg APP_VERSION=${{ github.sha }} \ -t $IMAGE_BASE-api:${{ github.sha }} -t $IMAGE_BASE-api:test . docker push $IMAGE_BASE-api:${{ github.sha }} docker push $IMAGE_BASE-api:test - name: Build and push collab image run: | docker build -f apps/collab/Dockerfile --build-arg APP_VERSION=${{ github.sha }} \ -t $IMAGE_BASE-collab:${{ github.sha }} -t $IMAGE_BASE-collab:test . docker push $IMAGE_BASE-collab:${{ github.sha }} docker push $IMAGE_BASE-collab:test deploy-test: name: Deploy to Test needs: build-push runs-on: ubuntu-latest steps: - name: Set up SSH run: | mkdir -p ~/.ssh && chmod 700 ~/.ssh printf '%s\n' "${{ secrets.DEPLOY_SSH_KEY_TEST }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 printf '%s\n' "${{ secrets.DEPLOY_HOST_KEY }}" > ~/.ssh/known_hosts - name: Pull and restart the Test stack run: | ssh deploy@$DEPLOY_HOST 'cd /home/DOCKER/dorfteich-test \ && docker compose pull --quiet && docker compose up -d --remove-orphans \ && docker compose ps' smoke-test: name: Smoke tests against Test needs: deploy-test runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v4 - name: Set up pnpm uses: pnpm/action-setup@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile - name: Install Playwright browser run: pnpm --filter @dorfteich/web exec playwright install --with-deps chromium - name: Wait for the Test stage to be ready run: | for i in $(seq 1 30); do code=$(curl -s -o /dev/null -w '%{http_code}' https://test.dorfteich.cloud/api/v1/readyz || true) [ "$code" = "200" ] && exit 0 sleep 5 done echo "Test stage did not become ready" >&2; exit 1 - name: Run smoke suite run: E2E_BASE_URL=https://test.dorfteich.cloud pnpm --filter @dorfteich/web exec playwright test e2e/smoke.spec.ts promote-int: name: Promote to Int needs: smoke-test runs-on: ubuntu-latest # Toggle: set the repo/org Actions variable `RUN_INT_DEPLOY` to `false` # (Gitea → Settings → Actions → Variables) to skip redeploying the Int # stack (e.g. host maintenance); unset/anything-else runs the normal # promotion. Int is a preview stage; CI quality gates are unaffected. if: ${{ vars.RUN_INT_DEPLOY != 'false' }} steps: - name: Log in to the Gitea registry run: printf '%s' "${{ secrets.REGISTRY_TOKEN }}" | tr -d '[:space:]' | docker login gitea.101010.cloud -u fable-5 --password-stdin # Registry-side retag of the SHA images that just passed on Test — # Int always runs bit-identical images, never a rebuild. - name: Retag SHA images as :int run: | docker buildx imagetools create -t $IMAGE_BASE-web:int $IMAGE_BASE-web:${{ github.sha }} docker buildx imagetools create -t $IMAGE_BASE-api:int $IMAGE_BASE-api:${{ github.sha }} docker buildx imagetools create -t $IMAGE_BASE-collab:int $IMAGE_BASE-collab:${{ github.sha }} - name: Set up SSH run: | mkdir -p ~/.ssh && chmod 700 ~/.ssh printf '%s\n' "${{ secrets.DEPLOY_SSH_KEY_INT }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 printf '%s\n' "${{ secrets.DEPLOY_HOST_KEY }}" > ~/.ssh/known_hosts - name: Pull and restart the Int stack run: | ssh deploy@$DEPLOY_HOST 'cd /home/DOCKER/dorfteich-int \ && docker compose pull --quiet && docker compose up -d --remove-orphans \ && docker compose ps'