From 90b93de8e5f77ee757c697c15e6a9ce3e4be5158 Mon Sep 17 00:00:00 2001 From: Pedro Faria da Costa Date: Mon, 6 Jul 2026 00:16:15 +0100 Subject: [PATCH] Unify workflows into coordinated pipeline.yml --- .forgejo/workflows/ci.yml | 60 --------- .forgejo/workflows/deploy.yml | 88 ------------- .forgejo/workflows/infra.yml | 82 ------------- .forgejo/workflows/pipeline.yml | 210 ++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+), 230 deletions(-) delete mode 100644 .forgejo/workflows/ci.yml delete mode 100644 .forgejo/workflows/deploy.yml delete mode 100644 .forgejo/workflows/infra.yml create mode 100644 .forgejo/workflows/pipeline.yml diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml deleted file mode 100644 index e80efbb..0000000 --- a/.forgejo/workflows/ci.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: CI - -on: - push: - branches: ['*'] - pull_request: - branches: [main] - -jobs: - # ── Go Backend ────────────────────────────────────────── - tongo-core: - runs-on: docker - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23' - - - name: Lint - working-directory: tongo-core - run: | - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - golangci-lint run ./... - - - name: Test - working-directory: tongo-core - run: go test -race -coverprofile=coverage.out ./... - - - name: Build - working-directory: tongo-core - run: go build -o bin/tongo-core ./cmd/tongo-core - - # ── Frontend ──────────────────────────────────────────── - web-terminal: - runs-on: docker - steps: - - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: '22' - - - name: Install - working-directory: web-terminal - run: npm ci - - - name: Lint & Format Check - working-directory: web-terminal - run: npm run format - - - name: Type Check - working-directory: web-terminal - run: npx tsc --noEmit - - - name: Build - working-directory: web-terminal - run: npm run build diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml deleted file mode 100644 index 0d6659b..0000000 --- a/.forgejo/workflows/deploy.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: Deploy - -on: - push: - branches: [main] - tags: ['v*'] - -env: - REGISTRY: git.holo-grid.bar - IMAGE_TONGO: git.holo-grid.bar/costap/quarkshologridledger/tongo-core - IMAGE_WEB: git.holo-grid.bar/costap/quarkshologridledger/web-terminal - -jobs: - build-and-push: - runs-on: docker - steps: - - uses: actions/checkout@v4 - - - name: Set image tag - run: | - if [ "${{ github.ref_type }}" = "tag" ]; then - echo "TAG=${{ github.ref_name }}" >> $GITHUB_ENV - else - echo "TAG=sha-$(git rev-parse --short HEAD)" >> $GITHUB_ENV - fi - - - name: Login to Forgejo Registry - run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login $REGISTRY -u ${{ secrets.REGISTRY_USER }} --password-stdin - - - name: Build & Push Tongo Core - run: | - docker build -t $IMAGE_TONGO:$TAG -t $IMAGE_TONGO:latest -f tongo-core/Dockerfile . - docker push $IMAGE_TONGO:$TAG - docker push $IMAGE_TONGO:latest - - - name: Build & Push Web Terminal - run: | - docker build -t $IMAGE_WEB:$TAG -t $IMAGE_WEB:latest -f web-terminal/Dockerfile . - docker push $IMAGE_WEB:$TAG - docker push $IMAGE_WEB:latest - - deploy: - runs-on: docker - needs: build-and-push - steps: - - uses: actions/checkout@v4 - - - name: Set environment target variables - id: target - run: | - if [[ "${{ github.ref }}" == refs/tags/v* ]]; then - echo "env_name=production" >> $GITHUB_OUTPUT - echo "deploy_host=${{ secrets.DEPLOY_HOST_PROD }}" >> $GITHUB_OUTPUT - echo "deploy_key<> $GITHUB_OUTPUT - echo "${{ secrets.DEPLOY_SSH_KEY_PROD }}" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "env_name=staging" >> $GITHUB_OUTPUT - echo "deploy_host=${{ secrets.DEPLOY_HOST_STAGING }}" >> $GITHUB_OUTPUT - echo "deploy_key<> $GITHUB_OUTPUT - echo "${{ secrets.DEPLOY_SSH_KEY_STAGING }}" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - fi - - - name: Deploy to Hetzner target environment - env: - ENV_NAME: ${{ steps.target.outputs.env_name }} - DEPLOY_HOST: ${{ steps.target.outputs.deploy_host }} - DEPLOY_KEY: ${{ steps.target.outputs.deploy_key }} - run: | - mkdir -p ~/.ssh - echo "$DEPLOY_KEY" > ~/.ssh/deploy_key - chmod 600 ~/.ssh/deploy_key - - # Copy production compose file and configuration - scp -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no \ - deploy/docker-compose.prod.yml \ - deploy/Caddyfile \ - deploy@$DEPLOY_HOST:/opt/hologrid/ - - # Pull new images and restart the stack - ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no deploy@$DEPLOY_HOST << 'EOF' - cd /opt/hologrid - echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ${{ env.REGISTRY }} -u ${{ secrets.REGISTRY_USER }} --password-stdin - docker compose -f docker-compose.prod.yml pull - docker compose -f docker-compose.prod.yml up -d --remove-orphans - docker image prune -f - EOF diff --git a/.forgejo/workflows/infra.yml b/.forgejo/workflows/infra.yml deleted file mode 100644 index a730ad7..0000000 --- a/.forgejo/workflows/infra.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: Infrastructure - -on: - push: - branches: [main] - tags: ['v*'] - paths: ['infra/**'] - pull_request: - branches: [main] - paths: ['infra/**'] - -jobs: - plan: - runs-on: docker - steps: - - uses: actions/checkout@v4 - - - name: Setup OpenTofu - uses: opentofu/setup-opentofu@v1 - - - name: Set environment target - id: target - run: | - if [[ "${{ github.ref }}" == refs/tags/v* ]]; then - echo "env_name=production" >> $GITHUB_OUTPUT - else - echo "env_name=staging" >> $GITHUB_OUTPUT - fi - - - name: Init and Plan - working-directory: infra - env: - HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }} - ENV_NAME: ${{ steps.target.outputs.env_name }} - TF_VAR_hcloud_token: ${{ secrets.HCLOUD_TOKEN }} - TF_VAR_ssh_public_key: ${{ secrets.SSH_PUBLIC_KEY }} - TF_VAR_domain: "holo-grid.bar" - TF_VAR_forgejo_domain: "git.holo-grid.bar" - run: | - tofu init - tofu workspace select $ENV_NAME || tofu workspace new $ENV_NAME - tofu plan -out=tfplan - - - name: Upload plan artifact - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v4 - with: - name: tfplan - path: infra/tfplan - - apply: - runs-on: docker - needs: plan - if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && github.event_name == 'push' - steps: - - uses: actions/checkout@v4 - - - name: Setup OpenTofu - uses: opentofu/setup-opentofu@v1 - - - name: Set environment target - id: target - run: | - if [[ "${{ github.ref }}" == refs/tags/v* ]]; then - echo "env_name=production" >> $GITHUB_OUTPUT - else - echo "env_name=staging" >> $GITHUB_OUTPUT - fi - - - name: Init and Apply - working-directory: infra - env: - HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }} - ENV_NAME: ${{ steps.target.outputs.env_name }} - TF_VAR_hcloud_token: ${{ secrets.HCLOUD_TOKEN }} - TF_VAR_ssh_public_key: ${{ secrets.SSH_PUBLIC_KEY }} - TF_VAR_domain: "holo-grid.bar" - TF_VAR_forgejo_domain: "git.holo-grid.bar" - run: | - tofu init - tofu workspace select $ENV_NAME || tofu workspace new $ENV_NAME - tofu apply -auto-approve diff --git a/.forgejo/workflows/pipeline.yml b/.forgejo/workflows/pipeline.yml new file mode 100644 index 0000000..08d892f --- /dev/null +++ b/.forgejo/workflows/pipeline.yml @@ -0,0 +1,210 @@ +name: Pipeline + +on: + push: + branches: ['*'] + tags: ['v*'] + pull_request: + branches: [main] + +env: + REGISTRY: git.holo-grid.bar + IMAGE_TONGO: git.holo-grid.bar/costap/quarkshologridledger/tongo-core + IMAGE_WEB: git.holo-grid.bar/costap/quarkshologridledger/web-terminal + +jobs: + # ── JOB 1: CI (LINT & TEST) ───────────────────────────────── + ci-backend: + runs-on: docker + steps: + - uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + + - name: Lint + working-directory: tongo-core + run: | + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + golangci-lint run ./... + + - name: Test + working-directory: tongo-core + run: go test -race -coverprofile=coverage.out ./... + + ci-frontend: + runs-on: docker + steps: + - uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Install + working-directory: web-terminal + run: npm ci + + - name: Lint & Format Check + working-directory: web-terminal + run: npm run format + + - name: Type Check + working-directory: web-terminal + run: npx tsc --noEmit + + # ── JOB 2: INFRASTRUCTURE PLAN ────────────────────────────── + infra-plan: + runs-on: docker + steps: + - uses: actions/checkout@v4 + + - name: Setup OpenTofu + uses: opentofu/setup-opentofu@v1 + + - name: Set environment target + id: target + run: | + if [[ "${{ github.ref }}" == refs/tags/v* ]]; then + echo "env_name=production" >> $GITHUB_OUTPUT + else + echo "env_name=staging" >> $GITHUB_OUTPUT + fi + + - name: Init and Plan + working-directory: infra + env: + HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }} + ENV_NAME: ${{ steps.target.outputs.env_name }} + TF_VAR_hcloud_token: ${{ secrets.HCLOUD_TOKEN }} + TF_VAR_ssh_public_key: ${{ secrets.SSH_PUBLIC_KEY }} + TF_VAR_domain: "holo-grid.bar" + TF_VAR_forgejo_domain: "git.holo-grid.bar" + run: | + tofu init + tofu workspace select $ENV_NAME || tofu workspace new $ENV_NAME + tofu plan -out=tfplan + + - name: Upload plan artifact + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: tfplan + path: infra/tfplan + + # ── JOB 3: INFRASTRUCTURE APPLY (Depends on Plan and CI) ──── + infra-apply: + runs-on: docker + needs: [ci-backend, ci-frontend, infra-plan] + if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && github.event_name == 'push' + steps: + - uses: actions/checkout@v4 + + - name: Setup OpenTofu + uses: opentofu/setup-opentofu@v1 + + - name: Set environment target + id: target + run: | + if [[ "${{ github.ref }}" == refs/tags/v* ]]; then + echo "env_name=production" >> $GITHUB_OUTPUT + else + echo "env_name=staging" >> $GITHUB_OUTPUT + fi + + - name: Init and Apply + working-directory: infra + env: + HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }} + ENV_NAME: ${{ steps.target.outputs.env_name }} + TF_VAR_hcloud_token: ${{ secrets.HCLOUD_TOKEN }} + TF_VAR_ssh_public_key: ${{ secrets.SSH_PUBLIC_KEY }} + TF_VAR_domain: "holo-grid.bar" + TF_VAR_forgejo_domain: "git.holo-grid.bar" + run: | + tofu init + tofu workspace select $ENV_NAME || tofu workspace new $ENV_NAME + tofu apply -auto-approve + + # ── JOB 4: BUILD AND PUSH DOCKER (Depends on CI) ──────────── + build-and-push: + runs-on: docker + needs: [ci-backend, ci-frontend] + if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && github.event_name == 'push' + steps: + - uses: actions/checkout@v4 + + - name: Set image tag + run: | + if [ "${{ github.ref_type }}" = "tag" ]; then + echo "TAG=${{ github.ref_name }}" >> $GITHUB_ENV + else + echo "TAG=sha-$(git rev-parse --short HEAD)" >> $GITHUB_ENV + fi + + - name: Login to Forgejo Registry + run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login $REGISTRY -u ${{ secrets.REGISTRY_USER }} --password-stdin + + - name: Build & Push Tongo Core + run: | + docker build -t $IMAGE_TONGO:$TAG -t $IMAGE_TONGO:latest -f tongo-core/Dockerfile . + docker push $IMAGE_TONGO:$TAG + docker push $IMAGE_TONGO:latest + + - name: Build & Push Web Terminal + run: | + docker build -t $IMAGE_WEB:$TAG -t $IMAGE_WEB:latest -f web-terminal/Dockerfile . + docker push $IMAGE_WEB:$TAG + docker push $IMAGE_WEB:latest + + # ── JOB 5: DEPLOY (Depends on Apply and Build) ────────────── + deploy: + runs-on: docker + needs: [infra-apply, build-and-push] + steps: + - uses: actions/checkout@v4 + + - name: Set environment target variables + id: target + run: | + if [[ "${{ github.ref }}" == refs/tags/v* ]]; then + echo "env_name=production" >> $GITHUB_OUTPUT + echo "deploy_host=${{ secrets.DEPLOY_HOST_PROD }}" >> $GITHUB_OUTPUT + echo "deploy_key<> $GITHUB_OUTPUT + echo "${{ secrets.DEPLOY_SSH_KEY_PROD }}" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + else + echo "env_name=staging" >> $GITHUB_OUTPUT + echo "deploy_host=${{ secrets.DEPLOY_HOST_STAGING }}" >> $GITHUB_OUTPUT + echo "deploy_key<> $GITHUB_OUTPUT + echo "${{ secrets.DEPLOY_SSH_KEY_STAGING }}" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + - name: Deploy to Hetzner target environment + env: + ENV_NAME: ${{ steps.target.outputs.env_name }} + DEPLOY_HOST: ${{ steps.target.outputs.deploy_host }} + DEPLOY_KEY: ${{ steps.target.outputs.deploy_key }} + run: | + mkdir -p ~/.ssh + echo "$DEPLOY_KEY" > ~/.ssh/deploy_key + chmod 600 ~/.ssh/deploy_key + + # Copy production compose file and configuration + scp -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no \ + deploy/docker-compose.prod.yml \ + deploy/Caddyfile \ + deploy@$DEPLOY_HOST:/opt/hologrid/ + + # Pull new images and restart the stack + ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no deploy@$DEPLOY_HOST << 'EOF' + cd /opt/hologrid + echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ${{ env.REGISTRY }} -u ${{ secrets.REGISTRY_USER }} --password-stdin + docker compose -f docker-compose.prod.yml pull + docker compose -f docker-compose.prod.yml up -d --remove-orphans + docker image prune -f + EOF