169 lines
5.3 KiB
YAML
169 lines
5.3 KiB
YAML
name: CI
|
||
|
||
on:
|
||
push:
|
||
branches:
|
||
- main
|
||
pull_request:
|
||
|
||
env:
|
||
IMAGE_NAME: ${{ vars.IMAGE_NAME }}
|
||
REGISTRY_LOCATION: ${{ vars.REGISTRY_LOCATION }}
|
||
PORT: ${{ vars.PORT }}
|
||
TEST_PORT: ${{ vars.TEST_PORT }}
|
||
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||
PROD_SERVER_HOST: ${{ secrets.PROD_SERVER_HOST }}
|
||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||
|
||
jobs:
|
||
lint:
|
||
name: ✅ Lint & Validate
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: 📥 Checkout repository
|
||
uses: actions/checkout@v4
|
||
|
||
- name: 🔧 Validate HTML
|
||
run: |
|
||
echo "Basic HTML validation"
|
||
test -f index.html
|
||
|
||
- name: 🐋 Validate Dockerfile
|
||
run: |
|
||
dockerfilelint Dockerfile || true
|
||
|
||
build:
|
||
name: Build & Push Docker Image
|
||
runs-on: ubuntu-latest
|
||
needs: lint
|
||
|
||
steps:
|
||
- name: 📥 Checkout repository
|
||
uses: actions/checkout@v4
|
||
|
||
- name: 🔖 Set image metadata
|
||
run: |
|
||
echo "RUN_NUMBER=${GITEA_RUN_NUMBER}" >> $GITEA_ENV
|
||
|
||
- name: 🐋 Build Docker image
|
||
run: |
|
||
docker build \
|
||
-t $IMAGE_NAME:$RUN_NUMBER \
|
||
-t $IMAGE_NAME:latest \
|
||
.
|
||
|
||
- name: ℹ️ Image info
|
||
run: docker images | grep $IMAGE_NAME
|
||
|
||
- name: 🔑 Login to registry
|
||
run: |
|
||
echo "$REGISTRY_TOKEN" | docker login $REGISTRY_LOCATION \
|
||
-u "$REGISTRY_USER" --password-stdin
|
||
|
||
- name: 🏷️ Build images
|
||
run: |
|
||
docker tag $IMAGE_NAME:latest $REGISTRY_LOCATION/$IMAGE_NAME:latest
|
||
docker tag $IMAGE_NAME:$RUN_NUMBER $REGISTRY_LOCATION/$IMAGE_NAME:build-$RUN_NUMBER
|
||
|
||
- name: 🚀 Push images
|
||
run: |
|
||
docker push $REGISTRY_LOCATION/$IMAGE_NAME:latest
|
||
docker push $REGISTRY_LOCATION/$IMAGE_NAME:build-$RUN_NUMBER
|
||
|
||
deploy:
|
||
name: 🚀 Deploy image to prod
|
||
runs-on: ubuntu-latest
|
||
needs: build
|
||
|
||
steps:
|
||
- name: 🔑 Setup SSH
|
||
run: |
|
||
mkdir -p ~/.ssh
|
||
echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_rsa
|
||
chmod 600 ~/.ssh/id_rsa
|
||
ssh-keyscan -H $PROD_SERVER_HOST >> ~/.ssh/known_hosts
|
||
|
||
- name: 🔑 Login to registry
|
||
run: |
|
||
echo "$REGISTRY_TOKEN" | docker login $REGISTRY_LOCATION \
|
||
-u "$REGISTRY_USER" --password-stdin
|
||
|
||
- name: 🚢 Deploy container
|
||
run: |
|
||
ssh $DEPLOY_USER@$PROD_SERVER_HOST << 'EOF'
|
||
set -e
|
||
NEW_IMAGE_NAME="$REGISTRY_LOCATION/$IMAGE_NAME:build-$RUN_NUMBER"
|
||
OLD_CONTAINER_NAME=$(docker inspect $IMAGE_NAME --format='{{.Config.Image}}')
|
||
NEW_CONTAINER_IMAGE="$IMAGE_NAME:build-$RUN_NUMBER"
|
||
|
||
echo "Pulling image $NEW_IMAGE_NAME"
|
||
docker pull "$NEW_IMAGE_NAME"
|
||
|
||
echo "Starting new test container"
|
||
docker run -d \
|
||
--name $NEW_CONTAINER_IMAGE \
|
||
--health-cmd="wget -qO- http://localhost:$TEST_PORT/health || exit 1" \
|
||
--health-interval=5s \
|
||
--health-retries=5 \
|
||
--health-timeout=2s \
|
||
--health-start-period=5s \
|
||
-p $TEST_PORT:80 \
|
||
"$NEW_CONTAINER_IMAGE"
|
||
|
||
echo "Waiting for healthcheck..."
|
||
for i in {1..15}; do
|
||
STATUS=$(docker inspect --format='{{.State.Health.Status}}' $NEW_CONTAINER_IMAGE)
|
||
[ "$STATUS" = "healthy" ] && break
|
||
[ "$STATUS" = "unhealthy" ] && break
|
||
sleep 2
|
||
done
|
||
|
||
docker stop $NEW_CONTAINER_IMAGE
|
||
docker image rm $NEW_CONTAINER_IMAGE
|
||
|
||
if [ "$STATUS" = "healthy" ]; then
|
||
echo "✅ Container is healthy - starting deployment"
|
||
docker stop $OLD_CONTAINER_NAME
|
||
docker run -d \
|
||
--name $NEW_CONTAINER_IMAGE \
|
||
--health-cmd="wget -qO- http://localhost:$PORT/health || exit 1" \
|
||
--health-interval=5s \
|
||
--health-retries=5 \
|
||
--health-timeout=2s \
|
||
--health-start-period=5s \
|
||
-p $PORT:80 \
|
||
"$NEW_CONTAINER_IMAGE"
|
||
sleep 10
|
||
|
||
DEPLOYMENT_STATUS=$(docker inspect --format='{{.State.Health.Status}}' $NEW_CONTAINER_IMAGE)
|
||
|
||
if [ "$DEPLOYMENT_STATUS" != "healthy" ]; then
|
||
echo "❌ Deployment failed — rolling back"
|
||
docker logs $NEW_CONTAINER_IMAGE
|
||
docker rm -f $NEW_CONTAINER_IMAGE
|
||
|
||
if [ -n "$OLD_CONTAINER_NAME" ]; then
|
||
docker run -d \
|
||
--name $OLD_CONTAINER_NAME \
|
||
--health-cmd="wget -qO- http://localhost:$PORT/health || exit 1" \
|
||
--health-interval=5s \
|
||
--health-retries=5 \
|
||
--health-timeout=2s \
|
||
--health-start-period=5s \
|
||
-p $PORT:80 \
|
||
"$OLD_CONTAINER_NAME"
|
||
echo "❌ Deployment failed — ✅ rollback successfull"
|
||
fi
|
||
exit 1
|
||
fi
|
||
|
||
docker image rm $OLD_CONTAINER_NAME
|
||
echo "✅ Deployment successfull"
|
||
|
||
else
|
||
echo "❌ Deployment failed — ❤️ healthcheck failed on the test container"
|
||
fi
|
||
EOF |