name: Publish Docker Images on: push: branches: - main paths: - "apps/server/**" - "apps/dashboard/**" - "apps/workflows/**" - "apps/private-location/**" - "apps/status-page/**" - "apps/checker/**" - "packages/**" - "docker-compose.yaml" workflow_dispatch: inputs: services: description: 'Services to build (comma-separated)' required: false default: 'server,dashboard,workflows,private-location,status-page,checker' type: string concurrency: group: docker-${{ github.ref }} cancel-in-progress: true env: REGISTRY: ghcr.io IMAGE_NAME: openstatus jobs: prepare: runs-on: ubuntu-latest outputs: services: ${{ steps.set-services.outputs.services }} steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 2 - name: Determine services to build id: set-services run: | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then # Convert comma-separated input to JSON array SERVICES=$(echo "${{ inputs.services }}" | tr ',' '\n' | jq -R . | jq -sc .) else # Detect changed files CHANGED=$(git diff --name-only HEAD~1 HEAD) SERVICES_LIST=() # packages/** changes affect all services if echo "$CHANGED" | grep -q '^packages/'; then SERVICES_LIST=("server" "dashboard" "workflows" "private-location" "status-page" "checker") else for svc in server dashboard workflows private-location status-page checker; do if echo "$CHANGED" | grep -q "^apps/$svc/"; then SERVICES_LIST+=("$svc") fi done fi SERVICES=$(printf '%s\n' "${SERVICES_LIST[@]}" | jq -R . | jq -sc .) fi echo "services=$SERVICES" >> "$GITHUB_OUTPUT" echo "Building services: $SERVICES" build-and-push: runs-on: ubuntu-latest needs: [prepare] if: needs.prepare.outputs.services != '[]' timeout-minutes: 30 permissions: contents: read id-token: write packages: write strategy: fail-fast: false matrix: service: ${{ fromJson(needs.prepare.outputs.services) }} include: - service: server context: . dockerfile: apps/server/Dockerfile - service: dashboard context: . dockerfile: apps/dashboard/Dockerfile - service: workflows context: . dockerfile: apps/workflows/Dockerfile - service: private-location context: apps/private-location dockerfile: apps/private-location/Dockerfile - service: status-page context: . dockerfile: apps/status-page/Dockerfile - service: checker context: apps/checker dockerfile: apps/checker/Dockerfile steps: - name: Checkout repository uses: actions/checkout@v6 - name: Lowercase owner run: echo "OWNER_LC=${GITHUB_REPOSITORY_OWNER,,}" >> $GITHUB_ENV - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}-${{ matrix.service }} tags: | type=ref,event=branch type=ref,event=pr type=sha,prefix= type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Docker image id: build uses: docker/build-push-action@v6 with: context: ${{ matrix.context }} file: ${{ matrix.dockerfile }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64 cache-from: type=gha cache-to: type=gha,mode=max provenance: false - name: Generate SBOM uses: anchore/sbom-action@v0 with: image: ${{ env.REGISTRY }}/${{ env.OWNER_LC }}/${{ env.IMAGE_NAME }}-${{ matrix.service }}@${{ steps.build.outputs.digest }} format: spdx-json output-file: sbom-${{ matrix.service }}.spdx.json - name: Upload SBOM uses: actions/upload-artifact@v4 with: name: sbom-${{ matrix.service }} path: sbom-${{ matrix.service }}.spdx.json retention-days: 30