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.json
      - Dockerfile
      - requirements.txt
      - setup.py

env:
  BUILD_NAME: supervisor
  BUILD_TYPE: supervisor
  WHEELS_TAG: 3.8-alpine3.13

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 }}
      requirements: ${{ steps.requirements.outputs.changed }}
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v2
        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: steps.version.outputs.publish == 'false'
        uses: jitterbit/get-changed-files@v1

      - name: Check if requirements files changed
        id: requirements
        run: |
          if [[ "${{ steps.changed_files.outputs.all }}" =~ requirements.txt ]]; then
            echo "::set-output name=changed::true"
          fi

  build:
    name: Build ${{ matrix.arch }} supervisor
    needs: init
    runs-on: ubuntu-latest
    strategy:
      matrix:
        arch: ${{ fromJson(needs.init.outputs.architectures) }}
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Build wheels
        if: needs.init.outputs.requirements == 'true'
        uses: home-assistant/wheels@master
        with:
          tag: ${{ env.WHEELS_TAG }}
          arch: ${{ matrix.arch }}
          wheels-host: ${{ secrets.WHEELS_HOST }}
          wheels-key: ${{ secrets.WHEELS_KEY }}
          wheels-user: wheels
          apk: "build-base;libffi-dev;openssl-dev;cargo"
          skip-binary: aiohttp
          requirements: "requirements.txt"

      - name: Set version
        if: needs.init.outputs.publish == 'true'
        uses: home-assistant/actions/helpers/version@master
        with:
          type: ${{ env.BUILD_TYPE }}

      - name: Login to DockerHub
        if: needs.init.outputs.publish == 'true'
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Login to GitHub Container Registry
        if: needs.init.outputs.publish == 'true'
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ secrets.GIT_USER }}
          password: ${{ secrets.GIT_TOKEN }}

      - name: Set build arguments
        if: needs.init.outputs.publish == 'false'
        run: echo "BUILD_ARGS=--test" >> $GITHUB_ENV

      - name: Build supervisor
        uses: home-assistant/builder@2021.04.2
        with:
          args: |
            $BUILD_ARGS \
            --${{ matrix.arch }} \
            --target /data \
            --with-codenotary "${{ secrets.VCN_USER }}" "${{ secrets.VCN_PASSWORD }}" "${{ secrets.VCN_ORG }}" \
            --validate-from "${{ secrets.VCN_ORG }}" \
            --validate-cache "${{ secrets.VCN_ORG }}" \
            --generic ${{ needs.init.outputs.version }}

  codenotary:
    name: CodeNotary signature
    needs: init
    runs-on: ubuntu-latest
    steps:
      - name: Checkout the repository
        if: needs.init.outputs.publish == 'true'
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Set version
        if: needs.init.outputs.publish == 'true'
        uses: home-assistant/actions/helpers/version@master
        with:
          type: ${{ env.BUILD_TYPE }}

      - name: Signing image
        if: needs.init.outputs.publish == 'true'
        uses: home-assistant/actions/helpers/codenotary@master
        with:
          source: dir://${{ github.workspace }}
          user: ${{ secrets.VCN_USER }}
          password: ${{ secrets.VCN_PASSWORD }}
          organisation: ${{ secrets.VCN_ORG }}

  version:
    name: Update version
    needs: ["init", "run_supervisor"]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout the repository
        if: needs.init.outputs.publish == 'true'
        uses: actions/checkout@v2

      - 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", "codenotary", "init"]
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v2

      - name: Build the Supervisor
        if: needs.init.outputs.publish != 'true'
        uses: home-assistant/builder@2021.04.2
        with:
          args: |
            --test \
            --amd64 \
            --target /data \
            --generic runner

      - name: Pull Supervisor
        if: needs.init.outputs.publish == 'true'
        run: |
          docker pull homeassistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }}
          docker tag homeassistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }} homeassistant/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" \
          homeassistant/amd64-hassio-supervisor:runner

      - name: Start the Supervisor
        run: docker start hassio_supervisor

      - name: Wait for Supervisor to come up
        run: |
          SUPERVISOR=$(docker inspect --format='{{.NetworkSettings.IPAddress}}' hassio_supervisor)
          ping="error"
          while [ "$ping" != "ok" ]; do
            ping=$(curl -sSL "http://$SUPERVISOR/supervisor/ping" | jq -r '.result')
            sleep 5
          done
          docker logs hassio_supervisor

      - 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
            docker logs hassio_supervisor
            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
            docker logs hassio_supervisor
            exit 1
          fi

      - name: Check the Store / Addon
        run: |
          echo "Install Core SSH Add-on"
          test=$(docker exec hassio_cli ha addons install core_ssh --no-progress --raw-json | jq -r '.result')
          if [ "$test" != "ok" ];then
            docker logs hassio_supervisor
            exit 1
          fi

          echo "Start Core SSH Add-on"
          test=$(docker exec hassio_cli ha addons start core_ssh --no-progress --raw-json | jq -r '.result')
          if [ "$test" != "ok" ];then
            docker logs hassio_supervisor
            exit 1
          fi

      - name: Check the Supervisor code sign
        if: needs.init.outputs.publish == 'true'
        run: |
          echo "Enable Content-Trust"
          test=$(docker exec hassio_cli ha supervisor options --content-trust=true --no-progress --raw-json | jq -r '.result')
          if [ "$test" != "ok" ];then
            docker logs hassio_supervisor
            exit 1
          fi

          echo "Run supervisor health check"
          test=$(docker exec hassio_cli ha resolution healthcheck --no-progress --raw-json | jq -r '.result')
          if [ "$test" != "ok" ];then
            docker logs hassio_supervisor
            exit 1
          fi

          echo "Check supervisor unhealthy"
          test=$(docker exec hassio_cli ha resolution info --no-progress --raw-json | jq -r '.data.unhealthy[]')
          if [ "$test" != "" ];then
            docker logs hassio_supervisor
            exit 1
          fi
