Fix after test on test-repo

This commit is contained in:
2026-01-28 13:37:01 +01:00
parent f332d62f8a
commit cc3a4e1bde
3 changed files with 103 additions and 63 deletions

View File

@@ -3,12 +3,13 @@ name: CI
on: on:
push: push:
branches: branches:
- main - master
pull_request: pull_request:
env: env:
IMAGE_NAME: ${{ vars.IMAGE_NAME }} IMAGE_NAME: ${{ vars.IMAGE_NAME }}
REGISTRY_LOCATION: ${{ vars.REGISTRY_LOCATION }} REGISTRY_LOCATION: ${{ vars.REGISTRY_LOCATION }}
REGISTRY_ORGANIZATION: ${{ vars.REGISTRY_ORGANIZATION }}
PORT: ${{ vars.PORT }} PORT: ${{ vars.PORT }}
TEST_PORT: ${{ vars.TEST_PORT }} TEST_PORT: ${{ vars.TEST_PORT }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER }} REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
@@ -16,6 +17,7 @@ env:
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
PROD_SERVER_HOST: ${{ secrets.PROD_SERVER_HOST }} PROD_SERVER_HOST: ${{ secrets.PROD_SERVER_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }} DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
BUILD_NUMBER: build-${{ gitea.run_number }}
jobs: jobs:
lint: lint:
@@ -31,10 +33,6 @@ jobs:
echo "Basic HTML validation" echo "Basic HTML validation"
test -f index.html test -f index.html
- name: 🐋 Validate Dockerfile
run: |
dockerfilelint Dockerfile || true
build: build:
name: Build & Push Docker Image name: Build & Push Docker Image
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -44,14 +42,10 @@ jobs:
- name: 📥 Checkout repository - name: 📥 Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: 🔖 Set image metadata
run: |
echo "RUN_NUMBER=${GITEA_RUN_NUMBER}" >> $GITEA_ENV
- name: 🐋 Build Docker image - name: 🐋 Build Docker image
run: | run: |
docker build \ docker build \
-t $IMAGE_NAME:$RUN_NUMBER \ -t $IMAGE_NAME:$BUILD_NUMBER \
-t $IMAGE_NAME:latest \ -t $IMAGE_NAME:latest \
. .
@@ -65,13 +59,13 @@ jobs:
- name: 🏷️ Build images - name: 🏷️ Build images
run: | run: |
docker tag $IMAGE_NAME:latest $REGISTRY_LOCATION/$IMAGE_NAME:latest docker tag $IMAGE_NAME:latest $REGISTRY_LOCATION/$REGISTRY_ORGANIZATION/$IMAGE_NAME:latest
docker tag $IMAGE_NAME:$RUN_NUMBER $REGISTRY_LOCATION/$IMAGE_NAME:build-$RUN_NUMBER docker tag $IMAGE_NAME:$BUILD_NUMBER $REGISTRY_LOCATION/$REGISTRY_ORGANIZATION/$IMAGE_NAME:$BUILD_NUMBER
- name: 🚀 Push images - name: 🚀 Push images
run: | run: |
docker push $REGISTRY_LOCATION/$IMAGE_NAME:latest docker push $REGISTRY_LOCATION/$REGISTRY_ORGANIZATION/$IMAGE_NAME:latest
docker push $REGISTRY_LOCATION/$IMAGE_NAME:build-$RUN_NUMBER docker push $REGISTRY_LOCATION/$REGISTRY_ORGANIZATION/$IMAGE_NAME:$BUILD_NUMBER
deploy: deploy:
name: 🚀 Deploy image to prod name: 🚀 Deploy image to prod
@@ -86,26 +80,56 @@ jobs:
chmod 600 ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H $PROD_SERVER_HOST >> ~/.ssh/known_hosts ssh-keyscan -H $PROD_SERVER_HOST >> ~/.ssh/known_hosts
- name: 🔑 Login to registry - name: 🗝️ Login to registry
run: | run: |
echo "$REGISTRY_TOKEN" | docker login $REGISTRY_LOCATION \ echo "$REGISTRY_TOKEN" | docker login $REGISTRY_LOCATION \
-u "$REGISTRY_USER" --password-stdin -u "$REGISTRY_USER" --password-stdin
- name: 🚢 Deploy container - name: 🔌 SSH into the prod server
run: | run: |
ssh $DEPLOY_USER@$PROD_SERVER_HOST << 'EOF' ssh $DEPLOY_USER@$PROD_SERVER_HOST << 'EOF'
set -e sleep 5
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" - name: 🚀 Deploy container to prod
run: |
set -e
NEW_IMAGE_NAME="$REGISTRY_LOCATION/$REGISTRY_ORGANIZATION/$IMAGE_NAME:$BUILD_NUMBER"
TEST_CONTAINER_NAME=test-$IMAGE_NAME
OLD_IMAGE_NAME=$(docker inspect $IMAGE_NAME --format='{{.Config.Image}}')
NEW_CONTAINER_IMAGE="$IMAGE_NAME:$BUILD_NUMBER"
echo "🏗️ Building functions"
# checks the health of the given container name $1
# returns "healthy" or "unhealthy"
is_container_healthy() {
for i in {1..15}; do
RETURN=$(docker inspect --format='{{.State.Health.Status}}' $1)
[ "$RETURN" = "healthy" ] && break
[ "$RETURN" = "unhealthy" ] && break
sleep 2
done
echo "$RETURN"
}
echo "🎣 Pulling image $NEW_IMAGE_NAME"
docker pull "$NEW_IMAGE_NAME" docker pull "$NEW_IMAGE_NAME"
echo "🧪 Test the new container health"
# if old test container is running then stop and remove it
if docker ps -a --format '{{.Names}}' | grep "^$TEST_CONTAINER_NAME$"; then
echo "Container ${TEST_CONTAINER_NAME} is running. Stopping and removing..."
docker stop $TEST_CONTAINER_NAME
docker rm $TEST_CONTAINER_NAME
fi
echo "Starting new test container" echo "Starting new test container"
docker run -d \ docker run -d \
--name $NEW_CONTAINER_IMAGE \ --name $TEST_CONTAINER_NAME \
--health-cmd="wget -qO- http://localhost:$TEST_PORT/health || exit 1" \ --health-cmd="curl -f http://$PROD_SERVER_HOST:$TEST_PORT/health || exit 1" \
--health-interval=5s \ --health-interval=5s \
--health-retries=5 \ --health-retries=5 \
--health-timeout=2s \ --health-timeout=2s \
@@ -113,57 +137,73 @@ jobs:
-p $TEST_PORT:80 \ -p $TEST_PORT:80 \
"$NEW_CONTAINER_IMAGE" "$NEW_CONTAINER_IMAGE"
echo "Waiting for healthcheck..." TEST_CONTAINER_HEALTHCHECK=$(is_container_healthy $TEST_CONTAINER_NAME)
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 stop $TEST_CONTAINER_NAME
docker image rm $NEW_CONTAINER_IMAGE docker rm $TEST_CONTAINER_NAME
echo "🚚 Deploy the new image if healthy, otherwise rollback"
if [ "$TEST_CONTAINER_HEALTHCHECK" = "healthy" ]; then
echo "✅ Test Container is healthy - starting deployment"
# Stop previous prod running container if found
if [ -n "$OLD_IMAGE_NAME" ]; then
echo "Stopping previous prod running container"
docker stop $IMAGE_NAME
docker rm $IMAGE_NAME
fi
if [ "$STATUS" = "healthy" ]; then
echo "✅ Container is healthy - starting deployment"
docker stop $OLD_CONTAINER_NAME
docker run -d \ docker run -d \
--name $NEW_CONTAINER_IMAGE \ --name $IMAGE_NAME \
--health-cmd="wget -qO- http://localhost:$PORT/health || exit 1" \ --health-cmd="curl -f http://$PROD_SERVER_HOST:$PORT/health || exit 1" \
--health-interval=5s \ --health-interval=5s \
--health-retries=5 \ --health-retries=5 \
--health-timeout=2s \ --health-timeout=2s \
--health-start-period=5s \ --health-start-period=5s \
-p $PORT:80 \ -p $PORT:80 \
"$NEW_CONTAINER_IMAGE" "$NEW_CONTAINER_IMAGE"
sleep 10
DEPLOYMENT_STATUS=$(docker inspect --format='{{.State.Health.Status}}' $NEW_CONTAINER_IMAGE) PROD_CONTAINER_HEALTHCHECK=$(is_container_healthy $IMAGE_NAME)
if [ "$DEPLOYMENT_STATUS" != "healthy" ]; then if [ "$PROD_CONTAINER_HEALTHCHECK" != "healthy" ]; then
echo "❌ Deployment failed — rolling back" echo "❌ Deployment failed — rolling back"
docker logs $NEW_CONTAINER_IMAGE docker logs $IMAGE_NAME
docker rm -f $NEW_CONTAINER_IMAGE docker stop $IMAGE_NAME
docker rm -f $IMAGE_NAME
docker image rm $NEW_CONTAINER_IMAGE
if [ -n "$OLD_CONTAINER_NAME" ]; then if [ -n "$OLD_IMAGE_NAME" ]; then
docker run -d \ docker run -d \
--name $OLD_CONTAINER_NAME \ --name $IMAGE_NAME \
--health-cmd="wget -qO- http://localhost:$PORT/health || exit 1" \ --health-cmd="curl -f http://$PROD_SERVER_HOST:$PORT/health || exit 1" \
--health-interval=5s \ --health-interval=5s \
--health-retries=5 \ --health-retries=5 \
--health-timeout=2s \ --health-timeout=2s \
--health-start-period=5s \ --health-start-period=5s \
-p $PORT:80 \ -p $PORT:80 \
"$OLD_CONTAINER_NAME" "$OLD_IMAGE_NAME"
if [["$(is_container_healthy $IMAGE_NAME)" == "healthy" ]]; then
echo "❌ Deployment failed — ✅ rollback successfull" echo "❌ Deployment failed — ✅ rollback successfull"
else
echo "❌ Deployment failed — ❌ rollback failed"
fi
exit 1
fi fi
echo "❌ Deployment failed — ❌ rollback not possible (no previous version was running)"
exit 1 exit 1
fi fi
docker image rm $OLD_CONTAINER_NAME if [ -n "$OLD_IMAGE_NAME" ]; then
echo "✅ Deployment successfull" docker image rm $OLD_IMAGE_NAME
fi
echo "✅ Deployment successfull ($IMAGE_NAME)"
exit 0
else else
docker image rm $NEW_CONTAINER_IMAGE
echo "❌ Deployment failed — ❤️ healthcheck failed on the test container" echo "❌ Deployment failed — ❤️ healthcheck failed on the test container"
exit 1
fi fi
EOF

