full upgrade (#31)
* ✨ chore: update CI workflow to include testing and multi-arch build (#29) * ✨ chore: remove unused dependencies from package-lock.json and updated to a better local dev environment (#30) * ✨ test: add unit tests * ✨ test: add unit tests for whole project * ✨ feat: add whatwg-fetch for improved fetch support * ✨ chore: update Node.js version to 22 in workflow * ✨ refactor: update types and improve email handling tests * ✨ refactor: remove unused imports * ✨ fix: normalize image name to lowercase in workflows * ✨ fix: ensure Docker image names are consistently lowercase * ✨ chore: update * ✨ chore: update base URL to use secret variable * ✨ chore: update to login to ghcr * ✨ fix: add missing 'fi' to close if statement in workflow
This commit is contained in:
97
.github/workflows/main.yml
vendored
97
.github/workflows/main.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Deploy Next.js to Raspberry Pi
|
||||
name: CI and Deploy to Raspberry Pi
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -8,11 +8,43 @@ on:
|
||||
- preview
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted # Der Runner sollte auf dem Raspberry Pi laufen
|
||||
|
||||
test_and_build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Run Tests
|
||||
run: npm run test
|
||||
|
||||
- name: Log in to GHCR
|
||||
run: |
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
||||
|
||||
- name: Build and Push Multi-Arch Docker Image
|
||||
run: |
|
||||
IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/my-nextjs-app:${{ github.ref_name }}"
|
||||
IMAGE_NAME=$(echo "$IMAGE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
docker buildx create --use
|
||||
docker buildx build \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
-t "$IMAGE_NAME" \
|
||||
--push \
|
||||
.
|
||||
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
needs: test_and_build
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Environment Variables
|
||||
@@ -28,52 +60,59 @@ jobs:
|
||||
echo "PORT=4002" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Build Docker Image
|
||||
- name: Log in to GHCR
|
||||
run: |
|
||||
IMAGE_NAME="my-nextjs-app:$DEPLOY_ENV"
|
||||
docker build -t $IMAGE_NAME .
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
||||
|
||||
- name: Pull Docker Image
|
||||
run: |
|
||||
IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/my-nextjs-app:${{ github.ref_name }}"
|
||||
IMAGE_NAME=$(echo "$IMAGE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
docker pull "$IMAGE_NAME"
|
||||
|
||||
- name: Deploy on Raspberry Pi (Zero-Downtime)
|
||||
run: |
|
||||
IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/my-nextjs-app:${{ github.ref_name }}"
|
||||
IMAGE_NAME=$(echo "$IMAGE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
CONTAINER_NAME="nextjs-$DEPLOY_ENV"
|
||||
IMAGE_NAME="my-nextjs-app:$DEPLOY_ENV"
|
||||
NEW_CONTAINER_NAME="$CONTAINER_NAME-new"
|
||||
NETWORK_NAME="big-bear-ghost_ghost-network"
|
||||
|
||||
# Remove existing temporary container, if any
|
||||
if [ "$(docker ps -aq -f name=$NEW_CONTAINER_NAME)" ]; then
|
||||
echo "Removing existing new container ($NEW_CONTAINER_NAME)..."
|
||||
docker rm -f "$NEW_CONTAINER_NAME" || true
|
||||
fi
|
||||
|
||||
# Start the new container on a temporary internal port
|
||||
docker run -d --name "$NEW_CONTAINER_NAME" --network $NETWORK_NAME -p 40000:3000 \
|
||||
# Start new container on a temporary internal port
|
||||
docker run -d --name "$NEW_CONTAINER_NAME" -p 40000:3000 \
|
||||
-e GHOST_API_KEY="${{ secrets.GHOST_API_KEY }}" \
|
||||
-e NEXT_PUBLIC_BASE_URL="https://dki.one" \
|
||||
$IMAGE_NAME
|
||||
-e NEXT_PUBLIC_BASE_URL="${{ secrets.NEXT_PUBLIC_BASE_URL }}" \
|
||||
-e MY_EMAIL="${{ secrets.MY_EMAIL }}" \
|
||||
-e MY_PASSWORD="${{ secrets.MY_PASSWORD }}" \
|
||||
-e GHOST_API_URL="${{ secrets.GHOST_API_URL }}" \
|
||||
"$IMAGE_NAME"
|
||||
|
||||
# Wait to ensure the new container is running
|
||||
# Wait for the new container to start
|
||||
sleep 10
|
||||
|
||||
# Check if the new container is running successfully
|
||||
if [ "$(docker inspect --format='{{.State.Running}}' $NEW_CONTAINER_NAME)" == "true" ]; then
|
||||
# Stop and remove the old container, if any
|
||||
if [ "$(docker inspect --format='{{.State.Running}}' $NEW_CONTAINER_NAME)" = "true" ]; then
|
||||
# Stop/remove the old container
|
||||
if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then
|
||||
docker stop "$CONTAINER_NAME" || true
|
||||
docker rm "$CONTAINER_NAME" || true
|
||||
docker rm "$CONTAINER_NAME" || true
|
||||
fi
|
||||
|
||||
# Stop and remove the temporary new container
|
||||
docker stop "$NEW_CONTAINER_NAME" || true
|
||||
docker rm "$NEW_CONTAINER_NAME" || true
|
||||
|
||||
# Start the container with the desired name and port
|
||||
docker run -d --name "$CONTAINER_NAME" --network $NETWORK_NAME -p $PORT:3000 \
|
||||
# Replace the new container with final name/port
|
||||
docker stop "$NEW_CONTAINER_NAME" || true
|
||||
docker rm "$NEW_CONTAINER_NAME" || true
|
||||
docker run -d --name "$CONTAINER_NAME" -p $PORT:3000 \
|
||||
-e GHOST_API_KEY="${{ secrets.GHOST_API_KEY }}" \
|
||||
-e NEXT_PUBLIC_BASE_URL="https://dki.one" \
|
||||
$IMAGE_NAME
|
||||
-e NEXT_PUBLIC_BASE_URL="${{ secrets.NEXT_PUBLIC_BASE_URL }}" \
|
||||
-e MY_EMAIL="${{ secrets.MY_EMAIL }}" \
|
||||
-e MY_PASSWORD="${{ secrets.MY_PASSWORD }}" \
|
||||
-e GHOST_API_URL="${{ secrets.GHOST_API_URL }}" \
|
||||
"$IMAGE_NAME"
|
||||
else
|
||||
echo "New container failed to start."
|
||||
docker logs $NEW_CONTAINER_NAME
|
||||
docker logs "$NEW_CONTAINER_NAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user