Files
jd-book-uploader-backend/.gitea/workflows/build.yml

138 lines
4.6 KiB
YAML

name: Build Application Image
on:
workflow_run:
workflows: ["Run Tests"]
types:
- completed
branches:
- main
- production
workflow_dispatch:
inputs:
image_tag:
description: 'Image tag (default: latest)'
required: false
default: 'latest'
env:
IMAGE_NAME: jd-book-uploader
IMAGE_TAG: ${{ inputs.image_tag || 'latest' }}
REGISTRY: ${{ secrets.REGISTRY_URL || '' }}
jobs:
build:
name: Build with Pack
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
outputs:
image: ${{ steps.image.outputs.full }}
image-digest: ${{ steps.build.outputs.digest }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
- name: Configure Docker Socket
run: |
# Prefer DOCKER_HOST if set (runner injects the real host socket path).
# This ensures pack passes the correct host path to lifecycle containers,
# which Podman can bind-mount without "mkdir permission denied".
if [ -n "$DOCKER_HOST" ]; then
echo "PACK_DOCKER_HOST=$DOCKER_HOST" >> $GITEA_ENV
elif [ -S "/run/user/$(id -u)/docker.sock" ]; then
echo "PACK_DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock" >> $GITEA_ENV
elif [ -S "/var/run/docker.sock" ]; then
echo "PACK_DOCKER_HOST=unix:///var/run/docker.sock" >> $GITEA_ENV
else
echo "Error: Docker socket not found"
exit 1
fi
docker info
- name: Install Pack CLI
run: |
PACK_VERSION="0.32.0"
wget -q "https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux.tgz"
tar -xzf "pack-v${PACK_VERSION}-linux.tgz"
sudo mv pack /usr/local/bin/
pack --version
- name: Set default builder
run: |
pack config default-builder paketobuildpacks/builder-jammy-tiny:latest
- name: Prepare build environment
run: |
# Create .env.production for build (no secrets, just structure)
cat > .env.production << EOF
PORT=8080
# Database and Firebase config loaded at runtime
EOF
- name: Build image
id: build
env:
PACK_DOCKER_HOST: ${{ env.PACK_DOCKER_HOST }}
run: |
PACK_ARGS=(
"${IMAGE_NAME}:${IMAGE_TAG}"
--path .
)
if [ -n "$PACK_DOCKER_HOST" ]; then
PACK_ARGS+=(--docker-host "$PACK_DOCKER_HOST")
fi
if [ -f ".env.production" ]; then
PACK_ARGS+=(--env-file .env.production)
fi
pack build "${PACK_ARGS[@]}"
IMAGE_DIGEST=$(docker inspect "${IMAGE_NAME}:${IMAGE_TAG}" --format='{{.Id}}')
echo "digest=${IMAGE_DIGEST}" >> $GITEA_OUTPUT
- name: Tag image
id: image
run: |
if [ -n "${{ env.REGISTRY }}" ]; then
FULL_IMAGE="${{ env.REGISTRY }}/${IMAGE_NAME}:${IMAGE_TAG}"
docker tag "${IMAGE_NAME}:${IMAGE_TAG}" "${FULL_IMAGE}"
echo "full=${FULL_IMAGE}" >> $GITEA_OUTPUT
else
echo "full=${IMAGE_NAME}:${IMAGE_TAG}" >> $GITEA_OUTPUT
fi
- name: Push to registry
if: env.REGISTRY != ''
run: |
# docker login sends POST /auth to Podman which incorrectly tries HTTPS even for
# insecure registries. Pre-populate config.json instead — docker push goes through
# the Podman daemon which correctly uses HTTP (insecure=true in registries.conf).
mkdir -p ~/.docker
AUTH=$(echo -n "${{ secrets.REGISTRY_USERNAME }}:${{ secrets.REGISTRY_PASSWORD }}" | base64 -w 0)
# Auth key must be the registry hostname only (e.g. host:port), not the full path
REGISTRY_HOST=$(echo "${{ env.REGISTRY }}" | cut -d'/' -f1)
echo "{\"auths\":{\"${REGISTRY_HOST}\":{\"auth\":\"${AUTH}\"}}}" > ~/.docker/config.json
docker push "${{ steps.image.outputs.full }}"
- name: Save image to file
if: env.REGISTRY == ''
run: |
docker save "${IMAGE_NAME}:${IMAGE_TAG}" -o /tmp/image.tar
- name: Upload image artifact
if: env.REGISTRY == ''
uses: actions/upload-artifact@v4
with:
name: docker-image
path: /tmp/image.tar
retention-days: 1