From 69a7d53aff8c099ac9863798522d93ebfdb31b50 Mon Sep 17 00:00:00 2001 From: Jiang Date: Tue, 11 Aug 2026 10:17:01 +0800 Subject: [PATCH] ci: replace webhook deployment with v2 workflow --- .gitea/workflows/package.yml | 268 ++--------------------------------- 1 file changed, 13 insertions(+), 255 deletions(-) diff --git a/.gitea/workflows/package.yml b/.gitea/workflows/package.yml index de41372..ade3d04 100644 --- a/.gitea/workflows/package.yml +++ b/.gitea/workflows/package.yml @@ -1,263 +1,21 @@ -name: Server CI/CD +name: Server CI/CD v2 on: push: tags: - "v*" - - "latest" workflow_dispatch: {} jobs: - docker-image: - runs-on: ubuntu-22.04 - if: startsWith(github.ref, 'refs/tags/') - permissions: - contents: read - defaults: - run: - shell: bash - - steps: - - name: Checkout repository - uses: https://gitea.waternetwork.cn/actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Normalize image metadata - env: - RAW_REGISTRY_HOST: ${{ vars.REGISTRY_HOST }} - RAW_REPOSITORY: ${{ github.repository }} - RAW_REF_NAME: ${{ github.ref_name }} - run: | - RAW_REGISTRY_HOST="$(printf '%s' "${RAW_REGISTRY_HOST}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')" - - if [ -z "${RAW_REGISTRY_HOST}" ]; then - echo "Missing required repository variable: REGISTRY_HOST" - exit 1 - fi - - REGISTRY_HOST="${RAW_REGISTRY_HOST#http://}" - REGISTRY_HOST="${REGISTRY_HOST#https://}" - REGISTRY_HOST="${REGISTRY_HOST%/}" - - if [ -z "${REGISTRY_HOST}" ]; then - echo "Repository variable REGISTRY_HOST resolves to an empty host" - exit 1 - fi - - REPOSITORY_PATH="${RAW_REPOSITORY#/}" - IMAGE_OWNER="${REPOSITORY_PATH%%/*}" - IMAGE_REPOSITORY_PATH="$(printf '%s' "${IMAGE_OWNER}/tjwater-backend" | tr '[:upper:]' '[:lower:]')" - IMAGE_NAME="${REGISTRY_HOST}/${IMAGE_REPOSITORY_PATH}" - IMAGE_TAG="${RAW_REF_NAME}" - { - echo "REGISTRY_HOST=${REGISTRY_HOST}" - echo "REPOSITORY_PATH=${REPOSITORY_PATH}" - echo "IMAGE_REPOSITORY_PATH=${IMAGE_REPOSITORY_PATH}" - echo "IMAGE_NAME=${IMAGE_NAME}" - echo "IMAGE_TAG=${IMAGE_TAG}" - echo "IMAGE_REF=${IMAGE_NAME}:${IMAGE_TAG}" - } >> "$GITHUB_ENV" - - - name: Login to Gitea Container Registry - env: - REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} - REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} - GITEA_SERVER_URL: ${{ github.server_url }} - run: | - if [ -z "${REGISTRY_HOST:-}" ]; then - echo "Missing resolved environment value: REGISTRY_HOST" - exit 1 - fi - - if [ -z "${REGISTRY_USERNAME}" ]; then - echo "Missing required repository secret: REGISTRY_USERNAME" - exit 1 - fi - - if [ -z "${REGISTRY_PASSWORD}" ]; then - echo "Missing required repository secret: REGISTRY_PASSWORD" - exit 1 - fi - - echo "Registry username: ${REGISTRY_USERNAME}" - echo "Image target: ${IMAGE_REF}" - - API_SERVER_URL="${GITEA_SERVER_URL%/}" - api_user="$(curl -fsS \ - -H "Authorization: token ${REGISTRY_PASSWORD}" \ - "${API_SERVER_URL}/api/v1/user" \ - | sed -n 's/.*"login"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \ - | head -n 1 || true)" - - if [ -n "${api_user}" ]; then - echo "Registry token resolves to Gitea user: ${api_user}" - else - echo "Could not resolve Gitea user from REGISTRY_PASSWORD token; docker login may still use a password or a token without API access." - fi - - echo "Logging into registry host: ${REGISTRY_HOST}" - echo "${REGISTRY_PASSWORD}" | docker login "$REGISTRY_HOST" \ - --username "${REGISTRY_USERNAME}" \ - --password-stdin - - - name: Materialize runtime env file - env: - TJWATER_SERVER_ENV: ${{ secrets.TJWATER_SERVER_ENV }} - run: | - if [ -z "${TJWATER_SERVER_ENV}" ]; then - echo "Missing required repository secret: TJWATER_SERVER_ENV" - echo "Store the backend .env file content as a multiline Gitea repository secret named TJWATER_SERVER_ENV." - exit 1 - fi - - printf '%s\n' "${TJWATER_SERVER_ENV}" > .env - chmod 600 .env - - required_env_keys=( - ENVIRONMENT - NETWORK_NAME - DB_NAME - DB_HOST - DB_PORT - DB_USER - DB_PASSWORD - TIMESCALEDB_DB_NAME - TIMESCALEDB_DB_HOST - TIMESCALEDB_DB_PORT - TIMESCALEDB_DB_USER - TIMESCALEDB_DB_PASSWORD - METADATA_DB_NAME - METADATA_DB_HOST - METADATA_DB_PORT - METADATA_DB_USER - METADATA_DB_PASSWORD - DATABASE_ENCRYPTION_KEY - ) - - missing_keys=() - for key in "${required_env_keys[@]}"; do - if ! grep -Eq "^[[:space:]]*(export[[:space:]]+)?${key}[[:space:]]*=" .env; then - missing_keys+=("$key") - fi - done - - if [ "${#missing_keys[@]}" -gt 0 ]; then - echo "TJWATER_SERVER_ENV is missing required keys: ${missing_keys[*]}" - exit 1 - fi - - - name: Validate workspace - run: | - if [ ! -f ./Dockerfile ]; then - echo "Dockerfile not found in workspace. Repository checkout may have failed or produced an unexpected workspace." - exit 1 - fi - - - name: Build and Push Image - run: | - if [ -z "${IMAGE_NAME:-}" ] || [ -z "${IMAGE_TAG:-}" ]; then - echo "Missing resolved image metadata: IMAGE_NAME or IMAGE_TAG" - exit 1 - fi - - push_with_retry() { - image_ref="$1" - attempt=1 - max_attempts=3 - - while [ "$attempt" -le "$max_attempts" ]; do - if docker push "$image_ref"; then - return 0 - fi - - if [ "$attempt" -eq "$max_attempts" ]; then - return 1 - fi - - echo "Push failed for $image_ref (attempt $attempt/$max_attempts); retrying in 10s..." - attempt=$((attempt + 1)) - sleep 10 - done - } - - if [ "${IMAGE_TAG}" = "latest" ]; then - docker build \ - -f ./Dockerfile \ - -t "${IMAGE_NAME}:latest" \ - . - push_with_retry "${IMAGE_NAME}:latest" - else - docker build \ - -f ./Dockerfile \ - -t "${IMAGE_NAME}:${IMAGE_TAG}" \ - -t "${IMAGE_NAME}:latest" \ - . - push_with_retry "${IMAGE_NAME}:${IMAGE_TAG}" - push_with_retry "${IMAGE_NAME}:latest" - fi - - - name: Notify Deploy Server - run: | - post_deploy_webhook() { - label="$1" - payload="$2" - webhook_url="${{ vars.DEPLOY_WEBHOOK_URL }}" - token="${{ secrets.DEPLOY_WEBHOOK_TOKEN }}" - - webhook_url=$(echo "$webhook_url" | xargs) - - if [ -z "$webhook_url" ]; then - echo "Missing required repository variable: DEPLOY_WEBHOOK_URL" - return 1 - fi - - if [ -z "$token" ]; then - echo "Missing required repository secret: DEPLOY_WEBHOOK_TOKEN" - return 1 - fi - - echo "[$label] Calling webhook: $webhook_url" - - http_code=$(curl -sS -D /tmp/deploy_headers.txt -o /tmp/deploy_response.txt -w "%{http_code}" -X POST "$webhook_url" \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $token" \ - -d "$payload") - - echo "[$label] webhook HTTP status: ${http_code}" - if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then - return 0 - fi - - echo "[$label] response headers:" - cat /tmp/deploy_headers.txt - echo "[$label] response body:" - cat /tmp/deploy_response.txt - return 1 - } - - PRIMARY_PAYLOAD="{\"image\":\"${IMAGE_REF}\",\"tag\":\"${IMAGE_TAG}\",\"repo\":\"${REPOSITORY_PATH}\"}" - FALLBACK_PAYLOAD="{\"image\":\"${IMAGE_REF}\",\"tag\":\"${IMAGE_TAG}\",\"repo\":\"${IMAGE_REPOSITORY_PATH}\"}" - - echo "Deploy webhook target: ${{ vars.DEPLOY_WEBHOOK_URL }}" - echo "Deploy payload(primary): image=${IMAGE_REF}, tag=${IMAGE_TAG}, repo=${REPOSITORY_PATH}" - if post_deploy_webhook "primary" "$PRIMARY_PAYLOAD"; then - exit 0 - fi - - echo "Primary webhook request failed, retrying with lowercase repo path..." - echo "Deploy payload(fallback): image=${IMAGE_REF}, tag=${IMAGE_TAG}, repo=${IMAGE_REPOSITORY_PATH}" - if post_deploy_webhook "fallback" "$FALLBACK_PAYLOAD"; then - exit 0 - fi - - echo "Deploy webhook failed after primary and fallback attempts." - exit 1 - - deploy-fallback-log: - runs-on: ubuntu-22.04 - needs: docker-image - if: failure() - steps: - - name: Deployment not triggered - run: echo "Image build/push failed, deployment webhook was not called." + build-test-publish-and-deploy: + uses: OrgTJWater/ci-templates/.gitea/workflows/container-cd.yml@main + with: + image_name: gitea.waternetwork.cn/orgtjwater/tjwater-backend + dockerfile: Dockerfile + build_context: . + deploy_service: backend + deploy_host: 192.168.1.114 + secrets: + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + DEV_DEPLOY_SSH_KEY: ${{ secrets.DEV_DEPLOY_SSH_KEY }}