Release Stage 2 - Scheduled - Build and Push stable Docker Images #115
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: Release Stage 2 - Build and Push Docker Images | |
| run-name: Release Stage 2 - ${{ github.event.inputs.Scheduled}} - Build and Push ${{ inputs.release_type }} Docker Images | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_type: | |
| description: 'Choose release type: "stable" (builds latest version), "beta" (builds beta version with beta-YYYY-MM-DD tag), or "alpha" (builds alpha version with alpha-YYYY-MM-DD tag).' | |
| required: true | |
| type: choice | |
| options: | |
| - stable | |
| - beta | |
| - alpha | |
| default: beta | |
| Scheduled: | |
| description: 'Whether this is a scheduled run' | |
| required: false | |
| type: choice | |
| options: | |
| - Scheduled | |
| - Manual | |
| - Testing | |
| default: Manual | |
| concurrency: | |
| group: stage-2-build-and-push | |
| cancel-in-progress: false | |
| jobs: | |
| set-versions: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| DOCKER_HOMEBRIDGE_VERSION: ${{ steps.docker_version.outputs.DOCKER_HOMEBRIDGE_VERSION }} | |
| IS_BETA: ${{ steps.check_beta.outputs.IS_BETA }} | |
| IS_ALPHA: ${{ steps.check_alpha.outputs.IS_ALPHA }} | |
| HOMEBRIDGE_APT_PKG_VERSION: ${{ steps.pkg_version.outputs.HOMEBRIDGE_APT_PKG_VERSION }} | |
| HOMEBRIDGE_APT_PKG_FILE: ${{ steps.pkg_version.outputs.HOMEBRIDGE_APT_PKG_FILE }} | |
| FFMPEG_FOR_HOMEBRIDGE_VERSION: ${{ steps.pkg_version.outputs.FFMPEG_FOR_HOMEBRIDGE_VERSION }} | |
| RELEASE_TITLE: ${{ steps.set_title.outputs.RELEASE_TITLE }} | |
| DOCKER_TAG: ${{ steps.pkg_version.outputs.DOCKER_TAG }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set Docker Homebridge version | |
| id: docker_version | |
| run: | | |
| if [[ "${{ inputs.release_type }}" == "beta" ]]; then | |
| export DOCKER_HOMEBRIDGE_VERSION="beta-$(date +%Y-%m-%d)" | |
| elif [[ "${{ inputs.release_type }}" == "alpha" ]]; then | |
| export DOCKER_HOMEBRIDGE_VERSION="alpha-$(date +%Y-%m-%d)" | |
| else | |
| export DOCKER_HOMEBRIDGE_VERSION="$(date +%Y-%m-%d)" | |
| fi | |
| echo "DOCKER_HOMEBRIDGE_VERSION=${DOCKER_HOMEBRIDGE_VERSION}" >> $GITHUB_OUTPUT | |
| - name: Check for beta release | |
| id: check_beta | |
| run: | | |
| if [[ "${{ inputs.release_type }}" == "beta" ]]; then | |
| if [[ -f beta/package.json ]]; then | |
| echo "IS_BETA=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "Error: beta/package.json is missing for beta release" | |
| exit 1 | |
| fi | |
| else | |
| echo "IS_BETA=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Check for alpha release | |
| id: check_alpha | |
| run: | | |
| if [[ "${{ inputs.release_type }}" == "alpha" ]]; then | |
| if [[ -f alpha/package.json ]]; then | |
| echo "IS_ALPHA=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "Error: alpha/package.json is missing for alpha release" | |
| exit 1 | |
| fi | |
| else | |
| echo "IS_ALPHA=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Set Package Versions | |
| id: pkg_version | |
| run: | | |
| if [[ "${{ steps.check_beta.outputs.IS_BETA }}" == "true" ]]; then | |
| export HOMEBRIDGE_APT_PKG_VERSION=$(jq -r '.dependencies["@homebridge/homebridge-apt-pkg"]' beta/package.json | sed 's/\^//') | |
| export HOMEBRIDGE_APT_PKG_FILE=$(echo "$HOMEBRIDGE_APT_PKG_VERSION" | sed 's/\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)-beta\(\.[0-9][0-9]*\)/\1.beta\2/') | |
| export FFMPEG_FOR_HOMEBRIDGE_VERSION=$(jq -r '.dependencies["ffmpeg-for-homebridge"]' beta/package.json | sed 's/\^//') | |
| echo "HOMEBRIDGE_APT_PKG_FILE=v${HOMEBRIDGE_APT_PKG_FILE}" >> $GITHUB_OUTPUT | |
| echo "DOCKER_TAG=beta" >> $GITHUB_OUTPUT | |
| elif [[ "${{ steps.check_alpha.outputs.IS_ALPHA }}" == "true" ]]; then | |
| export HOMEBRIDGE_APT_PKG_VERSION=$(jq -r '.dependencies["@homebridge/homebridge-apt-pkg"]' alpha/package.json | sed 's/\^//') | |
| export HOMEBRIDGE_APT_PKG_FILE=$(echo "$HOMEBRIDGE_APT_PKG_VERSION" | sed 's/\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)-alpha\(\.[0-9][0-9]*\)/\1.alpha\2/') | |
| export FFMPEG_FOR_HOMEBRIDGE_VERSION=$(jq -r '.dependencies["ffmpeg-for-homebridge"]' alpha/package.json | sed 's/\^//') | |
| echo "HOMEBRIDGE_APT_PKG_FILE=v${HOMEBRIDGE_APT_PKG_FILE}" >> $GITHUB_OUTPUT | |
| echo "DOCKER_TAG=alpha" >> $GITHUB_OUTPUT | |
| else | |
| export HOMEBRIDGE_APT_PKG_VERSION=$(jq -r '.dependencies["@homebridge/homebridge-apt-pkg"]' package.json | sed 's/\^//') | |
| export FFMPEG_FOR_HOMEBRIDGE_VERSION=$(jq -r '.dependencies["ffmpeg-for-homebridge"]' package.json | sed 's/\^//') | |
| echo "DOCKER_TAG=latest" >> $GITHUB_OUTPUT | |
| fi | |
| echo "HOMEBRIDGE_APT_PKG_VERSION=v${HOMEBRIDGE_APT_PKG_VERSION}" >> $GITHUB_OUTPUT | |
| echo "FFMPEG_FOR_HOMEBRIDGE_VERSION=v${FFMPEG_FOR_HOMEBRIDGE_VERSION}" >> $GITHUB_OUTPUT | |
| - name: Set Release Title | |
| id: set_title | |
| run: | | |
| if [[ "${{ steps.check_beta.outputs.IS_BETA }}" == "true" ]]; then | |
| echo "RELEASE_TITLE=BETA: Homebridge Docker Release ${{ steps.docker_version.outputs.DOCKER_HOMEBRIDGE_VERSION }}" >> $GITHUB_OUTPUT | |
| elif [[ "${{ steps.check_alpha.outputs.IS_ALPHA }}" == "true" ]]; then | |
| echo "RELEASE_TITLE=ALPHA: Homebridge Docker Release ${{ steps.docker_version.outputs.DOCKER_HOMEBRIDGE_VERSION }}" >> $GITHUB_OUTPUT | |
| else | |
| echo "RELEASE_TITLE=Homebridge Docker Release ${{ steps.docker_version.outputs.DOCKER_HOMEBRIDGE_VERSION }}" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Output versions | |
| run: | | |
| echo "::group::Version Information" | |
| echo "DOCKER_HOMEBRIDGE_VERSION=${{ steps.docker_version.outputs.DOCKER_HOMEBRIDGE_VERSION }}" | |
| echo "IS_BETA=${{ steps.check_beta.outputs.IS_BETA }}" | |
| echo "IS_ALPHA=${{ steps.check_alpha.outputs.IS_ALPHA }}" | |
| echo "HOMEBRIDGE_APT_PKG_VERSION=${{ steps.pkg_version.outputs.HOMEBRIDGE_APT_PKG_VERSION }}" | |
| echo "HOMEBRIDGE_APT_PKG_FILE=${{ steps.pkg_version.outputs.HOMEBRIDGE_APT_PKG_FILE }}" | |
| echo "FFMPEG_FOR_HOMEBRIDGE_VERSION=${{ steps.pkg_version.outputs.FFMPEG_FOR_HOMEBRIDGE_VERSION }}" | |
| echo "RELEASE_TITLE=${{ steps.set_title.outputs.RELEASE_TITLE }}" | |
| echo "DOCKER_TAG=${{ steps.pkg_version.outputs.DOCKER_TAG }}" | |
| echo "::endgroup::" | |
| build-images: | |
| runs-on: ubuntu-latest | |
| needs: set-versions | |
| outputs: | |
| docker_metadata: ${{ steps.docker_hub_build_and_push.outputs.metadata }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log into GitHub Container registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and Push Image to GitHub Container Registry | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64,linux/arm/v7,linux/arm64 | |
| push: true | |
| build-args: | | |
| HOMEBRIDGE_APT_PKG_VERSION=${{ needs.set-versions.outputs.HOMEBRIDGE_APT_PKG_VERSION }} | |
| ${{ (needs.set-versions.outputs.IS_BETA == 'true' || needs.set-versions.outputs.IS_ALPHA == 'true') && format('HOMEBRIDGE_APT_PKG_FILE={0}', needs.set-versions.outputs.HOMEBRIDGE_APT_PKG_FILE) || '' }} | |
| FFMPEG_FOR_HOMEBRIDGE_VERSION=${{ needs.set-versions.outputs.FFMPEG_FOR_HOMEBRIDGE_VERSION }} | |
| DOCKER_HOMEBRIDGE_VERSION=${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }} | |
| tags: | | |
| ${{ (needs.set-versions.outputs.IS_BETA == 'false' && needs.set-versions.outputs.IS_ALPHA == 'false') && 'ghcr.io/homebridge/homebridge:ubuntu' || '' }} | |
| ghcr.io/homebridge/homebridge:${{ needs.set-versions.outputs.DOCKER_TAG }} | |
| ghcr.io/homebridge/homebridge:${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }} | |
| - name: Log into Docker Hub | |
| uses: docker/login-action@v3 | |
| if: github.repository == 'homebridge/docker-homebridge' | |
| with: | |
| registry: docker.io | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Build and Push Image to Docker Hub | |
| if: github.repository == 'homebridge/docker-homebridge' | |
| id: docker_hub_build_and_push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64,linux/arm/v7,linux/arm64 | |
| push: true | |
| build-args: | | |
| HOMEBRIDGE_APT_PKG_VERSION=${{ needs.set-versions.outputs.HOMEBRIDGE_APT_PKG_VERSION }} | |
| ${{ (needs.set-versions.outputs.IS_BETA == 'true' || needs.set-versions.outputs.IS_ALPHA == 'true') && format('HOMEBRIDGE_APT_PKG_FILE={0}', needs.set-versions.outputs.HOMEBRIDGE_APT_PKG_FILE) || '' }} | |
| FFMPEG_FOR_HOMEBRIDGE_VERSION=${{ needs.set-versions.outputs.FFMPEG_FOR_HOMEBRIDGE_VERSION }} | |
| DOCKER_HOMEBRIDGE_VERSION=${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }} | |
| tags: | | |
| ${{ (needs.set-versions.outputs.IS_BETA == 'false' && needs.set-versions.outputs.IS_ALPHA == 'false') && 'homebridge/homebridge:ubuntu' || '' }} | |
| homebridge/homebridge:${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }} | |
| homebridge/homebridge:${{ needs.set-versions.outputs.DOCKER_TAG }} | |
| extract-manifest: | |
| runs-on: ubuntu-latest | |
| needs: [set-versions, build-images] | |
| outputs: | |
| release_body: ${{ steps.release_body.outputs.release_body }} | |
| package_changes: ${{ steps.extract_changes.outputs.package_changes }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Create Release Body | |
| id: release_body | |
| run: | | |
| ./scripts/create-release-body.sh "${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }}" "${{ inputs.release_type }}" | |
| echo "release_body=output/release-body.md" >> $GITHUB_OUTPUT | |
| echo "docker_manifest=output/Docker.manifest" >> $GITHUB_OUTPUT | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| - name: Extract package changes for Discord | |
| id: extract_changes | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Get the latest release to compare against (excluding the current one being created) | |
| if [[ "${{ needs.set-versions.outputs.IS_BETA }}" == "true" ]]; then | |
| # For beta releases, compare with the latest beta release | |
| LATEST_RELEASE=$(gh release list --limit 50 --json tagName | jq -r '.[] | select(.tagName | startswith("beta-")) | .tagName' | head -1) | |
| else | |
| # For stable releases, compare with the latest stable release (no beta prefix) | |
| LATEST_RELEASE=$(gh release list --limit 50 --json tagName | jq -r '.[] | select(.tagName | startswith("beta-") | not) | .tagName' | head -1) | |
| fi | |
| echo "Comparing with latest release: $LATEST_RELEASE" | |
| if [[ -n "$LATEST_RELEASE" ]]; then | |
| # Get the previous release manifest | |
| PREV_MANIFEST=$(gh release view "$LATEST_RELEASE" --json body | jq -r '.body') | |
| # Extract package versions from current manifest | |
| CURRENT_MANIFEST=$(cat ${{ steps.release_body.outputs.docker_manifest }}) | |
| # Parse package versions from both manifests | |
| extract_package_version() { | |
| local manifest="$1" | |
| local package="$2" | |
| echo "$manifest" | grep "|$package|" | awk -F'|' '{print $3}' | tr -d ' ' | |
| } | |
| # Compare packages and build changes summary | |
| PACKAGE_CHANGES="" | |
| packages=("Ubuntu" "ffmpeg for homebridge" "Homebridge APT Package" "NodeJS" "Homebridge UI" "Homebridge") | |
| for package in "${packages[@]}"; do | |
| current_version=$(extract_package_version "$CURRENT_MANIFEST" "$package") | |
| prev_version=$(extract_package_version "$PREV_MANIFEST" "$package") | |
| if [[ "$current_version" != "$prev_version" && -n "$current_version" && -n "$prev_version" ]]; then | |
| if [[ -n "$PACKAGE_CHANGES" ]]; then | |
| PACKAGE_CHANGES="$PACKAGE_CHANGES\n" | |
| fi | |
| PACKAGE_CHANGES="${PACKAGE_CHANGES}• **$package**: $prev_version → $current_version" | |
| fi | |
| done | |
| if [[ -z "$PACKAGE_CHANGES" ]]; then | |
| PACKAGE_CHANGES="• No package version changes detected" | |
| fi | |
| else | |
| PACKAGE_CHANGES="• Initial release - no previous version to compare" | |
| fi | |
| echo "Package changes:" | |
| echo -e "$PACKAGE_CHANGES" | |
| # Set output using multiline string | |
| { | |
| echo 'package_changes<<EOF' | |
| echo -e "$PACKAGE_CHANGES" | |
| echo 'EOF' | |
| } >> $GITHUB_OUTPUT | |
| - name: Upload manifest artifact | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: release-body | |
| path: ${{ steps.release_body.outputs.release_body }} | |
| create-release: | |
| runs-on: ubuntu-latest | |
| needs: [set-versions, extract-manifest, build-images] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download manifest artifact | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: release-body | |
| path: . | |
| - name: Display structure of downloaded files | |
| run: ls -R | |
| - name: Create GitHub Release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG_NAME=${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }} | |
| # Copy manifest for release asset with proper name | |
| gh release create "${TAG_NAME}" \ | |
| --title "${{ needs.set-versions.outputs.RELEASE_TITLE }}" \ | |
| --notes-file release-body.md \ | |
| --draft=false | |
| - name: Release created | |
| run: | | |
| echo "::notice::Release ${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }} - ${{ needs.set-versions.outputs.RELEASE_TITLE }} created successfully." | |
| discord-notification: | |
| name: Discord Webhooks | |
| needs: [set-versions, create-release, extract-manifest] | |
| if: ${{ inputs.release_type == 'stable' }} | |
| uses: homebridge/.github/.github/workflows/discord-webhooks.yml@latest | |
| with: | |
| title: "${{ needs.set-versions.outputs.RELEASE_TITLE }}" | |
| description: | | |
| Version `${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }}` | |
| url: "https://github.com/homebridge/docker-homebridge/releases/tag/${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }}" | |
| **Package Changes:** | |
| ${{ needs.extract-manifest.outputs.package_changes }} | |
| secrets: | |
| DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL_LATEST }} | |
| validate-container: | |
| name: Validate Docker Container | |
| needs: [set-versions, create-release] | |
| uses: ./.github/workflows/validate-docker-container.yml | |
| with: | |
| release_tag: ${{ needs.set-versions.outputs.DOCKER_TAG }} | |
| # stable release should be marked as non-prerelease, and latest | |
| stable-release-is-latest: | |
| needs: [create-release,set-versions] | |
| if: ${{ inputs.release_type == 'stable' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| # Mark stable release as non-prerelease and latest | |
| - name: Mark Stable Release as Non-Prerelease and Latest | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release edit ${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }} \ | |
| --prerelease=false \ | |
| --latest |