mirror of
https://github.com/home-assistant/supervisor.git
synced 2026-04-02 00:07:16 +01:00
Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](faadad0cce...ba7bc0a3fe)
---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
dependency-version: 4.1.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
500 lines
18 KiB
YAML
500 lines
18 KiB
YAML
name: Build supervisor
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
channel:
|
|
description: "Channel"
|
|
required: true
|
|
default: "dev"
|
|
version:
|
|
description: "Version"
|
|
required: true
|
|
publish:
|
|
description: "Publish"
|
|
required: true
|
|
default: "false"
|
|
stable:
|
|
description: "Stable"
|
|
required: true
|
|
default: "false"
|
|
pull_request:
|
|
branches: ["main"]
|
|
release:
|
|
types: ["published"]
|
|
push:
|
|
branches: ["main"]
|
|
paths:
|
|
- "rootfs/**"
|
|
- "supervisor/**"
|
|
- build.yaml
|
|
- Dockerfile
|
|
- requirements.txt
|
|
- setup.py
|
|
|
|
env:
|
|
DEFAULT_PYTHON: "3.14.3"
|
|
COSIGN_VERSION: "v2.5.3"
|
|
CRANE_VERSION: "v0.20.7"
|
|
CRANE_SHA256: "8ef3564d264e6b5ca93f7b7f5652704c4dd29d33935aff6947dd5adefd05953e"
|
|
BUILD_NAME: supervisor
|
|
BUILD_TYPE: supervisor
|
|
|
|
concurrency:
|
|
group: "${{ github.workflow }}-${{ github.ref }}"
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
init:
|
|
name: Initialize build
|
|
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 }}
|
|
build_wheels: ${{ steps.requirements.outputs.build_wheels }}
|
|
steps:
|
|
- name: Checkout the repository
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- 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: Get changed files
|
|
id: changed_files
|
|
if: github.event_name == 'pull_request' || github.event_name == 'push'
|
|
uses: masesgroup/retrieve-changed-files@491e80760c0e28d36ca6240a27b1ccb8e1402c13 # v3.0.0
|
|
|
|
- name: Check if requirements files changed
|
|
id: requirements
|
|
run: |
|
|
# No wheels build necessary for releases
|
|
if [[ "${{ github.event_name }}" == "release" ]]; then
|
|
echo "build_wheels=false" >> "$GITHUB_OUTPUT"
|
|
# Always build wheels for manual dispatches
|
|
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
|
echo "build_wheels=true" >> "$GITHUB_OUTPUT"
|
|
elif [[ "${{ steps.changed_files.outputs.all }}" =~ (requirements\.txt|build\.yaml|\.github/workflows/builder\.yml) ]]; then
|
|
echo "build_wheels=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "build_wheels=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
build:
|
|
name: Build ${{ matrix.arch }} supervisor
|
|
needs: init
|
|
runs-on: ${{ matrix.runs-on }}
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
packages: write
|
|
strategy:
|
|
matrix:
|
|
arch: ${{ fromJson(needs.init.outputs.architectures) }}
|
|
include:
|
|
- runs-on: ubuntu-24.04
|
|
- runs-on: ubuntu-24.04-arm
|
|
arch: aarch64
|
|
env:
|
|
WHEELS_ABI: cp314
|
|
WHEELS_TAG: musllinux_1_2
|
|
WHEELS_APK_DEPS: "libffi-dev;openssl-dev;yaml-dev"
|
|
WHEELS_SKIP_BINARY: aiohttp
|
|
steps:
|
|
- name: Checkout the repository
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Write env-file for wheels build
|
|
if: needs.init.outputs.build_wheels == 'true'
|
|
run: |
|
|
(
|
|
# Fix out of memory issues with rust
|
|
echo "CARGO_NET_GIT_FETCH_WITH_CLI=true"
|
|
) > .env_file
|
|
|
|
- name: Build and publish wheels
|
|
if: needs.init.outputs.build_wheels == 'true' && needs.init.outputs.publish == 'true'
|
|
uses: home-assistant/wheels@e5742a69d69f0e274e2689c998900c7d19652c21 # 2025.12.0
|
|
with:
|
|
wheels-key: ${{ secrets.WHEELS_KEY }}
|
|
abi: ${{ env.WHEELS_ABI }}
|
|
tag: ${{ env.WHEELS_TAG }}
|
|
arch: ${{ matrix.arch }}
|
|
apk: ${{ env.WHEELS_APK_DEPS }}
|
|
skip-binary: ${{ env.WHEELS_SKIP_BINARY }}
|
|
env-file: true
|
|
requirements: "requirements.txt"
|
|
|
|
- name: Build local wheels
|
|
if: needs.init.outputs.build_wheels == 'true' && needs.init.outputs.publish == 'false'
|
|
uses: home-assistant/wheels@e5742a69d69f0e274e2689c998900c7d19652c21 # 2025.12.0
|
|
with:
|
|
wheels-host: ""
|
|
wheels-user: ""
|
|
wheels-key: ""
|
|
local-wheels-repo-path: "wheels/"
|
|
abi: ${{ env.WHEELS_ABI }}
|
|
tag: ${{ env.WHEELS_TAG }}
|
|
arch: ${{ matrix.arch }}
|
|
apk: ${{ env.WHEELS_APK_DEPS }}
|
|
skip-binary: ${{ env.WHEELS_SKIP_BINARY }}
|
|
env-file: true
|
|
requirements: "requirements.txt"
|
|
|
|
- name: Upload local wheels artifact
|
|
if: needs.init.outputs.build_wheels == 'true' && needs.init.outputs.publish == 'false'
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: wheels-${{ matrix.arch }}
|
|
path: wheels
|
|
retention-days: 1
|
|
|
|
- name: Set version
|
|
if: needs.init.outputs.publish == 'true'
|
|
uses: home-assistant/actions/helpers/version@master
|
|
with:
|
|
type: ${{ env.BUILD_TYPE }}
|
|
|
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
if: needs.init.outputs.publish == 'true'
|
|
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
with:
|
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
|
|
- name: Install Cosign
|
|
if: needs.init.outputs.publish == 'true'
|
|
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
|
|
with:
|
|
cosign-release: ${{ env.COSIGN_VERSION }}
|
|
|
|
- name: Install dirhash and calc hash
|
|
if: needs.init.outputs.publish == 'true'
|
|
run: |
|
|
pip3 install setuptools dirhash
|
|
dir_hash="$(dirhash "${{ github.workspace }}/supervisor" -a sha256 --match "*.py")"
|
|
echo "${dir_hash}" > rootfs/supervisor.sha256
|
|
|
|
- name: Sign supervisor SHA256
|
|
if: needs.init.outputs.publish == 'true'
|
|
run: |
|
|
cosign sign-blob --yes rootfs/supervisor.sha256 --bundle rootfs/supervisor.sha256.sig
|
|
|
|
- name: Login to GitHub Container Registry
|
|
if: needs.init.outputs.publish == 'true'
|
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.repository_owner }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Set build arguments
|
|
if: needs.init.outputs.publish == 'false'
|
|
run: echo "BUILD_ARGS=--test" >> $GITHUB_ENV
|
|
|
|
# home-assistant/builder doesn't support sha pinning
|
|
- name: Build supervisor
|
|
uses: home-assistant/builder@2026.02.1
|
|
with:
|
|
image: ${{ matrix.arch }}
|
|
args: |
|
|
$BUILD_ARGS \
|
|
--${{ matrix.arch }} \
|
|
--target /data \
|
|
--cosign \
|
|
--generic ${{ needs.init.outputs.version }}
|
|
|
|
version:
|
|
name: Update version
|
|
needs: ["init", "run_supervisor", "retag_deprecated"]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout the repository
|
|
if: needs.init.outputs.publish == 'true'
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Initialize git
|
|
if: needs.init.outputs.publish == 'true'
|
|
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
|
|
if: needs.init.outputs.publish == 'true'
|
|
uses: home-assistant/actions/helpers/version-push@master
|
|
with:
|
|
key: ${{ env.BUILD_NAME }}
|
|
version: ${{ needs.init.outputs.version }}
|
|
channel: ${{ needs.init.outputs.channel }}
|
|
|
|
run_supervisor:
|
|
runs-on: ubuntu-latest
|
|
name: Run the Supervisor
|
|
needs: ["build", "init"]
|
|
timeout-minutes: 60
|
|
steps:
|
|
- name: Checkout the repository
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Download local wheels artifact
|
|
if: needs.init.outputs.build_wheels == 'true' && needs.init.outputs.publish == 'false'
|
|
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
|
with:
|
|
name: wheels-amd64
|
|
path: wheels
|
|
|
|
# home-assistant/builder doesn't support sha pinning
|
|
- name: Build the Supervisor
|
|
if: needs.init.outputs.publish != 'true'
|
|
uses: home-assistant/builder@2026.02.1
|
|
with:
|
|
args: |
|
|
--test \
|
|
--amd64 \
|
|
--target /data \
|
|
--generic runner
|
|
|
|
- name: Pull Supervisor
|
|
if: needs.init.outputs.publish == 'true'
|
|
run: |
|
|
docker pull ghcr.io/home-assistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }}
|
|
docker tag ghcr.io/home-assistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }} ghcr.io/home-assistant/amd64-hassio-supervisor:runner
|
|
|
|
- name: Create the Supervisor
|
|
run: |
|
|
mkdir -p /tmp/supervisor/data
|
|
docker create --name hassio_supervisor \
|
|
--privileged \
|
|
--security-opt seccomp=unconfined \
|
|
--security-opt apparmor=unconfined \
|
|
-v /run/docker.sock:/run/docker.sock \
|
|
-v /run/dbus:/run/dbus \
|
|
-v /tmp/supervisor/data:/data \
|
|
-v /etc/machine-id:/etc/machine-id:ro \
|
|
-e SUPERVISOR_SHARE="/tmp/supervisor/data" \
|
|
-e SUPERVISOR_NAME=hassio_supervisor \
|
|
-e SUPERVISOR_DEV=1 \
|
|
-e SUPERVISOR_MACHINE="qemux86-64" \
|
|
ghcr.io/home-assistant/amd64-hassio-supervisor:runner
|
|
|
|
- name: Start the Supervisor
|
|
run: docker start hassio_supervisor
|
|
|
|
- &wait_for_supervisor
|
|
name: Wait for Supervisor to come up
|
|
run: |
|
|
until SUPERVISOR=$(docker inspect --format='{{.NetworkSettings.Networks.hassio.IPAddress}}' hassio_supervisor 2>/dev/null) && \
|
|
[ -n "$SUPERVISOR" ] && [ "$SUPERVISOR" != "<no value>" ]; do
|
|
echo "Waiting for network configuration..."
|
|
sleep 1
|
|
done
|
|
echo "Waiting for Supervisor API at http://${SUPERVISOR}/supervisor/ping"
|
|
timeout=300
|
|
elapsed=0
|
|
|
|
while [ $elapsed -lt $timeout ]; do
|
|
if response=$(curl -sSf "http://${SUPERVISOR}/supervisor/ping" 2>/dev/null); then
|
|
if echo "$response" | jq -e '.result == "ok"' >/dev/null 2>&1; then
|
|
echo "Supervisor is up! (took ${elapsed}s)"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
if [ $((elapsed % 15)) -eq 0 ]; then
|
|
echo "Still waiting... (${elapsed}s/${timeout}s)"
|
|
fi
|
|
|
|
sleep 5
|
|
elapsed=$((elapsed + 5))
|
|
done
|
|
|
|
echo "ERROR: Supervisor failed to start within ${timeout}s"
|
|
echo "Last response: $response"
|
|
echo "Checking supervisor logs..."
|
|
docker logs --tail 50 hassio_supervisor
|
|
exit 1
|
|
|
|
# Wait for Core to come up so subsequent steps (backup, addon install) succeed.
|
|
# On first startup, Supervisor installs Core via the "home_assistant_core_install"
|
|
# job (which pulls the image and then starts Core). Jobs with cleanup=True are
|
|
# removed from the jobs list once done, so we poll until it's gone.
|
|
- name: Wait for Core to be started
|
|
run: |
|
|
echo "Waiting for Home Assistant Core to be installed and started..."
|
|
timeout=300
|
|
elapsed=0
|
|
|
|
while [ $elapsed -lt $timeout ]; do
|
|
jobs=$(docker exec hassio_cli ha jobs info --no-progress --raw-json | jq -r '.data.jobs[] | select(.name == "home_assistant_core_install" and .done == false) | .name' 2>/dev/null)
|
|
if [ -z "$jobs" ]; then
|
|
echo "Home Assistant Core install/start complete (took ${elapsed}s)"
|
|
exit 0
|
|
fi
|
|
|
|
if [ $((elapsed % 15)) -eq 0 ]; then
|
|
echo "Core still installing... (${elapsed}s/${timeout}s)"
|
|
fi
|
|
|
|
sleep 5
|
|
elapsed=$((elapsed + 5))
|
|
done
|
|
|
|
echo "ERROR: Home Assistant Core failed to install/start within ${timeout}s"
|
|
docker logs --tail 50 hassio_supervisor
|
|
exit 1
|
|
|
|
- name: Check the Supervisor
|
|
run: |
|
|
echo "Checking supervisor info"
|
|
test=$(docker exec hassio_cli ha supervisor info --no-progress --raw-json | jq -r '.result')
|
|
if [ "$test" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
echo "Checking supervisor network info"
|
|
test=$(docker exec hassio_cli ha network info --no-progress --raw-json | jq -r '.result')
|
|
if [ "$test" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
- name: Check the Store / App
|
|
run: |
|
|
echo "Install Core SSH app"
|
|
test=$(docker exec hassio_cli ha apps install core_ssh --no-progress --raw-json | jq -r '.result')
|
|
if [ "$test" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
# Make sure it actually installed
|
|
test=$(docker exec hassio_cli ha apps info core_ssh --no-progress --raw-json | jq -r '.data.version')
|
|
if [[ "$test" == "null" ]]; then
|
|
exit 1
|
|
fi
|
|
|
|
echo "Start Core SSH app"
|
|
test=$(docker exec hassio_cli ha apps start core_ssh --no-progress --raw-json | jq -r '.result')
|
|
if [ "$test" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
# Make sure its state is started
|
|
test="$(docker exec hassio_cli ha apps info core_ssh --no-progress --raw-json | jq -r '.data.state')"
|
|
if [ "$test" != "started" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
- name: Create full backup
|
|
id: backup
|
|
run: |
|
|
test=$(docker exec hassio_cli ha backups new --no-progress --raw-json)
|
|
if [ "$(echo $test | jq -r '.result')" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
echo "slug=$(echo $test | jq -r '.data.slug')" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Uninstall SSH app
|
|
run: |
|
|
test=$(docker exec hassio_cli ha apps uninstall core_ssh --no-progress --raw-json | jq -r '.result')
|
|
if [ "$test" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
- name: Restart supervisor
|
|
run: |
|
|
test=$(docker exec hassio_cli ha supervisor restart --no-progress --raw-json | jq -r '.result')
|
|
if [ "$test" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
- *wait_for_supervisor
|
|
|
|
- name: Restore SSH app from backup
|
|
run: |
|
|
test=$(docker exec hassio_cli ha backups restore ${{ steps.backup.outputs.slug }} --app core_ssh --no-progress --raw-json | jq -r '.result')
|
|
if [ "$test" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
# Make sure it actually installed
|
|
test=$(docker exec hassio_cli ha apps info core_ssh --no-progress --raw-json | jq -r '.data.version')
|
|
if [[ "$test" == "null" ]]; then
|
|
exit 1
|
|
fi
|
|
|
|
# Make sure its state is started
|
|
test="$(docker exec hassio_cli ha apps info core_ssh --no-progress --raw-json | jq -r '.data.state')"
|
|
if [ "$test" != "started" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
- name: Restore SSL directory from backup
|
|
run: |
|
|
test=$(docker exec hassio_cli ha backups restore ${{ steps.backup.outputs.slug }} --folders ssl --no-progress --raw-json | jq -r '.result')
|
|
if [ "$test" != "ok" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
- name: Get supervisor logs on failiure
|
|
if: ${{ cancelled() || failure() }}
|
|
run: docker logs hassio_supervisor
|
|
|
|
retag_deprecated:
|
|
needs: ["build", "init"]
|
|
name: Re-tag deprecated ${{ matrix.arch }} images
|
|
if: needs.init.outputs.publish == 'true'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
packages: write
|
|
strategy:
|
|
matrix:
|
|
arch: ["armhf", "armv7", "i386"]
|
|
env:
|
|
# Last available release for deprecated architectures
|
|
FROZEN_VERSION: "2025.11.5"
|
|
steps:
|
|
- name: Login to GitHub Container Registry
|
|
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.repository_owner }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Install Cosign
|
|
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
|
|
with:
|
|
cosign-release: ${{ env.COSIGN_VERSION }}
|
|
|
|
- name: Install crane
|
|
run: |
|
|
curl -sLO https://github.com/google/go-containerregistry/releases/download/${{ env.CRANE_VERSION }}/go-containerregistry_Linux_x86_64.tar.gz
|
|
echo "${{ env.CRANE_SHA256 }} go-containerregistry_Linux_x86_64.tar.gz" | sha256sum -c -
|
|
tar xzf go-containerregistry_Linux_x86_64.tar.gz crane
|
|
sudo mv crane /usr/local/bin/
|
|
|
|
- name: Re-tag deprecated image with updated version label
|
|
run: |
|
|
crane auth login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
|
crane mutate \
|
|
--label io.hass.version=${{ needs.init.outputs.version }} \
|
|
--tag ghcr.io/home-assistant/${{ matrix.arch }}-hassio-supervisor:${{ needs.init.outputs.version }} \
|
|
ghcr.io/home-assistant/${{ matrix.arch }}-hassio-supervisor:${{ env.FROZEN_VERSION }}
|
|
|
|
- name: Sign image with Cosign
|
|
run: |
|
|
cosign sign --yes ghcr.io/home-assistant/${{ matrix.arch }}-hassio-supervisor:${{ needs.init.outputs.version }}
|