ci: add github actions workflow and dockerfiles
This commit is contained in:
180
.github/workflows/ci-cd.yml
vendored
Normal file
180
.github/workflows/ci-cd.yml
vendored
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
name: TakeoutSaaS CI/CD
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ${{ secrets.REGISTRY }}
|
||||||
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
|
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||||
|
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||||
|
DEPLOY_PASSWORD: ${{ secrets.DEPLOY_PASSWORD }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
detect:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
services: ${{ steps.collect.outputs.services }}
|
||||||
|
image_tag: ${{ steps.collect.outputs.image_tag }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- id: collect
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE="${{ github.event.before }}"
|
||||||
|
if [ -z "$BASE" ] || [ "$BASE" = "0000000000000000000000000000000000000000" ]; then
|
||||||
|
if git rev-parse HEAD^ >/dev/null 2>&1; then
|
||||||
|
BASE="$(git rev-parse HEAD^)"
|
||||||
|
else
|
||||||
|
BASE=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$BASE" ]; then
|
||||||
|
CHANGED=$(git ls-tree -r --name-only HEAD)
|
||||||
|
else
|
||||||
|
CHANGED=$(git diff --name-only "$BASE" HEAD || true)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "本次变更文件:"
|
||||||
|
echo "$CHANGED"
|
||||||
|
|
||||||
|
deploy_all=false
|
||||||
|
services=()
|
||||||
|
|
||||||
|
hit() { echo "$CHANGED" | grep -qE "$1"; }
|
||||||
|
|
||||||
|
if hit '^src/(Domain|Application|Infrastructure|Core|Modules)/'; then deploy_all=true; fi
|
||||||
|
if hit '^Directory\.Build\.props$'; then deploy_all=true; fi
|
||||||
|
|
||||||
|
if hit '^src/Api/TakeoutSaaS.AdminApi/'; then services+=("admin-api"); fi
|
||||||
|
if hit '^src/Api/TakeoutSaaS.MiniApi/'; then services+=("mini-api"); fi
|
||||||
|
if hit '^src/Api/TakeoutSaaS.UserApi/'; then services+=("user-api"); fi
|
||||||
|
|
||||||
|
if $deploy_all || [ ${#services[@]} -eq 0 ]; then
|
||||||
|
services=("admin-api" "mini-api" "user-api")
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '需要处理的服务: %s\n' "${services[*]}"
|
||||||
|
|
||||||
|
SERVICES_LIST="${services[*]}"
|
||||||
|
export SERVICES_LIST
|
||||||
|
SERVICES_JSON=$(python - <<'PY'
|
||||||
|
import json, os
|
||||||
|
raw = os.environ.get("SERVICES_LIST", "").split()
|
||||||
|
print(json.dumps(raw))
|
||||||
|
PY
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "services=$SERVICES_JSON" >> "$GITHUB_OUTPUT"
|
||||||
|
TAG=$(date +%Y%m%d%H%M%S)
|
||||||
|
echo "image_tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: detect
|
||||||
|
if: needs.detect.outputs.services != '[]'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
service: ${{ fromJson(needs.detect.outputs.services) }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ env.REGISTRY_USERNAME }}
|
||||||
|
password: ${{ env.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push ${{ matrix.service }}
|
||||||
|
env:
|
||||||
|
SERVICE: ${{ matrix.service }}
|
||||||
|
IMAGE_TAG: ${{ needs.detect.outputs.image_tag }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
case "$SERVICE" in
|
||||||
|
admin-api)
|
||||||
|
DOCKERFILE="src/Api/TakeoutSaaS.AdminApi/Dockerfile"
|
||||||
|
IMAGE="$REGISTRY/admin-api:$IMAGE_TAG"
|
||||||
|
;;
|
||||||
|
mini-api)
|
||||||
|
DOCKERFILE="src/Api/TakeoutSaaS.MiniApi/Dockerfile"
|
||||||
|
IMAGE="$REGISTRY/mini-api:$IMAGE_TAG"
|
||||||
|
;;
|
||||||
|
user-api)
|
||||||
|
DOCKERFILE="src/Api/TakeoutSaaS.UserApi/Dockerfile"
|
||||||
|
IMAGE="$REGISTRY/user-api:$IMAGE_TAG"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "未知服务:$SERVICE"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ ! -f "$DOCKERFILE" ]; then
|
||||||
|
echo "未找到 Dockerfile: $DOCKERFILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker build -f "$DOCKERFILE" -t "$IMAGE" .
|
||||||
|
docker push "$IMAGE"
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- detect
|
||||||
|
- build
|
||||||
|
if: needs.detect.outputs.services != '[]'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
service: ${{ fromJson(needs.detect.outputs.services) }}
|
||||||
|
steps:
|
||||||
|
- name: Install sshpass
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y sshpass
|
||||||
|
|
||||||
|
- name: Deploy ${{ matrix.service }}
|
||||||
|
env:
|
||||||
|
SERVICE: ${{ matrix.service }}
|
||||||
|
IMAGE_TAG: ${{ needs.detect.outputs.image_tag }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
case "$SERVICE" in
|
||||||
|
admin-api)
|
||||||
|
IMAGE="$REGISTRY/admin-api:$IMAGE_TAG"
|
||||||
|
PORT=7801
|
||||||
|
;;
|
||||||
|
mini-api)
|
||||||
|
IMAGE="$REGISTRY/mini-api:$IMAGE_TAG"
|
||||||
|
PORT=7701
|
||||||
|
;;
|
||||||
|
user-api)
|
||||||
|
IMAGE="$REGISTRY/user-api:$IMAGE_TAG"
|
||||||
|
PORT=7901
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "未知服务:$SERVICE"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
sshpass -p "$DEPLOY_PASSWORD" ssh -o StrictHostKeyChecking=no "$DEPLOY_USER@$DEPLOY_HOST" <<EOF
|
||||||
|
set -e
|
||||||
|
echo "$REGISTRY_PASSWORD" | docker login "$REGISTRY" -u "$REGISTRY_USERNAME" --password-stdin
|
||||||
|
docker pull $IMAGE
|
||||||
|
docker stop $SERVICE 2>/dev/null || true
|
||||||
|
docker rm $SERVICE 2>/dev/null || true
|
||||||
|
docker run -d --name $SERVICE --restart=always -p $PORT:$PORT $IMAGE
|
||||||
|
EOF
|
||||||
12
src/Api/TakeoutSaaS.AdminApi/Dockerfile
Normal file
12
src/Api/TakeoutSaaS.AdminApi/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . .
|
||||||
|
RUN dotnet restore src/Api/TakeoutSaaS.AdminApi/TakeoutSaaS.AdminApi.csproj
|
||||||
|
RUN dotnet publish src/Api/TakeoutSaaS.AdminApi/TakeoutSaaS.AdminApi.csproj -c Release -o /app/publish
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /app/publish .
|
||||||
|
EXPOSE 7801
|
||||||
|
ENV ASPNETCORE_URLS=http://+:7801
|
||||||
|
ENTRYPOINT ["dotnet", "TakeoutSaaS.AdminApi.dll"]
|
||||||
12
src/Api/TakeoutSaaS.MiniApi/Dockerfile
Normal file
12
src/Api/TakeoutSaaS.MiniApi/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . .
|
||||||
|
RUN dotnet restore src/Api/TakeoutSaaS.MiniApi/TakeoutSaaS.MiniApi.csproj
|
||||||
|
RUN dotnet publish src/Api/TakeoutSaaS.MiniApi/TakeoutSaaS.MiniApi.csproj -c Release -o /app/publish
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /app/publish .
|
||||||
|
EXPOSE 7701
|
||||||
|
ENV ASPNETCORE_URLS=http://+:7701
|
||||||
|
ENTRYPOINT ["dotnet", "TakeoutSaaS.MiniApi.dll"]
|
||||||
12
src/Api/TakeoutSaaS.UserApi/Dockerfile
Normal file
12
src/Api/TakeoutSaaS.UserApi/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . .
|
||||||
|
RUN dotnet restore src/Api/TakeoutSaaS.UserApi/TakeoutSaaS.UserApi.csproj
|
||||||
|
RUN dotnet publish src/Api/TakeoutSaaS.UserApi/TakeoutSaaS.UserApi.csproj -c Release -o /app/publish
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /app/publish .
|
||||||
|
EXPOSE 7901
|
||||||
|
ENV ASPNETCORE_URLS=http://+:7901
|
||||||
|
ENTRYPOINT ["dotnet", "TakeoutSaaS.UserApi.dll"]
|
||||||
Reference in New Issue
Block a user