From 3f5b28a0b411a266c7fbd9306cafdab6679b3c69 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Thu, 19 Nov 2020 12:29:21 +0100 Subject: [PATCH] Use GitHub Actions (#1005) * Initial version of release workflow using GitHub Actions Add release workflow using GitHub Actions to replace the current Azure DevOps pipeline. Currently the same functionality is implemented. This uses multiple builds in parallel to make better use of CPU resources. Remove Azure DevOps pipeline. * Add GitHub Actions workflow for pull-request checks Lint Dockerfile and shell scripts when PRs are opened. * Use multiple runners in parallel Buildroot has stretches where CPU resources are not fully utilized. Spawn multiple builds accross builders to increase load. Also sort them by architecture to maximize ccache hit rate. * Checkout before validate version --- .github/workflows/pr-checks.yml | 20 +++++ .github/workflows/release.yml | 137 ++++++++++++++++++++++++++++++++ azure-pipelines-ci.yml | 53 ------------ azure-pipelines-release.yml | 97 ---------------------- 4 files changed, 157 insertions(+), 150 deletions(-) create mode 100644 .github/workflows/pr-checks.yml create mode 100644 .github/workflows/release.yml delete mode 100644 azure-pipelines-ci.yml delete mode 100644 azure-pipelines-release.yml diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 000000000..45df8726e --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,20 @@ +# Home Assistant Operating System pull-request checks + +name: PR checks + +on: [pull_request] + +jobs: + linters: + runs-on: ubuntu-20.04 + steps: + - name: Check out code + uses: actions/checkout@v1 + - name: Check Dockerfile + uses: brpaz/hadolint-action@v1.1.0 + with: + dockerfile: Dockerfile + - name: Check shell scripts + uses: ludeeus/action-shellcheck@1.0.0 + with: + ignore: "buildroot" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..520b19485 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,137 @@ +# Home Assistant Operating System release build workflow + +name: Release build + +on: + release: + types: [published] + +jobs: + validate_release: + name: Validate release + runs-on: [ "ubuntu-20.04" ] + outputs: + version: ${{ steps.version_check.outputs.version }} + steps: + - uses: actions/checkout@v2 + - name: Validate version + id: version_check + run: | + major=$(cat ${GITHUB_WORKSPACE}/buildroot-external/meta | grep VERSION_MAJOR | cut -d'=' -f2) + build=$(cat ${GITHUB_WORKSPACE}/buildroot-external/meta | grep VERSION_BUILD | cut -d'=' -f2) + if [ "${major}.${build}" != "${{ github.event.release.tag_name }}" ]; then + echo "Version number in Buildroot metadata is does not match tag (${major}.${build} vs ${{ github.event.release.tag_name }})." + exit 1 + fi + echo "::set-output name=version::${major}.${build}" + + build: + name: Release build for ${{ matrix.board.name }} + needs: validate_release + strategy: + matrix: + board: + - {"name": "ova", "output": "ova", "runner": "x86-64-runner"} + - {"name": "intel_nuc", "output": "intel-nuc", "runner": "x86-64-runner"} + - {"name": "odroid_c2", "output": "odroid-c2", "runner": "aarch64-runner"} + - {"name": "odroid_c4", "output": "odroid-c4", "runner": "aarch64-runner"} + - {"name": "odroid_n2", "output": "odroid-n2", "runner": "aarch64-runner"} + - {"name": "odroid_xu4", "output": "odroid-xu4" , "runner": "aarch64-runner"} + - {"name": "rpi", "output": "rpi", "runner": "arm-runner"} + - {"name": "rpi0_w", "output": "rpi0-w", "runner": "arm-runner"} + - {"name": "rpi2", "output": "rpi2", "runner": "arm-runner"} + - {"name": "rpi3", "output": "rpi3", "runner": "arm-runner"} + - {"name": "rpi3_64", "output": "rpi3-64", "runner": "aarch64-runner"} + - {"name": "rpi4", "output": "rpi4", "runner": "arm-runner"} + - {"name": "rpi4_64", "output": "rpi4-64", "runner": "aarch64-runner"} + - {"name": "tinker", "output": "tinker", "runner": "arm-runner"} + runs-on: ${{ matrix.board.runner }} + + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + - name: Build container + run: docker build -t haos-builder . + + - name: 'Add release PKI certs' + env: + RAUC_CERTIFICATE: ${{ secrets.RAUC_CERTIFICATE }} + RAUC_PRIVATE_KEY: ${{ secrets.RAUC_PRIVATE_KEY }} + run: | + echo -e "-----BEGIN CERTIFICATE-----\n${RAUC_CERTIFICATE}\n-----END CERTIFICATE-----" > cert.pem + echo -e "-----BEGIN PRIVATE KEY-----\n${RAUC_PRIVATE_KEY}\n-----END PRIVATE KEY-----" > key.pem + + - name: Build + run: | + BUILDER_UID="$(id -u)" + BUILDER_GID="$(id -g)" + docker run --rm --privileged -v "${GITHUB_WORKSPACE}:/build" \ + -e BUILDER_UID="${BUILDER_UID}" -e BUILDER_GID="${BUILDER_GID}" \ + -v "${{ matrix.board.runner }}-build-cache:/cache" \ + haos-builder make ${{ matrix.board.name }} + + - name: Upload disk image + if: ${{ matrix.board.name != 'ova' }} + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ github.workspace }}/release/hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.img.gz + asset_name: hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.img.gz + asset_content_type: application/gzip + + - name: Upload rauc update + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ github.workspace }}/release/hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.raucb + asset_name: hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.raucb + asset_content_type: application/octet-stream + + - name: Upload qcow2 image + if: ${{ matrix.board.name == 'ova' }} + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ github.workspace }}/release/hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.qcow2.gz + asset_name: hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.qcow2.gz + asset_content_type: application/gzip + + - name: Upload vdi image + if: ${{ matrix.board.name == 'ova' }} + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ github.workspace }}/release/hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.vdi.gz + asset_name: hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.vdi.gz + asset_content_type: application/gzip + + - name: Upload vhdx image + if: ${{ matrix.board.name == 'ova' }} + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ github.workspace }}/release/hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.vhdx.gz + asset_name: hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.vhdx.gz + asset_content_type: application/gzip + + - name: Upload vmdk image + if: ${{ matrix.board.name == 'ova' }} + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ github.workspace }}/release/hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.vmdk.gz + asset_name: hassos_${{ matrix.board.output }}-${{ needs.validate_release.outputs.version }}.vmdk.gz + asset_content_type: application/gzip diff --git a/azure-pipelines-ci.yml b/azure-pipelines-ci.yml deleted file mode 100644 index 998f14198..000000000 --- a/azure-pipelines-ci.yml +++ /dev/null @@ -1,53 +0,0 @@ -# https://dev.azure.com/home-assistant - -trigger: - batch: true - branches: - include: - - dev -pr: -- dev - -variables: - - name: versionHadolint - value: 'v1.17.2' - - name: versionShellCheck - value: 'v0.7.0' - -jobs: - -- job: 'Hadolint' - pool: - vmImage: 'ubuntu-16.04' - steps: - - script: | - sudo docker pull hadolint/hadolint:$(versionHadolint) - displayName: 'Install Hadolint' - - script: | - sudo docker run --rm -i \ - -v $(pwd)/.hadolint.yaml:/.hadolint.yaml:ro \ - hadolint/hadolint:$(versionHadolint) < Dockerfile - displayName: 'Run Hadolint' - - -- job: 'ShellCheck' - pool: - vmImage: 'ubuntu-16.04' - steps: - - script: | - sudo docker pull koalaman/shellcheck:$(versionShellCheck) - displayName: 'Install ShellCheck' - - script: | - set -e - - # Check build script - sudo docker run --rm -i \ - -v $(pwd):/mnt:ro koalaman/shellcheck:$(versionShellCheck) \ - scripts/*.sh \ - buildroot-external/scripts/*.sh \ - buildroot-external/board/**/*.sh \ - buildroot-external/ota/rauc-hook \ - buildroot-external/rootfs-overlay/usr/bin/* \ - buildroot-external/rootfs-overlay/usr/sbin/* \ - buildroot-external/rootfs-overlay/usr/libexec/* \ - displayName: 'Run ShellCheck' diff --git a/azure-pipelines-release.yml b/azure-pipelines-release.yml deleted file mode 100644 index 7453ad7fa..000000000 --- a/azure-pipelines-release.yml +++ /dev/null @@ -1,97 +0,0 @@ -# https://dev.azure.com/home-assistant - -trigger: - batch: true - tags: - include: - - '*' - exclude: - - untagged* -pr: none - -variables: - - name: versionGHR - value: 'v0.13.0' - - group: github - - group: rauc - -jobs: - -- job: 'VersionValidate' - condition: startsWith(variables['Build.SourceBranch'], 'refs/tags') - pool: - vmImage: 'ubuntu-latest' - steps: - - script: | - . buildroot-external/meta - - if [ "${VERSION_MAJOR}.${VERSION_BUILD}" != "$(Build.SourceBranchName)" ]; then - exit 1 - fi - displayName: 'Check version of branch/tag' - - -- job: 'Release' - dependsOn: - - 'VersionValidate' - timeoutInMinutes: 240 - pool: - name: 'Buildroot' - strategy: - maxParallel: 1 - matrix: - OpenVirtualAppliance: - board: 'ova' - IntelNuc: - board: 'intel_nuc' - OdroidC2: - board: 'odroid_c2' - OdroidC4: - board: 'odroid_c4' - OdroidN2: - board: 'odroid_n2' - OdroidXU4: - board: 'odroid_xu4' - RaspberryPi: - board: 'rpi' - RaspberryPi0-W: - board: 'rpi0_w' - RaspberryPi2: - board: 'rpi2' - RaspberryPi3: - board: 'rpi3' - RaspberryPi3-64: - board: 'rpi3_64' - RaspberryPi4: - board: 'rpi4' - RaspberryPi4-64: - board: 'rpi4_64' - AsusTinker: - board: 'tinker' - workspace: - clean: 'all' - steps: - - script: | - echo -e "-----BEGIN CERTIFICATE-----\n$(releaseCertificate)\n-----END CERTIFICATE-----" > cert.pem - echo -e "-----BEGIN PRIVATE KEY-----\n$(releaseKey)\n-----END PRIVATE KEY-----" > key.pem - displayName: 'Add release PKI certs' - - script: | - sudo docker build -t hassos:azure . - displayName: 'Build container for HassOS' - - script: | - curl -SsL https://github.com/tcnksm/ghr/releases/download/$(versionGHR)/ghr_$(versionGHR)_linux_amd64.tar.gz | tar xzf - - cp ghr_$(versionGHR)_linux_amd64/ghr . - rm -rf ghr_$(versionGHR)_linux_amd64 - displayName: 'Install GHR' - - script: | - BUILDER_UID="$(id -u)" - BUILDER_GID="$(id -g)" - - sudo docker run --rm --privileged -v "$(pwd):/build" \ - -e BUILDER_UID="${BUILDER_UID}" -e BUILDER_GID="${BUILDER_GID}" \ - -v "/mnt/build-cache:/cache" \ - hassos:azure make $(board) - displayName: 'Build $(board)' - - script: | - ./ghr -t $(githubToken) -replace $(Build.SourceBranchName) release/ - displayName: 'Upload $(board)'