Skip to content

Release Stage 2 - Scheduled - Build and Push alpha Docker Images #21

Release Stage 2 - Scheduled - Build and Push alpha Docker Images

Release Stage 2 - Scheduled - Build and Push alpha Docker Images #21

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
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@v4
- 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
steps:
- name: Checkout
uses: actions/checkout@v4
- 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@v5
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'
uses: docker/build-push-action@v5
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:
manifest_file: ${{ steps.extract.outputs.manifest_file }}
package_changes: ${{ steps.extract_changes.outputs.package_changes }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Extract Docker.manifest from Image
id: extract
run: |
docker create --name temp-homebridge ghcr.io/homebridge/homebridge:${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }}
docker cp temp-homebridge:/opt/homebridge/Docker.manifest ./manifest.md
docker rm temp-homebridge
echo "manifest_file=manifest.md" >> $GITHUB_OUTPUT
- name: Generate Release Notes with Changes
id: generate_notes
run: |
# Get the previous release tag (excluding current one)
if [[ "${{ needs.set-versions.outputs.IS_BETA }}" == "true" ]]; then
PREVIOUS_TAG=$(gh release list --limit 50 | cut -f3 | grep -E "^beta-[0-9]{4}-[0-9]{2}-[0-9]{2}" | head -1)
elif [[ "${{ needs.set-versions.outputs.IS_ALPHA }}" == "true" ]]; then
PREVIOUS_TAG=$(gh release list --limit 50 | cut -f3 | grep -E "^alpha-[0-9]{4}-[0-9]{2}-[0-9]{2}" | head -1)
else
PREVIOUS_TAG=$(gh release list --limit 50 | cut -f3 | grep -vE "^(beta|alpha)-" | head -1)
fi
echo "Previous release tag: $PREVIOUS_TAG"
if [[ -n "$PREVIOUS_TAG" ]]; then
# Download previous manifest if it exists
if gh release download "$PREVIOUS_TAG" --pattern "Docker.manifest" --dir ./previous 2>/dev/null; then
echo -e "\n## Changes Since Previous Release ($PREVIOUS_TAG)\n" >> manifest.md
# Compare manifests and show differences
if ! diff -u ./previous/Docker.manifest ./manifest.md > manifest.diff 2>/dev/null; then
echo "### Package Version Changes" >> manifest.md
echo "\`\`\`diff" >> manifest.md
# Sort the diff output by package name for better readability
cat manifest.diff | grep -E "^[+-] \|" | sort -k2 | head -20 >> manifest.md
echo "\`\`\`" >> manifest.md
else
echo "No package version changes detected." >> manifest.md
fi
# Show Docker image specific changes
echo -e "\n### Docker Image Changes" >> manifest.md
echo "See [commit history](https://github.com/homebridge/docker-homebridge/compare/$PREVIOUS_TAG...${{ needs.set-versions.outputs.DOCKER_HOMEBRIDGE_VERSION }}) for Docker-specific changes." >> manifest.md
else
echo -e "\n## Changes Since Previous Release\n" >> manifest.md
echo "Previous release manifest not available for comparison." >> manifest.md
fi
else
echo -e "\n## Initial Release\n" >> manifest.md
echo "This appears to be the initial release." >> manifest.md
fi
env:
GITHUB_TOKEN: ${{ secrets.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 manifest.md)
# 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@v4
with:
name: manifest
path: manifest.md
create-release:
runs-on: ubuntu-latest
needs: [set-versions, extract-manifest]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download manifest artifact
uses: actions/download-artifact@v4
with:
name: manifest
path: .
- 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
cp manifest.md Docker.manifest
gh release create "${TAG_NAME}" \
--title "${{ needs.set-versions.outputs.RELEASE_TITLE }}" \
--notes-file manifest.md \
--draft=false \
Docker.manifest
- 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]
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, discord-notification]
uses: ./.github/workflows/validate-docker-container.yml
with:
release_tag: ${{ needs.set-versions.outputs.DOCKER_TAG }}