chore(release): v0.15.0 #56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Container Image | |
| on: | |
| # Release commits skip the ordinary main build. Tagged releases arrive through | |
| # repository_dispatch while exact-SHA public CI is verified after publication. | |
| push: | |
| branches: | |
| - main | |
| repository_dispatch: | |
| types: | |
| - container-image | |
| workflow_dispatch: | |
| inputs: | |
| push_ghcr: | |
| description: "Publish to GHCR with GHCR_TOKEN or github.token" | |
| type: boolean | |
| default: true | |
| push_dockerhub: | |
| description: "Publish the Docker Hub mirrors when credentials are configured" | |
| type: boolean | |
| default: true | |
| env: | |
| GHCR_IMAGE: ghcr.io/corgicorner/bisibility | |
| GHCR_WORKER_IMAGE: ghcr.io/corgicorner/bisibility-worker | |
| DOCKERHUB_IMAGE: docker.io/corgicorner/bisibility | |
| DOCKERHUB_WORKER_IMAGE: docker.io/corgicorner/bisibility-worker | |
| jobs: | |
| prepare: | |
| name: Prepare image metadata | |
| if: github.repository == 'CorgiCorner/bisibility' && (github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'chore(release):')) | |
| runs-on: ${{ github.repository != 'CorgiCorner/bisibility' && vars.CI_USE_DEPOT == 'true' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} | |
| timeout-minutes: 10 | |
| permissions: | |
| actions: read | |
| contents: read | |
| packages: write | |
| outputs: | |
| ghcr_enabled: ${{ steps.registries.outputs.ghcr_enabled }} | |
| dockerhub_enabled: ${{ steps.registries.outputs.dockerhub_enabled }} | |
| version: ${{ steps.version.outputs.version }} | |
| source_sha: ${{ steps.version.outputs.source_sha }} | |
| web_labels: ${{ steps.web-meta.outputs.labels }} | |
| worker_labels: ${{ steps.worker-meta.outputs.labels }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| ref: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.public_sha || github.sha }} | |
| - name: Resolve image version | |
| id: version | |
| env: | |
| DISPATCH_VERSION: ${{ github.event.client_payload.version }} | |
| DISPATCH_MINOR: ${{ github.event.client_payload.minor }} | |
| DISPATCH_MAJOR: ${{ github.event.client_payload.major }} | |
| DISPATCH_ORIGIN_SHA: ${{ github.event.client_payload.origin_sha }} | |
| DISPATCH_PUBLIC_SHA: ${{ github.event.client_payload.public_sha }} | |
| run: | | |
| package_version="$(node -p "require('./package.json').version")" | |
| version="${DISPATCH_VERSION:-$package_version}" | |
| source_sha="${DISPATCH_PUBLIC_SHA:-$GITHUB_SHA}" | |
| if [ "${GITHUB_EVENT_NAME}" = "repository_dispatch" ] && [ -z "${DISPATCH_PUBLIC_SHA}" ]; then | |
| echo "::error::repository_dispatch requires client_payload.public_sha." | |
| exit 1 | |
| fi | |
| if [ "${GITHUB_EVENT_NAME}" = "repository_dispatch" ] && [ -z "${DISPATCH_ORIGIN_SHA}" ]; then | |
| echo "::error::repository_dispatch requires client_payload.origin_sha." | |
| exit 1 | |
| fi | |
| if [ "${GITHUB_EVENT_NAME}" = "repository_dispatch" ] \ | |
| && ! [[ "${DISPATCH_ORIGIN_SHA}" =~ ^[0-9a-f]{40}$ ]]; then | |
| echo "::error::Origin commit is not a full Git SHA: ${DISPATCH_ORIGIN_SHA}" | |
| exit 1 | |
| fi | |
| if ! [[ "$source_sha" =~ ^[0-9a-f]{40}$ ]]; then | |
| echo "::error::Source commit is not a full Git SHA: $source_sha" | |
| exit 1 | |
| fi | |
| if [ "$(git rev-parse HEAD)" != "$source_sha" ]; then | |
| echo "::error::Checkout does not match source commit $source_sha." | |
| exit 1 | |
| fi | |
| if [ "${GITHUB_EVENT_NAME}" = "repository_dispatch" ] && [ "$version" != "$package_version" ]; then | |
| echo "::error::Dispatched version $version does not match package.json $package_version." | |
| exit 1 | |
| fi | |
| if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([+-][0-9A-Za-z.-]+)?$ ]]; then | |
| echo "::error::Image version is not valid SemVer: $version" | |
| exit 1 | |
| fi | |
| expected_minor="${version%.*}" | |
| expected_major="${version%%.*}" | |
| if [ "${GITHUB_EVENT_NAME}" = "repository_dispatch" ] \ | |
| && { [ "${DISPATCH_MINOR}" != "$expected_minor" ] || [ "${DISPATCH_MAJOR}" != "$expected_major" ]; }; then | |
| echo "::error::Dispatched major/minor tags do not match version $version." | |
| exit 1 | |
| fi | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "source_sha=$source_sha" >> "$GITHUB_OUTPUT" | |
| - name: Verify published public release source | |
| if: github.event_name == 'repository_dispatch' | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| ORIGIN_SHA: ${{ github.event.client_payload.origin_sha }} | |
| PUBLIC_SHA: ${{ steps.version.outputs.source_sha }} | |
| RELEASE_TAG: v${{ steps.version.outputs.version }} | |
| run: >- | |
| node scripts/ci/verify-public-release-source.mjs | |
| --repo "$GITHUB_REPOSITORY" | |
| --sha "$PUBLIC_SHA" | |
| --tag "$RELEASE_TAG" | |
| --origin-sha "$ORIGIN_SHA" | |
| --source-only | |
| - name: Select registries | |
| id: registries | |
| env: | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| PUSH_GHCR_INPUT: ${{ inputs.push_ghcr }} | |
| PUSH_DOCKERHUB_INPUT: ${{ inputs.push_dockerhub }} | |
| run: | | |
| set -euo pipefail | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ] && [ "${PUSH_GHCR_INPUT}" = "false" ] \ | |
| && [ "${PUSH_DOCKERHUB_INPUT}" = "false" ]; then | |
| echo "::error::No container registry is enabled for this run." | |
| exit 1 | |
| fi | |
| if [ "${GITHUB_EVENT_NAME}" != "workflow_dispatch" ] || [ "${PUSH_GHCR_INPUT}" != "false" ]; then | |
| echo "ghcr_enabled=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "ghcr_enabled=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| if { [ "${GITHUB_EVENT_NAME}" != "workflow_dispatch" ] || [ "${PUSH_DOCKERHUB_INPUT}" != "false" ]; } \ | |
| && [ -n "${DOCKERHUB_USERNAME}" ] && [ -n "${DOCKERHUB_TOKEN}" ]; then | |
| echo "dockerhub_enabled=true" >> "$GITHUB_OUTPUT" | |
| elif [ "${GITHUB_EVENT_NAME}" != "workflow_dispatch" ] || [ "${PUSH_DOCKERHUB_INPUT}" != "false" ]; then | |
| if [ "${GITHUB_EVENT_NAME}" = "repository_dispatch" ]; then | |
| echo "::error::Docker Hub credentials are required for release publication." | |
| exit 1 | |
| fi | |
| echo "::notice::Skipping Docker Hub because DOCKERHUB_USERNAME or DOCKERHUB_TOKEN is not configured." | |
| echo "dockerhub_enabled=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "dockerhub_enabled=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Extract web metadata | |
| id: web-meta | |
| uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6 | |
| with: | |
| images: ${{ env.GHCR_IMAGE }} | |
| labels: | | |
| org.opencontainers.image.title=bisibility | |
| org.opencontainers.image.description=Open-source search visibility platform | |
| org.opencontainers.image.licenses=AGPL-3.0-only | |
| org.opencontainers.image.url=https://bisibility.com | |
| org.opencontainers.image.source=https://github.com/CorgiCorner/bisibility | |
| org.opencontainers.image.documentation=https://bisibility.com/docs/self-hosting | |
| org.opencontainers.image.version=${{ steps.version.outputs.version }} | |
| org.opencontainers.image.revision=${{ steps.version.outputs.source_sha }} | |
| - name: Extract worker metadata | |
| id: worker-meta | |
| uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6 | |
| with: | |
| images: ${{ env.GHCR_WORKER_IMAGE }} | |
| labels: | | |
| org.opencontainers.image.title=bisibility worker | |
| org.opencontainers.image.description=Temporal worker for bisibility | |
| org.opencontainers.image.licenses=AGPL-3.0-only | |
| org.opencontainers.image.url=https://bisibility.com | |
| org.opencontainers.image.source=https://github.com/CorgiCorner/bisibility | |
| org.opencontainers.image.documentation=https://bisibility.com/docs/self-hosting | |
| org.opencontainers.image.version=${{ steps.version.outputs.version }} | |
| org.opencontainers.image.revision=${{ steps.version.outputs.source_sha }} | |
| build: | |
| name: Build ${{ matrix.image.registry }} ${{ matrix.image.runtime }} ${{ matrix.platform.arch }} | |
| if: github.repository == 'CorgiCorner/bisibility' | |
| needs: prepare | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| image: | |
| - registry: ghcr | |
| host: ghcr.io | |
| runtime: web | |
| image: ghcr.io/corgicorner/bisibility | |
| package: bisibility | |
| dockerfile: Dockerfile | |
| - registry: ghcr | |
| host: ghcr.io | |
| runtime: worker | |
| image: ghcr.io/corgicorner/bisibility-worker | |
| package: bisibility-worker | |
| dockerfile: Dockerfile.worker | |
| - registry: dockerhub | |
| host: docker.io | |
| runtime: web | |
| image: docker.io/corgicorner/bisibility | |
| package: bisibility | |
| dockerfile: Dockerfile | |
| - registry: dockerhub | |
| host: docker.io | |
| runtime: worker | |
| image: docker.io/corgicorner/bisibility-worker | |
| package: bisibility-worker | |
| dockerfile: Dockerfile.worker | |
| platform: | |
| - arch: amd64 | |
| value: linux/amd64 | |
| runner: ${{ github.repository != 'CorgiCorner/bisibility' && vars.CI_USE_DEPOT == 'true' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} | |
| - arch: arm64 | |
| value: linux/arm64 | |
| runner: ${{ github.repository != 'CorgiCorner/bisibility' && vars.CI_USE_DEPOT == 'true' && 'depot-ubuntu-24.04-arm' || 'ubuntu-24.04-arm' }} | |
| runs-on: ${{ matrix.platform.runner }} | |
| timeout-minutes: 90 | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| ref: ${{ needs.prepare.outputs.source_sha }} | |
| - name: Set up Docker Buildx | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4 | |
| - name: Log in to registry | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4 | |
| with: | |
| registry: ${{ matrix.image.host }} | |
| username: ${{ matrix.image.registry == 'ghcr' && (secrets.GHCR_USERNAME || github.actor) || secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ matrix.image.registry == 'ghcr' && (secrets.GHCR_TOKEN || github.token) || secrets.DOCKERHUB_TOKEN }} | |
| - name: Build and push image digest | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| id: build | |
| uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7 | |
| with: | |
| context: . | |
| file: ${{ matrix.image.dockerfile }} | |
| platforms: ${{ matrix.platform.value }} | |
| build-args: | | |
| APP_VERSION=${{ needs.prepare.outputs.source_sha }} | |
| APP_REVISION=${{ needs.prepare.outputs.source_sha }} | |
| labels: ${{ matrix.image.runtime == 'web' && needs.prepare.outputs.web_labels || needs.prepare.outputs.worker_labels }} | |
| outputs: type=image,name=${{ matrix.image.image }},push-by-digest=true,name-canonical=true,push=true | |
| cache-from: type=gha,scope=public-${{ matrix.image.runtime }}-${{ matrix.platform.arch }} | |
| cache-to: type=gha,mode=max,scope=public-${{ matrix.image.runtime }}-${{ matrix.platform.arch }} | |
| - name: Export digest | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| run: | | |
| mkdir -p "$RUNNER_TEMP/digests" | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "$RUNNER_TEMP/digests/${digest#sha256:}" | |
| - name: Upload digest | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: digests-${{ matrix.image.registry }}-${{ matrix.image.runtime }}-${{ matrix.platform.arch }} | |
| path: ${{ runner.temp }}/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| merge: | |
| name: Publish ${{ matrix.image.registry }} ${{ matrix.image.runtime }} manifest | |
| if: github.repository == 'CorgiCorner/bisibility' | |
| needs: | |
| - prepare | |
| - build | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| image: | |
| - registry: ghcr | |
| host: ghcr.io | |
| runtime: web | |
| image: ghcr.io/corgicorner/bisibility | |
| package: bisibility | |
| - registry: ghcr | |
| host: ghcr.io | |
| runtime: worker | |
| image: ghcr.io/corgicorner/bisibility-worker | |
| package: bisibility-worker | |
| - registry: dockerhub | |
| host: docker.io | |
| runtime: web | |
| image: docker.io/corgicorner/bisibility | |
| package: bisibility | |
| - registry: dockerhub | |
| host: docker.io | |
| runtime: worker | |
| image: docker.io/corgicorner/bisibility-worker | |
| package: bisibility-worker | |
| runs-on: ${{ github.repository != 'CorgiCorner/bisibility' && vars.CI_USE_DEPOT == 'true' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Set up Docker Buildx | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4 | |
| - name: Log in to registry | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4 | |
| with: | |
| registry: ${{ matrix.image.host }} | |
| username: ${{ matrix.image.registry == 'ghcr' && (secrets.GHCR_USERNAME || github.actor) || secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ matrix.image.registry == 'ghcr' && (secrets.GHCR_TOKEN || github.token) || secrets.DOCKERHUB_TOKEN }} | |
| - name: Download digests | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: ${{ runner.temp }}/digests | |
| pattern: digests-${{ matrix.image.registry }}-${{ matrix.image.runtime }}-* | |
| merge-multiple: true | |
| - name: Create and push multi-arch manifest | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| working-directory: ${{ runner.temp }}/digests | |
| env: | |
| IMAGE_NAME: ${{ matrix.image.image }} | |
| RELEASE_VERSION: ${{ github.event.client_payload.version }} | |
| RELEASE_MINOR: ${{ github.event.client_payload.minor }} | |
| RELEASE_MAJOR: ${{ github.event.client_payload.major }} | |
| SOURCE_SHA: ${{ needs.prepare.outputs.source_sha }} | |
| run: | | |
| tag_names=() | |
| if [ "${GITHUB_EVENT_NAME}" = "repository_dispatch" ]; then | |
| tag_names+=("${RELEASE_VERSION}" "${RELEASE_MINOR}" "${RELEASE_MAJOR}" "latest" "edge") | |
| elif [ "${GITHUB_REF}" = "refs/heads/main" ]; then | |
| tag_names+=("edge") | |
| fi | |
| tag_names+=("sha-${SOURCE_SHA::7}") | |
| tag_args=() | |
| for tag in "${tag_names[@]}"; do | |
| tag_args+=("-t" "${IMAGE_NAME}:${tag}") | |
| done | |
| source_args=() | |
| for digest in *; do | |
| source_args+=("${IMAGE_NAME}@sha256:${digest}") | |
| done | |
| docker buildx imagetools create "${tag_args[@]}" "${source_args[@]}" | |
| - name: Make GHCR package public | |
| if: matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GHCR_TOKEN || github.token }} | |
| PACKAGE_NAME: ${{ matrix.image.package }} | |
| run: | | |
| if ! gh api --method PATCH \ | |
| -H "Accept: application/vnd.github+json" \ | |
| -H "X-GitHub-Api-Version: 2022-11-28" \ | |
| "/orgs/corgicorner/packages/container/${PACKAGE_NAME}/visibility" \ | |
| -f visibility=public; then | |
| echo "::notice::GHCR visibility update was unavailable; anonymous pull verification remains authoritative." | |
| fi | |
| - name: Verify anonymous pull access | |
| if: (matrix.image.registry == 'ghcr' && needs.prepare.outputs.ghcr_enabled == 'true') || (matrix.image.registry == 'dockerhub' && needs.prepare.outputs.dockerhub_enabled == 'true') | |
| env: | |
| IMAGE_NAME: ${{ matrix.image.image }} | |
| SOURCE_SHA: ${{ needs.prepare.outputs.source_sha }} | |
| run: | | |
| docker logout "${{ matrix.image.host }}" | |
| for ((attempt = 1; attempt <= 5; attempt++)); do | |
| if docker buildx imagetools inspect "${IMAGE_NAME}:sha-${SOURCE_SHA::7}" >/dev/null; then | |
| exit 0 | |
| fi | |
| sleep 5 | |
| done | |
| echo "::error::Published image is not anonymously pullable: ${IMAGE_NAME}:sha-${SOURCE_SHA::7}" | |
| exit 1 | |
| verify-release: | |
| name: Verify release distribution | |
| if: >- | |
| github.repository == 'CorgiCorner/bisibility' && | |
| github.event_name == 'repository_dispatch' && | |
| needs.prepare.result == 'success' && | |
| needs.build.result == 'success' && | |
| needs.merge.result == 'success' | |
| needs: | |
| - prepare | |
| - build | |
| - merge | |
| runs-on: ${{ github.repository != 'CorgiCorner/bisibility' && vars.CI_USE_DEPOT == 'true' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout public release | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| ref: ${{ needs.prepare.outputs.source_sha }} | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4 | |
| - name: Verify manifest against published images | |
| run: | | |
| mkdir -p "$RUNNER_TEMP/release-assets" | |
| cp compose.yaml "$RUNNER_TEMP/release-assets/" | |
| cp compose.worker.yaml "$RUNNER_TEMP/release-assets/" | |
| cp compose.temporal.yaml "$RUNNER_TEMP/release-assets/" | |
| cp docker-compose.self-host.yml "$RUNNER_TEMP/release-assets/" | |
| cp .env.example "$RUNNER_TEMP/release-assets/bisibility.env.example" | |
| cp scripts/self-host/generate-env.mjs "$RUNNER_TEMP/release-assets/generate-self-host-env.mjs" | |
| cp upgrade.sh "$RUNNER_TEMP/release-assets/" | |
| node scripts/distribution/verify.mjs \ | |
| --manifest distribution-manifest.json \ | |
| --artifacts-dir "$RUNNER_TEMP/release-assets" \ | |
| --revision "${{ needs.prepare.outputs.source_sha }}" | |
| publish-release: | |
| name: Publish immutable release assets | |
| if: >- | |
| github.repository == 'CorgiCorner/bisibility' && | |
| github.event_name == 'repository_dispatch' && | |
| needs.verify-release.result == 'success' | |
| needs: | |
| - prepare | |
| - verify-release | |
| runs-on: ${{ github.repository != 'CorgiCorner/bisibility' && vars.CI_USE_DEPOT == 'true' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout public release | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| ref: ${{ needs.prepare.outputs.source_sha }} | |
| - name: Stage immutable release assets | |
| run: | | |
| mkdir -p "$RUNNER_TEMP/release-assets" | |
| cp compose.yaml "$RUNNER_TEMP/release-assets/" | |
| cp compose.worker.yaml "$RUNNER_TEMP/release-assets/" | |
| cp compose.temporal.yaml "$RUNNER_TEMP/release-assets/" | |
| cp docker-compose.self-host.yml "$RUNNER_TEMP/release-assets/" | |
| cp .env.example "$RUNNER_TEMP/release-assets/bisibility.env.example" | |
| cp scripts/self-host/generate-env.mjs "$RUNNER_TEMP/release-assets/generate-self-host-env.mjs" | |
| cp upgrade.sh "$RUNNER_TEMP/release-assets/" | |
| cp distribution-manifest.json "$RUNNER_TEMP/release-assets/" | |
| - name: Publish immutable release assets | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| RELEASE_TAG: v${{ github.event.client_payload.version }} | |
| run: | | |
| set -euo pipefail | |
| assets=( | |
| compose.yaml | |
| compose.worker.yaml | |
| compose.temporal.yaml | |
| docker-compose.self-host.yml | |
| bisibility.env.example | |
| generate-self-host-env.mjs | |
| upgrade.sh | |
| distribution-manifest.json | |
| ) | |
| if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then | |
| mkdir -p "$RUNNER_TEMP/published-assets" | |
| for asset in "${assets[@]}"; do | |
| gh release download "$RELEASE_TAG" \ | |
| --pattern "$asset" \ | |
| --dir "$RUNNER_TEMP/published-assets" | |
| cmp "$RUNNER_TEMP/release-assets/$asset" "$RUNNER_TEMP/published-assets/$asset" | |
| done | |
| echo "Release assets already exist and match byte-for-byte." | |
| exit 0 | |
| fi | |
| gh release create "$RELEASE_TAG" \ | |
| "$RUNNER_TEMP/release-assets/compose.yaml" \ | |
| "$RUNNER_TEMP/release-assets/compose.worker.yaml" \ | |
| "$RUNNER_TEMP/release-assets/compose.temporal.yaml" \ | |
| "$RUNNER_TEMP/release-assets/docker-compose.self-host.yml" \ | |
| "$RUNNER_TEMP/release-assets/bisibility.env.example" \ | |
| "$RUNNER_TEMP/release-assets/generate-self-host-env.mjs" \ | |
| "$RUNNER_TEMP/release-assets/upgrade.sh" \ | |
| "$RUNNER_TEMP/release-assets/distribution-manifest.json" \ | |
| --verify-tag \ | |
| --generate-notes \ | |
| --title "$RELEASE_TAG" | |
| sync-dockerhub-descriptions: | |
| name: Sync Docker Hub descriptions | |
| if: >- | |
| github.repository == 'CorgiCorner/bisibility' && | |
| github.event_name == 'repository_dispatch' && | |
| needs.prepare.outputs.dockerhub_enabled == 'true' && | |
| needs.publish-release.result == 'success' | |
| needs: | |
| - prepare | |
| - publish-release | |
| concurrency: | |
| group: dockerhub-description-sync | |
| cancel-in-progress: false | |
| runs-on: ${{ github.repository != 'CorgiCorner/bisibility' && vars.CI_USE_DEPOT == 'true' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout dispatched public release | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| ref: ${{ needs.prepare.outputs.source_sha }} | |
| - name: Set up Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6 | |
| with: | |
| node-version-file: .nvmrc | |
| - name: Update and verify Docker Hub descriptions | |
| env: | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| GITHUB_TOKEN: ${{ github.token }} | |
| RELEASE_TAG: v${{ github.event.client_payload.version }} | |
| run: node .github/scripts/sync-dockerhub-descriptions.mjs --version "$RELEASE_TAG" |