-
Notifications
You must be signed in to change notification settings - Fork 339
Modernize and migrate builder workflow to new builder actions #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| name: Build app | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| app: | ||
| required: true | ||
| type: string | ||
| publish: | ||
| required: true | ||
| type: boolean | ||
|
|
||
| jobs: | ||
| prepare: | ||
| name: Prepare | ||
| if: github.repository == 'home-assistant/apps-example' | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| architectures: ${{ steps.info.outputs.architectures }} | ||
| build_matrix: ${{ steps.matrix.outputs.matrix }} | ||
| image_name: ${{ steps.normalize.outputs.image_name }} | ||
| registry_prefix: ${{ steps.normalize.outputs.registry_prefix }} | ||
| version: ${{ steps.normalize.outputs.version }} | ||
| steps: | ||
| - name: Check out the repository | ||
| uses: actions/checkout@v6.0.2 | ||
|
|
||
| - name: Get app information | ||
| id: info | ||
| uses: home-assistant/actions/helpers/info@master | ||
| with: | ||
| path: "./${{ inputs.app }}" | ||
|
|
||
| - name: Normalize app information | ||
| id: normalize | ||
| run: | | ||
| image="${{ steps.info.outputs.image }}" | ||
| echo "image_name=${image##*/}" >> "$GITHUB_OUTPUT" | ||
| echo "registry_prefix=${image%/*}" >> "$GITHUB_OUTPUT" | ||
| # Strip surrounding quotes that the info action includes from YAML string values | ||
| version="${{ steps.info.outputs.version }}" | ||
| echo "version=${version//[\"\']/}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Prepare build matrix | ||
| id: matrix | ||
| uses: home-assistant/builder/actions/prepare-multi-arch-matrix@2026.03.2 | ||
| with: | ||
| architectures: ${{ steps.info.outputs.architectures }} | ||
| image-name: ${{ steps.normalize.outputs.image_name }} | ||
| registry-prefix: ${{ steps.normalize.outputs.registry_prefix }} | ||
|
|
||
| build: | ||
| name: Build ${{ matrix.arch }} image | ||
| needs: prepare | ||
| runs-on: ${{ matrix.os }} | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| packages: write | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: ${{ fromJSON(needs.prepare.outputs.build_matrix) }} | ||
| steps: | ||
| - name: Check out the repository | ||
| uses: actions/checkout@v6.0.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Build image | ||
| uses: home-assistant/builder/actions/build-image@2026.03.2 | ||
| with: | ||
| arch: ${{ matrix.arch }} | ||
| container-registry-password: ${{ secrets.GITHUB_TOKEN }} | ||
| context: "./${{ inputs.app }}" | ||
| image: ${{ matrix.image }} | ||
| image-tags: | | ||
| ${{ needs.prepare.outputs.version }} | ||
| latest | ||
| push: ${{ inputs.publish }} | ||
| version: ${{ needs.prepare.outputs.version }} | ||
|
|
||
| manifest: | ||
| name: Publish multi-arch manifest | ||
| needs: [prepare, build] | ||
| if: inputs.publish | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| id-token: write | ||
| packages: write | ||
| steps: | ||
| - name: Publish multi-arch manifest | ||
| uses: home-assistant/builder/actions/publish-multi-arch-manifest@2026.03.2 | ||
| with: | ||
| architectures: ${{ needs.prepare.outputs.architectures }} | ||
| container-registry-password: ${{ secrets.GITHUB_TOKEN }} | ||
| image-name: ${{ needs.prepare.outputs.image_name }} | ||
| image-tags: | | ||
| ${{ needs.prepare.outputs.version }} | ||
| latest | ||
| registry-prefix: ${{ needs.prepare.outputs.registry_prefix }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,117 +1,81 @@ | ||
| name: Builder | ||
|
|
||
| env: | ||
| BUILD_ARGS: "--test" | ||
| MONITORED_FILES: "build.yaml config.yaml Dockerfile rootfs" | ||
| MONITORED_FILES: "config.json config.yaml config.yml Dockerfile rootfs" | ||
|
|
||
| on: | ||
| push: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| init: | ||
| runs-on: ubuntu-latest | ||
| name: Initialize builds | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| changed_addons: ${{ steps.changed_addons.outputs.addons }} | ||
| changed: ${{ steps.changed_addons.outputs.changed }} | ||
| changed: ${{ steps.filter.outputs.changed }} | ||
| changed_apps: ${{ steps.filter.outputs.changed_apps }} | ||
| steps: | ||
| - name: Check out the repository | ||
| uses: actions/checkout@v6.0.2 | ||
|
|
||
| - name: Get changed files | ||
| id: changed_files | ||
| uses: jitterbit/get-changed-files@v1 | ||
| uses: tj-actions/changed-files@v47 | ||
|
|
||
| - name: Find app directories | ||
| id: addons | ||
| id: apps | ||
| uses: home-assistant/actions/helpers/find-addons@master | ||
|
|
||
| - name: Get changed apps | ||
| id: changed_addons | ||
| - name: Filter changed apps | ||
| id: filter | ||
| env: | ||
| APPS: ${{ steps.apps.outputs.addons }} | ||
| CHANGED_FILES: ${{ steps.changed_files.outputs.all_changed_files }} | ||
| run: | | ||
| declare -a changed_addons | ||
| for addon in ${{ steps.addons.outputs.addons }}; do | ||
| if [[ "${{ steps.changed_files.outputs.all }}" =~ $addon ]]; then | ||
| for file in ${{ env.MONITORED_FILES }}; do | ||
| if [[ "${{ steps.changed_files.outputs.all }}" =~ $addon/$file ]]; then | ||
| if [[ ! "${changed_addons[@]}" =~ $addon ]]; then | ||
| changed_addons+=("\"${addon}\","); | ||
| fi | ||
| fi | ||
| done | ||
| fi | ||
| done | ||
| changed_apps=() | ||
|
|
||
| changed=$(echo ${changed_addons[@]} | rev | cut -c 2- | rev) | ||
| # If the workflow file itself changed, rebuild all apps | ||
| if [[ "${CHANGED_FILES}" =~ \.github/workflows/(builder|build-app)\.yaml ]]; then | ||
| changed_apps=(${APPS}) | ||
| else | ||
| for app in ${APPS}; do | ||
| for file in ${MONITORED_FILES}; do | ||
| if [[ "${CHANGED_FILES}" =~ ${app}/${file} ]]; then | ||
| changed_apps+=("${app}") | ||
| break | ||
| fi | ||
| done | ||
| done | ||
| fi | ||
|
|
||
| if [[ -n ${changed} ]]; then | ||
| echo "Changed apps: $changed"; | ||
| echo "changed=true" >> $GITHUB_OUTPUT; | ||
| echo "addons=[$changed]" >> $GITHUB_OUTPUT; | ||
| if [[ ${#changed_apps[@]} -gt 0 ]]; then | ||
| echo "changed=true" >> "$GITHUB_OUTPUT" | ||
| echo "changed_apps=$(jq -nc '$ARGS.positional' --args "${changed_apps[@]}")" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "No app had any monitored files changed (${{ env.MONITORED_FILES }})"; | ||
| echo "changed=false" >> "$GITHUB_OUTPUT" | ||
| fi | ||
| build: | ||
|
|
||
| build-app: | ||
| name: Build ${{ matrix.app }} | ||
| needs: init | ||
| runs-on: ubuntu-latest | ||
| if: needs.init.outputs.changed == 'true' | ||
| name: Build ${{ matrix.arch }} ${{ matrix.addon }} app | ||
| strategy: | ||
| matrix: | ||
| addon: ${{ fromJson(needs.init.outputs.changed_addons) }} | ||
| arch: ["aarch64", "amd64"] | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| packages: write | ||
|
|
||
| steps: | ||
| - name: Check out repository | ||
| uses: actions/checkout@v6.0.2 | ||
|
|
||
| - name: Get information | ||
| id: info | ||
| uses: home-assistant/actions/helpers/info@master | ||
| with: | ||
| path: "./${{ matrix.addon }}" | ||
|
|
||
| - name: Check if app should be built | ||
| id: check | ||
| run: | | ||
| if [[ "${{ steps.info.outputs.image }}" == "null" ]]; then | ||
| echo "Image property is not defined, skipping build" | ||
| echo "build_arch=false" >> $GITHUB_OUTPUT; | ||
| elif [[ "${{ steps.info.outputs.architectures }}" =~ ${{ matrix.arch }} ]]; then | ||
| echo "build_arch=true" >> $GITHUB_OUTPUT; | ||
| echo "image=$(echo ${{ steps.info.outputs.image }} | cut -d'/' -f3)" >> $GITHUB_OUTPUT; | ||
| if [[ -z "${{ github.head_ref }}" ]] && [[ "${{ github.event_name }}" == "push" ]]; then | ||
| echo "BUILD_ARGS=" >> $GITHUB_ENV; | ||
| fi | ||
| else | ||
| echo "${{ matrix.arch }} is not a valid arch for ${{ matrix.addon }}, skipping build"; | ||
| echo "build_arch=false" >> $GITHUB_OUTPUT; | ||
| fi | ||
|
|
||
| - name: Login to GitHub Container Registry | ||
| if: env.BUILD_ARGS != '--test' | ||
| uses: docker/login-action@v4.0.0 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.repository_owner }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Build ${{ matrix.addon }} app | ||
| if: steps.check.outputs.build_arch == 'true' | ||
| uses: home-assistant/builder@2026.02.1 | ||
| with: | ||
| args: | | ||
| ${{ env.BUILD_ARGS }} \ | ||
| --${{ matrix.arch }} \ | ||
| --target /data/${{ matrix.addon }} \ | ||
| --image "${{ steps.check.outputs.image }}" \ | ||
| --docker-hub "ghcr.io/${{ github.repository_owner }}" \ | ||
| --addon | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| app: ${{ fromJSON(needs.init.outputs.changed_apps) }} | ||
| uses: ./.github/workflows/build-app.yaml | ||
| with: | ||
| app: ${{ matrix.app }} | ||
| publish: ${{ github.event_name == 'push' }} | ||
| secrets: inherit |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,28 @@ | ||
| # https://developers.home-assistant.io/docs/apps/configuration#app-dockerfile | ||
| ARG BUILD_FROM | ||
| FROM $BUILD_FROM | ||
| ARG BUILD_FROM=ghcr.io/home-assistant/base:3.23 | ||
| FROM ${BUILD_FROM} | ||
|
|
||
| # Execute during the build of the image | ||
| ARG TEMPIO_VERSION BUILD_ARCH | ||
| ARG TEMPIO_VERSION=2021.09.0 | ||
| ARG TARGETARCH | ||
| RUN \ | ||
| curl -sSLf -o /usr/bin/tempio \ | ||
| "https://github.com/home-assistant/tempio/releases/download/${TEMPIO_VERSION}/tempio_${BUILD_ARCH}" | ||
| if [ -z "${TARGETARCH}" ]; then \ | ||
| echo "TARGETARCH is not set, please use Docker BuildKit for the build." && exit 1; \ | ||
| fi \ | ||
| && case "${TARGETARCH}" in \ | ||
| amd64) tempio_arch="amd64" ;; \ | ||
| arm64) tempio_arch="aarch64" ;; \ | ||
| *) echo "Unsupported TARGETARCH: ${TARGETARCH}" && exit 1 ;; \ | ||
| esac \ | ||
| && curl -sSLf -o /usr/bin/tempio \ | ||
| "https://github.com/home-assistant/tempio/releases/download/${TEMPIO_VERSION}/tempio_${tempio_arch}" | ||
|
|
||
| # Copy root filesystem | ||
| COPY rootfs / | ||
|
|
||
| LABEL \ | ||
| io.hass.type="addon" \ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we maybe introduce
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIRC Supervisor doesn't really consume it but defines it amongst its consts. So we should at least add it there (and maybe make some use of it?). Let's do it in a follow-up there and here before we update the docs. |
||
| org.opencontainers.image.title="Home Assistant App: Example app" \ | ||
| org.opencontainers.image.description="Example app to use as a blueprint for new apps." \ | ||
| org.opencontainers.image.source="https://github.com/home-assistant/apps-example" \ | ||
| org.opencontainers.image.licenses="Apache License 2.0" | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, not really new, but tempio is actually in the base image, so this is somewhat a bad example 🤔 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, right 😅 It does no harm as it works and just displays some patterns but we can come up with something more practical.