218 lines
6.8 KiB
YAML
218 lines
6.8 KiB
YAML
name: Agent CI/CD
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches:
|
|
- main
|
|
- master
|
|
tags:
|
|
- "v*"
|
|
- "latest"
|
|
|
|
jobs:
|
|
validate:
|
|
runs-on: ubuntu-22.04
|
|
permissions:
|
|
contents: read
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
env:
|
|
SERVER_URL: ${{ github.server_url }}
|
|
REPOSITORY: ${{ github.repository }}
|
|
COMMIT_SHA: ${{ github.sha }}
|
|
GIT_USERNAME: ${{ github.actor }}
|
|
GIT_TOKEN: ${{ github.token }}
|
|
run: |
|
|
case "$SERVER_URL" in
|
|
http://*)
|
|
AUTH_SERVER_URL="http://${GIT_USERNAME}:${GIT_TOKEN}@${SERVER_URL#http://}"
|
|
;;
|
|
https://*)
|
|
AUTH_SERVER_URL="https://${GIT_USERNAME}:${GIT_TOKEN}@${SERVER_URL#https://}"
|
|
;;
|
|
*)
|
|
AUTH_SERVER_URL="$SERVER_URL"
|
|
;;
|
|
esac
|
|
|
|
if [ ! -d .git ]; then
|
|
git init .
|
|
fi
|
|
|
|
if git remote get-url origin >/dev/null 2>&1; then
|
|
git remote set-url origin "${AUTH_SERVER_URL}/${REPOSITORY}.git"
|
|
else
|
|
git remote add origin "${AUTH_SERVER_URL}/${REPOSITORY}.git"
|
|
fi
|
|
|
|
git fetch --depth=1 origin "$COMMIT_SHA"
|
|
git checkout --force --detach FETCH_HEAD
|
|
git clean -ffdx
|
|
|
|
- name: Install Bun
|
|
run: |
|
|
GITHUB="https://ghproxy.net/https://github.com" curl -fsSL https://bun.sh/install | bash
|
|
echo "$HOME/.bun/bin" >> "$GITHUB_PATH"
|
|
|
|
- name: Install dependencies
|
|
run: bun install --frozen-lockfile --registry=https://registry.npmmirror.com
|
|
|
|
- name: Run checks
|
|
run: bun run check
|
|
|
|
docker-image:
|
|
runs-on: ubuntu-22.04
|
|
needs: validate
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
permissions:
|
|
contents: read
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
env:
|
|
SERVER_URL: ${{ github.server_url }}
|
|
REPOSITORY: ${{ github.repository }}
|
|
COMMIT_SHA: ${{ github.sha }}
|
|
GIT_USERNAME: ${{ github.actor }}
|
|
GIT_TOKEN: ${{ github.token }}
|
|
run: |
|
|
case "$SERVER_URL" in
|
|
http://*)
|
|
AUTH_SERVER_URL="http://${GIT_USERNAME}:${GIT_TOKEN}@${SERVER_URL#http://}"
|
|
;;
|
|
https://*)
|
|
AUTH_SERVER_URL="https://${GIT_USERNAME}:${GIT_TOKEN}@${SERVER_URL#https://}"
|
|
;;
|
|
*)
|
|
AUTH_SERVER_URL="$SERVER_URL"
|
|
;;
|
|
esac
|
|
|
|
if [ ! -d .git ]; then
|
|
git init .
|
|
fi
|
|
|
|
if git remote get-url origin >/dev/null 2>&1; then
|
|
git remote set-url origin "${AUTH_SERVER_URL}/${REPOSITORY}.git"
|
|
else
|
|
git remote add origin "${AUTH_SERVER_URL}/${REPOSITORY}.git"
|
|
fi
|
|
|
|
git fetch --depth=1 origin "$COMMIT_SHA"
|
|
git checkout --force --detach FETCH_HEAD
|
|
git clean -ffdx
|
|
|
|
- name: Normalize image metadata
|
|
env:
|
|
RAW_REGISTRY_HOST: ${{ vars.REGISTRY_HOST }}
|
|
RAW_REPOSITORY: ${{ github.repository }}
|
|
IMAGE_TAG: ${{ github.ref_name }}
|
|
run: |
|
|
REGISTRY_HOST="${RAW_REGISTRY_HOST#http://}"
|
|
REGISTRY_HOST="${REGISTRY_HOST#https://}"
|
|
REGISTRY_HOST="${REGISTRY_HOST%/}"
|
|
REPOSITORY_PATH="${RAW_REPOSITORY#/}"
|
|
IMAGE_REPOSITORY_PATH="$(printf '%s' "$REPOSITORY_PATH" | tr '[:upper:]' '[:lower:]')"
|
|
IMAGE_NAME="${REGISTRY_HOST}/${IMAGE_REPOSITORY_PATH}"
|
|
{
|
|
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
|
|
run: |
|
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "$REGISTRY_HOST" \
|
|
--username "${{ secrets.REGISTRY_USERNAME }}" \
|
|
--password-stdin
|
|
|
|
- name: Build and Push Image
|
|
run: |
|
|
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
|
|
}
|
|
|
|
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"
|
|
|
|
- name: Notify Deploy Server
|
|
run: |
|
|
post_deploy_webhook() {
|
|
label="$1"
|
|
payload="$2"
|
|
|
|
http_code=$(curl -sS -D /tmp/deploy_headers.txt -o /tmp/deploy_response.txt -w "%{http_code}" -X POST "${{ vars.DEPLOY_WEBHOOK_URL }}" \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer ${{ secrets.DEPLOY_WEBHOOK_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."
|