diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 000000000..9e25ca195 --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,199 @@ +name: Manual Rebuild and Republish Image +on: + workflow_dispatch: + +permissions: + contents: write + packages: write + +env: + IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/comfyui-docker + +jobs: + check-tag: + name: Resolve Current Tag + runs-on: ubuntu-latest + outputs: + current_tag: ${{ steps.resolve.outputs.current_tag }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + - name: Install prerequisites (jq, curl) + run: | + set -e + if ! command -v jq >/dev/null 2>&1; then + sudo apt-get update -y + sudo apt-get install -y jq curl + fi + - name: Determine current tag (release, then git fallback) + id: resolve + shell: bash + run: | + set -euo pipefail + REPO="${GITHUB_REPOSITORY}" + TAG=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | jq -r .tag_name || echo "") + if [ -z "${TAG}" ] || [ "${TAG}" = "null" ]; then + TAG=$(git describe --tags --abbrev=0 2>/dev/null || true) + fi + if [ -z "${TAG}" ]; then + echo "No existing release or tag found; aborting." >&2 + exit 1 + fi + echo "current_tag=${TAG}" >> "$GITHUB_OUTPUT" + + build-gh: + name: Build on GitHub Runner (primary) + needs: check-tag + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + cleanup: true + + - name: Check CR_PAT secret + id: crpat + shell: bash + run: | + if [ -n "${{ secrets.CR_PAT }}" ]; then + echo "present=true" >> "$GITHUB_OUTPUT" + else + echo "present=false" >> "$GITHUB_OUTPUT" + fi + + - name: Login to GHCR with GITHUB_TOKEN + if: ${{ steps.crpat.outputs.present == 'false' }} + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to GHCR with CR_PAT + if: ${{ steps.crpat.outputs.present == 'true' }} + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.CR_PAT }} + + - name: Build and Push (GH runner) + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + tags: | + ${{ env.IMAGE_NAME }}:${{ needs.check-tag.outputs.current_tag }} + ${{ env.IMAGE_NAME }}:latest + + build-self: + name: Build on Self-Hosted (fallback) + needs: [check-tag, build-gh] + if: needs.build-gh.result != 'success' + runs-on: [self-hosted, linux, x64, homelab] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + cleanup: true + + - name: Check CR_PAT secret + id: crpat + shell: bash + run: | + if [ -n "${{ secrets.CR_PAT }}" ]; then + echo "present=true" >> "$GITHUB_OUTPUT" + else + echo "present=false" >> "$GITHUB_OUTPUT" + fi + + - name: Login to GHCR with GITHUB_TOKEN + if: ${{ steps.crpat.outputs.present == 'false' }} + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to GHCR with CR_PAT + if: ${{ steps.crpat.outputs.present == 'true' }} + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.CR_PAT }} + + - name: Build and Push (self-hosted) + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + tags: | + ${{ env.IMAGE_NAME }}:${{ needs.check-tag.outputs.current_tag }} + ${{ env.IMAGE_NAME }}:latest + + publish: + name: Update Release and Cleanup + needs: [check-tag, build-gh, build-self] + if: needs.build-gh.result == 'success' || needs.build-self.result == 'success' + runs-on: ubuntu-latest + steps: + - name: Update GitHub Release (same tag) + uses: softprops/action-gh-release@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag_name: ${{ needs.check-tag.outputs.current_tag }} + name: Release ${{ needs.check-tag.outputs.current_tag }} + body: | + Rebuilt image for tag ${{ needs.check-tag.outputs.current_tag }}. + Docker image: + - docker pull ${{ env.IMAGE_NAME }}:${{ needs.check-tag.outputs.current_tag }} + - docker pull ${{ env.IMAGE_NAME }}:latest + draft: false + prerelease: false + + - name: Select package cleanup token + id: pkg_token + shell: bash + run: | + if [ -n "${{ secrets.CR_PAT }}" ]; then + echo "token=${{ secrets.CR_PAT }}" >> "$GITHUB_OUTPUT" + else + echo "token=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_OUTPUT" + fi + + - name: Prune untagged GHCR versions (multi-arch safe) + uses: dataaxiom/ghcr-cleanup-action@v1 + with: + token: ${{ steps.pkg_token.outputs.token }} + owner: ${{ github.repository_owner }} + repository: ${{ github.event.repository.name }} + package: comfyui-docker + delete-untagged: true + dry-run: false + + finalize: + name: Finalize Outcome + needs: [check-tag, build-gh, build-self, publish] + runs-on: ubuntu-latest + steps: + - name: Fail if both build paths failed + if: ${{ !(needs.build-gh.result == 'success' || needs.build-self.result == 'success') }} + run: | + echo "Manual rebuild failed on both GitHub-hosted and self-hosted paths." + exit 1