View File

@@ -24,12 +24,11 @@ It is designed to be **forked and reused** as a starting point for real-world de
│ └── workflows/ │ └── workflows/
│ └── ci.yml │ └── ci.yml
├── assets/ ├── assets/
│ ├── scripts/
│ └── styles/
├── docker/ ├── docker/
│ ├── default.conf.template │ ├── default.conf.template
│ └── nginx.conf │ └── nginx.conf
├── src/
│ ├── css/
│ └── js/
├── Dockerfile ├── Dockerfile
├── index.html ├── index.html
└── README.md └── README.md
@@ -94,12 +93,13 @@ Used by:
The following secrets and variables **must be setup** inside the destination repository. The following secrets and variables **must be setup** inside the destination repository.
### Variables ### Variables
| Variable | Description | | Variable | Description |
| ------------------- | --------------------------------------------------- | | ----------------------- | --------------------------------------------------- |
| `IMAGE_NAME` | Name of the docker image (built and deployed) | | `IMAGE_NAME` | Name of the docker image (built and deployed) |
| `REGISTRY_LOCATION` | Location of the image registery | | `REGISTRY_LOCATION` | Location of the image registery |
| `PORT` | Port on which the site will be exposed on | | `REGISTRY_ORGANIZATION` | Name of the organisation in the image registery |
| `TEST_PORT` | Port on which the test container will be exposed on | | `PORT` | Port on which the site will be exposed on |
| `TEST_PORT` | Port on which the test container will be exposed on |
### Secrets ### Secrets
| Secrets | Description | | Secrets | Description |

View File

@@ -1,6 +1,6 @@
server { server {
listen ${NGINX_PORT}; listen 80;
server_name ${NGINX_SERVER_NAME}; server_name _;
root /usr/share/nginx/html; root /usr/share/nginx/html;
index index.html; index index.html;