name: Build images # yamllint disable-line rule:truthy on: workflow_dispatch: release: types: ["published"] schedule: - cron: "0 2 * * *" env: BUILD_TYPE: core DEFAULT_PYTHON: 3.9 jobs: init: name: Initialize build if: github.repository_owner == 'home-assistant' runs-on: ubuntu-latest outputs: architectures: ${{ steps.info.outputs.architectures }} version: ${{ steps.version.outputs.version }} channel: ${{ steps.version.outputs.channel }} publish: ${{ steps.version.outputs.publish }} steps: - name: Checkout the repository uses: actions/checkout@v3.0.2 with: fetch-depth: 0 - name: Set up Python ${{ env.DEFAULT_PYTHON }} uses: actions/setup-python@v4.1.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Get information id: info uses: home-assistant/actions/helpers/info@master - name: Get version id: version uses: home-assistant/actions/helpers/version@master with: type: ${{ env.BUILD_TYPE }} - name: Verify version uses: home-assistant/actions/helpers/verify-version@master with: ignore-dev: true - name: Generate meta info shell: bash run: | echo "${{ github.sha }};${{ github.ref }};${{ github.event_name }};${{ github.actor }}" > OFFICIAL_IMAGE - name: Signing meta info file uses: home-assistant/actions/helpers/codenotary@master with: source: file://${{ github.workspace }}/OFFICIAL_IMAGE asset: OFFICIAL_IMAGE-${{ steps.version.outputs.version }} token: ${{ secrets.CAS_TOKEN }} build_python: name: Build PyPi package needs: init runs-on: ubuntu-latest if: github.repository_owner == 'home-assistant' && needs.init.outputs.publish == 'true' steps: - name: Checkout the repository uses: actions/checkout@v3.0.2 - name: Set up Python ${{ env.DEFAULT_PYTHON }} uses: actions/setup-python@v4.1.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Build package shell: bash run: | # Remove dist, build, and homeassistant.egg-info # when build locally for testing! pip install twine build python -m build - name: Upload package shell: bash run: | export TWINE_USERNAME="__token__" export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}" twine upload dist/* --skip-existing build_base: name: Build ${{ matrix.arch }} base core image if: github.repository_owner == 'home-assistant' needs: init runs-on: ubuntu-latest strategy: matrix: arch: ${{ fromJson(needs.init.outputs.architectures) }} steps: - name: Checkout the repository uses: actions/checkout@v3.0.2 - name: Download nightly wheels of frontend if: needs.init.outputs.channel == 'dev' uses: dawidd6/action-download-artifact@v2 with: github_token: ${{secrets.GITHUB_TOKEN}} repo: home-assistant/frontend branch: dev workflow: nightly.yaml workflow_conclusion: success name: wheels - name: Set up Python ${{ env.DEFAULT_PYTHON }} if: needs.init.outputs.channel == 'dev' uses: actions/setup-python@v4.1.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Adjust nightly version if: needs.init.outputs.channel == 'dev' shell: bash run: | python3 -m pip install packaging tomli python3 -m pip install --use-deprecated=legacy-resolver . version="$(python3 script/version_bump.py nightly)" if [[ "$(ls home_assistant_frontend*.whl)" =~ ^home_assistant_frontend-(.*)-py3-none-any.whl$ ]]; then echo "Found frontend wheel, setting version to: ${BASH_REMATCH[1]}" frontend_version="${BASH_REMATCH[1]}" yq \ --inplace e -o json \ '.requirements = ["home-assistant-frontend=="+env(frontend_version)]' \ homeassistant/components/frontend/manifest.json sed -i "s|home-assistant-frontend==.*|home-assistant-frontend==${BASH_REMATCH[1]}|" \ homeassistant/package_constraints.txt python -m script.gen_requirements_all fi - name: Write meta info file shell: bash run: | echo "${{ github.sha }};${{ github.ref }};${{ github.event_name }};${{ github.actor }}" > rootfs/OFFICIAL_IMAGE - name: Login to DockerHub uses: docker/login-action@v2.0.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Login to GitHub Container Registry uses: docker/login-action@v2.0.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build base image uses: home-assistant/builder@2022.07.0 with: args: | $BUILD_ARGS \ --${{ matrix.arch }} \ --target /data \ --generic ${{ needs.init.outputs.version }} env: CAS_API_KEY: ${{ secrets.CAS_TOKEN }} build_machine: name: Build ${{ matrix.machine }} machine core image if: github.repository_owner == 'home-assistant' needs: ["init", "build_base"] runs-on: ubuntu-latest strategy: matrix: machine: - generic-x86-64 - intel-nuc - khadas-vim3 - odroid-c2 - odroid-c4 - odroid-n2 - odroid-xu - qemuarm - qemuarm-64 - qemux86 - qemux86-64 - raspberrypi - raspberrypi2 - raspberrypi3 - raspberrypi3-64 - raspberrypi4 - raspberrypi4-64 - tinker - yellow steps: - name: Checkout the repository uses: actions/checkout@v3.0.2 - name: Set build additional args run: | # Create general tags if [[ "${{ needs.init.outputs.version }}" =~ d ]]; then echo "BUILD_ARGS=--additional-tag dev" >> $GITHUB_ENV elif [[ "${{ needs.init.outputs.version }}" =~ b ]]; then echo "BUILD_ARGS=--additional-tag beta" >> $GITHUB_ENV else echo "BUILD_ARGS=--additional-tag stable" >> $GITHUB_ENV fi - name: Login to DockerHub uses: docker/login-action@v2.0.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Login to GitHub Container Registry uses: docker/login-action@v2.0.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build base image uses: home-assistant/builder@2022.07.0 with: args: | $BUILD_ARGS \ --target /data/machine \ --machine "${{ needs.init.outputs.version }}=${{ matrix.machine }}" env: CAS_API_KEY: ${{ secrets.CAS_TOKEN }} publish_ha: name: Publish version files if: github.repository_owner == 'home-assistant' needs: ["init", "build_machine"] runs-on: ubuntu-latest steps: - name: Checkout the repository uses: actions/checkout@v3.0.2 - name: Initialize git uses: home-assistant/actions/helpers/git-init@master with: name: ${{ secrets.GIT_NAME }} email: ${{ secrets.GIT_EMAIL }} token: ${{ secrets.GIT_TOKEN }} - name: Update version file uses: home-assistant/actions/helpers/version-push@master with: key: "homeassistant[]" key-description: "Home Assistant Core" version: ${{ needs.init.outputs.version }} channel: ${{ needs.init.outputs.channel }} - name: Update version file (stable -> beta) if: needs.init.outputs.channel == 'stable' uses: home-assistant/actions/helpers/version-push@master with: key: "homeassistant[]" key-description: "Home Assistant Core" version: ${{ needs.init.outputs.version }} channel: beta publish_container: name: Publish meta container for ${{ matrix.registry }} if: github.repository_owner == 'home-assistant' needs: ["init", "build_base"] runs-on: ubuntu-latest strategy: fail-fast: false matrix: registry: - "ghcr.io/home-assistant" - "homeassistant" steps: - name: Checkout the repository uses: actions/checkout@v3.0.2 - name: Login to DockerHub if: matrix.registry == 'homeassistant' uses: docker/login-action@v2.0.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Login to GitHub Container Registry if: matrix.registry == 'ghcr.io/home-assistant' uses: docker/login-action@v2.0.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Install CAS tools uses: home-assistant/actions/helpers/cas@master - name: Build Meta Image shell: bash run: | export DOCKER_CLI_EXPERIMENTAL=enabled function create_manifest() { local tag_l=${1} local tag_r=${2} docker manifest create "${{ matrix.registry }}/home-assistant:${tag_l}" \ "${{ matrix.registry }}/amd64-homeassistant:${tag_r}" \ "${{ matrix.registry }}/i386-homeassistant:${tag_r}" \ "${{ matrix.registry }}/armhf-homeassistant:${tag_r}" \ "${{ matrix.registry }}/armv7-homeassistant:${tag_r}" \ "${{ matrix.registry }}/aarch64-homeassistant:${tag_r}" docker manifest annotate "${{ matrix.registry }}/home-assistant:${tag_l}" \ "${{ matrix.registry }}/amd64-homeassistant:${tag_r}" \ --os linux --arch amd64 docker manifest annotate "${{ matrix.registry }}/home-assistant:${tag_l}" \ "${{ matrix.registry }}/i386-homeassistant:${tag_r}" \ --os linux --arch 386 docker manifest annotate "${{ matrix.registry }}/home-assistant:${tag_l}" \ "${{ matrix.registry }}/armhf-homeassistant:${tag_r}" \ --os linux --arch arm --variant=v6 docker manifest annotate "${{ matrix.registry }}/home-assistant:${tag_l}" \ "${{ matrix.registry }}/armv7-homeassistant:${tag_r}" \ --os linux --arch arm --variant=v7 docker manifest annotate "${{ matrix.registry }}/home-assistant:${tag_l}" \ "${{ matrix.registry }}/aarch64-homeassistant:${tag_r}" \ --os linux --arch arm64 --variant=v8 docker manifest push --purge "${{ matrix.registry }}/home-assistant:${tag_l}" } function validate_image() { local image=${1} if ! cas authenticate --signerID notary@home-assistant.io "docker://${image}"; then echo "Invalid signature!" exit 1 fi } docker pull "${{ matrix.registry }}/amd64-homeassistant:${{ needs.init.outputs.version }}" docker pull "${{ matrix.registry }}/i386-homeassistant:${{ needs.init.outputs.version }}" docker pull "${{ matrix.registry }}/armhf-homeassistant:${{ needs.init.outputs.version }}" docker pull "${{ matrix.registry }}/armv7-homeassistant:${{ needs.init.outputs.version }}" docker pull "${{ matrix.registry }}/aarch64-homeassistant:${{ needs.init.outputs.version }}" validate_image "${{ matrix.registry }}/amd64-homeassistant:${{ needs.init.outputs.version }}" validate_image "${{ matrix.registry }}/i386-homeassistant:${{ needs.init.outputs.version }}" validate_image "${{ matrix.registry }}/armhf-homeassistant:${{ needs.init.outputs.version }}" validate_image "${{ matrix.registry }}/armv7-homeassistant:${{ needs.init.outputs.version }}" validate_image "${{ matrix.registry }}/aarch64-homeassistant:${{ needs.init.outputs.version }}" # Create version tag create_manifest "${{ needs.init.outputs.version }}" "${{ needs.init.outputs.version }}" # Create general tags if [[ "${{ needs.init.outputs.version }}" =~ d ]]; then create_manifest "dev" "${{ needs.init.outputs.version }}" elif [[ "${{ needs.init.outputs.version }}" =~ b ]]; then create_manifest "beta" "${{ needs.init.outputs.version }}" create_manifest "rc" "${{ needs.init.outputs.version }}" else create_manifest "stable" "${{ needs.init.outputs.version }}" create_manifest "latest" "${{ needs.init.outputs.version }}" create_manifest "beta" "${{ needs.init.outputs.version }}" create_manifest "rc" "${{ needs.init.outputs.version }}" # Create series version tag (e.g. 2021.6) v="${{ needs.init.outputs.version }}" create_manifest "${v%.*}" "${{ needs.init.outputs.version }}" fi