diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 03f2df3..d921c03 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,12 +1,9 @@ -name: Build Docker Images +name: Build and Push Docker Images on: push: branches: - main - pull_request: - branches: - - main jobs: build: @@ -14,64 +11,89 @@ jobs: permissions: packages: write contents: read - + strategy: + matrix: + project: + - admin-dashboard + - battleship + - calculator + - cv-project + - inventory + - library + - messages + - nodejs-mini-message-board + - portfolio + - restaurant + - shopping-cart + - signup_form + - tictactoe + - weather steps: - # Checkout the repository - name: Checkout code uses: actions/checkout@v4 - - # Log into the GitHub Container Registry - - name: Login to GHCR + + - name: Set Registry based on GITHUB_SERVER_URL + run: | + if [[ "${{ github.server_url }}" == *"github.com"* ]]; then + echo "REGISTRY=ghcr.io" >> $GITHUB_ENV + elif [[ "${{ github.server_url }}" == *"git.thecodedom.com"* ]]; then + echo "REGISTRY=git.thecodedom.com" >> $GITHUB_ENV + else + echo "REGISTRY=ghcr.io" >> $GITHUB_ENV + fi + echo "Registry is $REGISTRY" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: - registry: ghcr.io - username: ${{ github.actor }} + registry: ${{ env.registry }} + username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - # Define the list of project directories - - name: Set project list - id: set_projects - run: | - echo "projects<> $GITHUB_OUTPUT - echo "admin-dashboard" >> $GITHUB_OUTPUT - echo "battleship" >> $GITHUB_OUTPUT - echo "calculator" >> $GITHUB_OUTPUT - echo "cv" >> $GITHUB_OUTPUT - echo "cv-project" >> $GITHUB_OUTPUT - echo "inventory" >> $GITHUB_OUTPUT - echo "library" >> $GITHUB_OUTPUT - echo "messages" >> $GITHUB_OUTPUT - echo "nodejs-mini-message-board" >> $GITHUB_OUTPUT - echo "portfolio" >> $GITHUB_OUTPUT - echo "restaurant" >> $GITHUB_OUTPUT - echo "shopping-cart" >> $GITHUB_OUTPUT - echo "signup_form" >> $GITHUB_OUTPUT - echo "tictactoe" >> $GITHUB_OUTPUT - echo "todo" >> $GITHUB_OUTPUT - echo "weather" >> $GITHUB_OUTPUT - echo "auth-expressjs" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - # Build and push Docker images for changed projects - - name: Build and push Docker images - id: build_push + - name: Build and Push Docker Image + id: build-and-push env: - PROJECTS: ${{ steps.set_projects.outputs.projects }} + IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/odin-codeprojects/${{ matrix.project }} run: | - # Loop through each project directory - for project in $(cat <<< "$PROJECTS"); do - # Check if the project has changes - if git diff --quiet HEAD^ HEAD -- "$project" || git diff --quiet HEAD^ HEAD -- "${project}/devops"; then - echo "Changes detected in project: $project" - # Set the image name dynamically using github context - image_name="ghcr.io/${{ github.repository_owner }}/$project:${{ github.sha }}" - # Build the docker image - echo "Building image: $image_name" - docker build -t "$image_name" "$project/devops" - # Push the docker image to the github container registry - echo "Pushing image: $image_name" - docker push "$image_name" + IMAGE_TAG_LATEST=$IMAGE_NAME:latest + + # Check if the latest image exists in the registry + IMAGE_EXISTS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" "https://ghcr.io/v2/${{ github.repository_owner }}/${{ matrix.project }}/manifests/latest") + + + if [ "$IMAGE_EXISTS" == "200" ]; then + echo "Latest image exists, checking for changes..." + + # Get the latest image digest + LATEST_DIGEST=$(curl -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" "https://ghcr.io/v2/${{ github.repository_owner }}/${{ matrix.project }}/manifests/latest" | jq -r '.config.digest') + + # Get the digest of the current revision image + CURRENT_DIGEST=$(docker buildx bake --print ${{ matrix.project }}/devops/Dockerfile | grep '^sha256:' | head -n 1 | awk '{print $2}') + + if [ "$LATEST_DIGEST" == "$CURRENT_DIGEST" ]; then + echo "No changes detected, skipping build." else - echo "No changes detected in project: $project" + echo "Changes detected, building..." + docker buildx build \ + --push \ + -t $IMAGE_TAG_LATEST \ + -f ${{ matrix.project }}/devops/Dockerfile \ + --build-arg TARGET_REVISION=$(git rev-parse HEAD) \ + --cache-from type=gha \ + --cache-to type=gha,mode=max \ + ${{ matrix.project }} fi - done \ No newline at end of file + else + echo "Latest image does not exist, building..." + docker buildx build \ + --push \ + -t $IMAGE_TAG_LATEST \ + -f ${{ matrix.project }}/devops/Dockerfile \ + --build-arg TARGET_REVISION=$(git rev-parse HEAD) \ + --cache-from type=gha \ + --cache-to type=gha,mode=max \ + ${{ matrix.project }} + fi \ No newline at end of file