diff --git a/.env b/.env new file mode 100644 index 0000000..f098803 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +RASPIOS_BUILD_DATE="2022-09-22" +RASPIOS_RELEASE_DATE="2022-09-26" diff --git a/.github/workflows/bullseye-experimental.yml b/.github/workflows/bullseye-experimental.yml deleted file mode 100644 index 77436a9..0000000 --- a/.github/workflows/bullseye-experimental.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: pi-topOS Experimental Bullseye Build - -on: - push: - branches: - - "**" - paths: - - "playbooks/**" - - "inventory" - - "ansible.cfg" - - ".github/workflows/bullseye-experimental.yml" - workflow_dispatch: - schedule: - # Run daily at midnight - - cron: '0 0 * * *' - -env: - DISTRO_NAME: "bullseye" - REPO_NAME: "experimental" # 'experimental', 'unstable', 'testing', 'release' - RASPIOS_BUILD_DATE: "2022-09-22" - RASPIOS_RELEASE_DATE: "2022-09-26" - -jobs: - build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - # armhf-lite - # armhf - - build_type_name: "armhf" - - steps: - - name: GitHub Environment Variables Action - uses: FranzDiebold/github-env-vars-action@v1.2.1 - - - name: Checkout code - uses: actions/checkout@v2.2.0 - with: - fetch-depth: 0 - - - name: Get RPi OS image name - run: | - echo "IMAGE_NAME=${{ env.RASPIOS_BUILD_DATE }}-raspios-${{ env.DISTRO_NAME }}-${{ matrix.build_type_name }}" >> $GITHUB_ENV - - - name: Install ansible and playbook dependencies - run: | - sudo apt-get update && sudo apt-get install -y ansible qemu-user-static unzip zerofree - - - name: Build - run: | - export ANSIBLE_FORCE_COLOR=true - export TERM=xterm-color - # chroot connection requires running as root - # 'ansible-playbook' is not in root user's PATH - ANSIBLE="sudo $(which ansible-playbook) -i inventory -vv" - - build_type_dir="raspios_$(echo ${{ matrix.build_type_name }} | python3 -c "import sys; print('_'.join(reversed(sys.stdin.read().strip().split('-'))))")" - url="https://downloads.raspberrypi.org/${build_type_dir}/images/${build_type_dir}-${{ env.RASPIOS_RELEASE_DATE }}/${{ env.IMAGE_NAME }}.img.xz" - - echo "==> Running get_raspios playbook..." - ${ANSIBLE} --extra-vars raspi_os_url=${url} \ - --extra-vars image_name=${{ env.IMAGE_NAME }} \ - playbooks/get_raspios.yml - - echo "==> Running mount_raspios playbook..." - ${ANSIBLE} --extra-vars image_name=${{ env.IMAGE_NAME }} \ - playbooks/mount_raspios.yml - - echo "==> Running create_pi_top_os_image playbook..." - ${ANSIBLE} playbooks/create_pi_top_os_image.yml - - echo "==> Running mount_pi_top_os playbook..." - ${ANSIBLE} playbooks/mount_pi_top_os.yml - - echo "==> Running install_pi_top_os playbook..." - ${ANSIBLE} --extra-vars repo_name=${{ env.REPO_NAME }} \ - playbooks/install_pi_top_os.yml - - echo "==> Running configure_pi_top_os playbook..." - ${ANSIBLE} --extra-vars distro_name=${{ env.DISTRO_NAME }} \ - --extra-vars build_number=${{ github.run_number || github.run_id }} \ - --extra-vars build_repo_commit="$(git rev-parse HEAD)" \ - --extra-vars build_repo_commit_short="$(git rev-parse --short HEAD)" \ - --extra-vars build_action_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ - --extra-vars build_repo_name="${{ env.REPO_NAME }}" \ - playbooks/configure_pi_top_os.yml - - echo "==> Running finalise_pi_top_image playbook..." - ${ANSIBLE} --extra-vars distro_name=${{ env.DISTRO_NAME }} \ - --extra-vars build_number=${{ github.run_number || github.run_id }} \ - --extra-vars build_repo_name="${{ env.REPO_NAME }}" \ - --extra-vars architecture="${{ matrix.build_type_name }}" \ - playbooks/finalise_pi_top_image.yml - - echo "==> Running analyse_build playbook..." - ${ANSIBLE} --extra-vars build_number=${{ github.run_number || github.run_id }} \ - playbooks/analyse_build.yml - - - name: Get zip filename - run: echo "ZIP_FILENAME=$(find playbooks/artifacts -name "*.zip" | head -n1)" >> $GITHUB_ENV - - - name: Get current date - id: date - run: echo "::set-output name=date::$(date +'%Y-%m-%d')" - - - name: Upload OS zip artifact - uses: actions/upload-artifact@v2 - with: - name: pi-topOS_${{ env.DISTRO_NAME }}_${{ env.REPO_NAME }}_${{ matrix.build_type_name }}_${{ steps.date.outputs.date }}_B${{ github.run_number || github.run_id }} - if-no-files-found: error - path: ${{ env.ZIP_FILENAME }} - - - name: Upload metadata artifact - uses: actions/upload-artifact@v2 - with: - name: metadata - if-no-files-found: error - path: | - playbooks/artifacts/* - !${{ env.ZIP_FILENAME }} diff --git a/.github/workflows/bullseye-stable.yml b/.github/workflows/bullseye-stable.yml deleted file mode 100644 index d43bb44..0000000 --- a/.github/workflows/bullseye-stable.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: pi-topOS Release Bullseye Build - -on: - workflow_dispatch: - -env: - DISTRO_NAME: "bullseye" - REPO_NAME: "release" # 'experimental', 'unstable', 'testing', 'release' - RASPIOS_BUILD_DATE: "2022-09-22" - RASPIOS_RELEASE_DATE: "2022-09-26" - -jobs: - build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - # armhf-lite - # armhf - - build_type_name: "armhf" - - steps: - - name: GitHub Environment Variables Action - uses: FranzDiebold/github-env-vars-action@v1.2.1 - - - name: Checkout code - uses: actions/checkout@v2.2.0 - with: - fetch-depth: 0 - - - name: Get RPi OS image name - run: | - echo "IMAGE_NAME=${{ env.RASPIOS_BUILD_DATE }}-raspios-${{ env.DISTRO_NAME }}-${{ matrix.build_type_name }}" >> $GITHUB_ENV - - - name: Install ansible and playbook dependencies - run: | - sudo apt-get update && sudo apt-get install -y ansible qemu-user-static unzip zerofree - - - name: Build - run: | - export ANSIBLE_FORCE_COLOR=true - export TERM=xterm-color - # chroot connection requires running as root - # 'ansible-playbook' is not in root user's PATH - ANSIBLE="sudo $(which ansible-playbook) -i inventory -vv" - - build_type_dir="raspios_$(echo ${{ matrix.build_type_name }} | python3 -c "import sys; print('_'.join(reversed(sys.stdin.read().strip().split('-'))))")" - url="https://downloads.raspberrypi.org/${build_type_dir}/images/${build_type_dir}-${{ env.RASPIOS_RELEASE_DATE }}/${{ env.IMAGE_NAME }}.img.xz" - - echo "==> Running get_raspios playbook..." - ${ANSIBLE} --extra-vars raspi_os_url=${url} \ - --extra-vars image_name=${{ env.IMAGE_NAME }} \ - playbooks/get_raspios.yml - - echo "==> Running mount_raspios playbook..." - ${ANSIBLE} --extra-vars image_name=${{ env.IMAGE_NAME }} \ - playbooks/mount_raspios.yml - - echo "==> Running create_pi_top_os_image playbook..." - ${ANSIBLE} playbooks/create_pi_top_os_image.yml - - echo "==> Running mount_pi_top_os playbook..." - ${ANSIBLE} playbooks/mount_pi_top_os.yml - - echo "==> Running install_pi_top_os playbook..." - ${ANSIBLE} --extra-vars repo_name=${{ env.REPO_NAME }} \ - playbooks/install_pi_top_os.yml - - echo "==> Running configure_pi_top_os playbook..." - ${ANSIBLE} --extra-vars distro_name=${{ env.DISTRO_NAME }} \ - --extra-vars build_number=${{ github.run_number || github.run_id }} \ - --extra-vars build_repo_commit="$(git rev-parse HEAD)" \ - --extra-vars build_repo_commit_short="$(git rev-parse --short HEAD)" \ - --extra-vars build_action_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ - --extra-vars build_repo_name="${{ env.REPO_NAME }}" \ - playbooks/configure_pi_top_os.yml - - echo "==> Running finalise_pi_top_image playbook..." - ${ANSIBLE} --extra-vars distro_name=${{ env.DISTRO_NAME }} \ - --extra-vars build_number=${{ github.run_number || github.run_id }} \ - --extra-vars build_repo_name="${{ env.REPO_NAME }}" \ - --extra-vars architecture="${{ matrix.build_type_name }}" \ - playbooks/finalise_pi_top_image.yml - - echo "==> Running analyse_build playbook..." - ${ANSIBLE} --extra-vars build_number=${{ github.run_number || github.run_id }} \ - playbooks/analyse_build.yml - - - name: Get zip filename - run: echo "ZIP_FILENAME=$(find playbooks/artifacts -name "*.zip" | head -n1)" >> $GITHUB_ENV - - - name: Get current date - id: date - run: echo "::set-output name=date::$(date +'%Y-%m-%d')" - - - name: Upload OS zip artifact - uses: actions/upload-artifact@v2 - with: - name: pi-topOS_${{ env.DISTRO_NAME }}_${{ env.REPO_NAME }}_${{ matrix.build_type_name }}_${{ steps.date.outputs.date }}_B${{ github.run_number || github.run_id }} - if-no-files-found: error - path: ${{ env.ZIP_FILENAME }} - - - name: Upload metadata artifact - uses: actions/upload-artifact@v2 - with: - name: metadata - if-no-files-found: error - path: | - playbooks/artifacts/* - !${{ env.ZIP_FILENAME }} - - - name: Upload OS zip to GCS - uses: google-github-actions/upload-cloud-storage@v0.4.0 - with: - credentials: ${{ secrets.GOOGLE_CLOUD_UPLOAD_JSON_CREDENTIALS }} - path: ${{ env.ZIP_FILENAME }} - destination: ${{ secrets.GOOGLE_CLOUD_OS_UPLOAD_BUCKET }}/pi-topOS-${{ env.DISTRO_NAME }}/ diff --git a/.github/workflows/bullseye-testing.yml b/.github/workflows/bullseye-testing.yml deleted file mode 100644 index 8dd6b5d..0000000 --- a/.github/workflows/bullseye-testing.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: pi-topOS Testing Bullseye Build - -on: - workflow_dispatch: - -env: - DISTRO_NAME: "bullseye" - REPO_NAME: "testing" # 'experimental', 'unstable', 'testing', 'release' - RASPIOS_BUILD_DATE: "2022-09-22" - RASPIOS_RELEASE_DATE: "2022-09-26" - -jobs: - build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - # armhf-lite - # armhf - - build_type_name: "armhf" - - steps: - - name: GitHub Environment Variables Action - uses: FranzDiebold/github-env-vars-action@v1.2.1 - - - name: Checkout code - uses: actions/checkout@v2.2.0 - with: - fetch-depth: 0 - - - name: Get RPi OS image name - run: | - echo "IMAGE_NAME=${{ env.RASPIOS_BUILD_DATE }}-raspios-${{ env.DISTRO_NAME }}-${{ matrix.build_type_name }}" >> $GITHUB_ENV - - - name: Install ansible and playbook dependencies - run: | - sudo apt-get update && sudo apt-get install -y ansible qemu-user-static unzip zerofree - - - name: Build - run: | - export ANSIBLE_FORCE_COLOR=true - export TERM=xterm-color - # chroot connection requires running as root - # 'ansible-playbook' is not in root user's PATH - ANSIBLE="sudo $(which ansible-playbook) -i inventory -vv" - - build_type_dir="raspios_$(echo ${{ matrix.build_type_name }} | python3 -c "import sys; print('_'.join(reversed(sys.stdin.read().strip().split('-'))))")" - url="https://downloads.raspberrypi.org/${build_type_dir}/images/${build_type_dir}-${{ env.RASPIOS_RELEASE_DATE }}/${{ env.IMAGE_NAME }}.img.xz" - - echo "==> Running get_raspios playbook..." - ${ANSIBLE} --extra-vars raspi_os_url=${url} \ - --extra-vars image_name=${{ env.IMAGE_NAME }} \ - playbooks/get_raspios.yml - - echo "==> Running mount_raspios playbook..." - ${ANSIBLE} --extra-vars image_name=${{ env.IMAGE_NAME }} \ - playbooks/mount_raspios.yml - - echo "==> Running create_pi_top_os_image playbook..." - ${ANSIBLE} playbooks/create_pi_top_os_image.yml - - echo "==> Running mount_pi_top_os playbook..." - ${ANSIBLE} playbooks/mount_pi_top_os.yml - - echo "==> Running install_pi_top_os playbook..." - ${ANSIBLE} --extra-vars repo_name=${{ env.REPO_NAME }} \ - playbooks/install_pi_top_os.yml - - echo "==> Running configure_pi_top_os playbook..." - ${ANSIBLE} --extra-vars distro_name=${{ env.DISTRO_NAME }} \ - --extra-vars build_number=${{ github.run_number || github.run_id }} \ - --extra-vars build_repo_commit="$(git rev-parse HEAD)" \ - --extra-vars build_repo_commit_short="$(git rev-parse --short HEAD)" \ - --extra-vars build_action_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ - --extra-vars build_repo_name="${{ env.REPO_NAME }}" \ - playbooks/configure_pi_top_os.yml - - echo "==> Running finalise_pi_top_image playbook..." - ${ANSIBLE} --extra-vars distro_name=${{ env.DISTRO_NAME }} \ - --extra-vars build_number=${{ github.run_number || github.run_id }} \ - --extra-vars build_repo_name="${{ env.REPO_NAME }}" \ - --extra-vars architecture="${{ matrix.build_type_name }}" \ - playbooks/finalise_pi_top_image.yml - - echo "==> Running analyse_build playbook..." - ${ANSIBLE} --extra-vars build_number=${{ github.run_number || github.run_id }} \ - playbooks/analyse_build.yml - - - name: Get zip filename - run: echo "ZIP_FILENAME=$(find playbooks/artifacts -name "*.zip" | head -n1)" >> $GITHUB_ENV - - - name: Get current date - id: date - run: echo "::set-output name=date::$(date +'%Y-%m-%d')" - - - name: Upload OS zip artifact - uses: actions/upload-artifact@v2 - with: - name: pi-topOS_${{ env.DISTRO_NAME }}_${{ env.REPO_NAME }}_${{ matrix.build_type_name }}_${{ steps.date.outputs.date }}_B${{ github.run_number || github.run_id }} - if-no-files-found: error - path: ${{ env.ZIP_FILENAME }} - - - name: Upload metadata artifact - uses: actions/upload-artifact@v2 - with: - name: metadata - if-no-files-found: error - path: | - playbooks/artifacts/* - !${{ env.ZIP_FILENAME }} - - - name: Upload OS zip to GCS - uses: google-github-actions/upload-cloud-storage@v0.4.0 - with: - credentials: ${{ secrets.GOOGLE_CLOUD_UPLOAD_JSON_CREDENTIALS }} - path: ${{ env.ZIP_FILENAME }} - destination: ${{ secrets.GOOGLE_CLOUD_OS_UPLOAD_BUCKET }}/pi-topOS-${{ env.DISTRO_NAME }}/ diff --git a/.github/workflows/bullseye-unstable.yml b/.github/workflows/bullseye-unstable.yml deleted file mode 100644 index dc8ef81..0000000 --- a/.github/workflows/bullseye-unstable.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: pi-topOS Unstable Bullseye Build - -on: - workflow_dispatch - -env: - DISTRO_NAME: "bullseye" - REPO_NAME: "unstable" # 'experimental', 'unstable', 'testing', 'release' - RASPIOS_BUILD_DATE: "2022-09-22" - RASPIOS_RELEASE_DATE: "2022-09-26" - -jobs: - build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - # armhf-lite - # armhf - - build_type_name: "armhf" - - steps: - - name: GitHub Environment Variables Action - uses: FranzDiebold/github-env-vars-action@v1.2.1 - - - name: Checkout code - uses: actions/checkout@v2.2.0 - with: - fetch-depth: 0 - - - name: Get RPi OS image name - run: | - echo "IMAGE_NAME=${{ env.RASPIOS_BUILD_DATE }}-raspios-${{ env.DISTRO_NAME }}-${{ matrix.build_type_name }}" >> $GITHUB_ENV - - - name: Install ansible and playbook dependencies - run: | - sudo apt-get update && sudo apt-get install -y ansible qemu-user-static unzip zerofree - - - name: Build - run: | - export ANSIBLE_FORCE_COLOR=true - export TERM=xterm-color - # chroot connection requires running as root - # 'ansible-playbook' is not in root user's PATH - ANSIBLE="sudo $(which ansible-playbook) -i inventory -vv" - - build_type_dir="raspios_$(echo ${{ matrix.build_type_name }} | python3 -c "import sys; print('_'.join(reversed(sys.stdin.read().strip().split('-'))))")" - url="https://downloads.raspberrypi.org/${build_type_dir}/images/${build_type_dir}-${{ env.RASPIOS_RELEASE_DATE }}/${{ env.IMAGE_NAME }}.img.xz" - - echo "==> Running get_raspios playbook..." - ${ANSIBLE} --extra-vars raspi_os_url=${url} \ - --extra-vars image_name=${{ env.IMAGE_NAME }} \ - playbooks/get_raspios.yml - - echo "==> Running mount_raspios playbook..." - ${ANSIBLE} --extra-vars image_name=${{ env.IMAGE_NAME }} \ - playbooks/mount_raspios.yml - - echo "==> Running create_pi_top_os_image playbook..." - ${ANSIBLE} playbooks/create_pi_top_os_image.yml - - echo "==> Running mount_pi_top_os playbook..." - ${ANSIBLE} playbooks/mount_pi_top_os.yml - - echo "==> Running install_pi_top_os playbook..." - ${ANSIBLE} --extra-vars repo_name=${{ env.REPO_NAME }} \ - playbooks/install_pi_top_os.yml - - echo "==> Running configure_pi_top_os playbook..." - ${ANSIBLE} --extra-vars distro_name=${{ env.DISTRO_NAME }} \ - --extra-vars build_number=${{ github.run_number || github.run_id }} \ - --extra-vars build_repo_commit="$(git rev-parse HEAD)" \ - --extra-vars build_repo_commit_short="$(git rev-parse --short HEAD)" \ - --extra-vars build_action_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ - --extra-vars build_repo_name="${{ env.REPO_NAME }}" \ - playbooks/configure_pi_top_os.yml - - echo "==> Running finalise_pi_top_image playbook..." - ${ANSIBLE} --extra-vars distro_name=${{ env.DISTRO_NAME }} \ - --extra-vars build_number=${{ github.run_number || github.run_id }} \ - --extra-vars build_repo_name="${{ env.REPO_NAME }}" \ - --extra-vars architecture="${{ matrix.build_type_name }}" \ - playbooks/finalise_pi_top_image.yml - - echo "==> Running analyse_build playbook..." - ${ANSIBLE} --extra-vars build_number=${{ github.run_number || github.run_id }} \ - playbooks/analyse_build.yml - - - name: Get zip filename - run: echo "ZIP_FILENAME=$(find playbooks/artifacts -name "*.zip" | head -n1)" >> $GITHUB_ENV - - - name: Get current date - id: date - run: echo "::set-output name=date::$(date +'%Y-%m-%d')" - - - name: Upload OS zip artifact - uses: actions/upload-artifact@v2 - with: - name: pi-topOS_${{ env.DISTRO_NAME }}_${{ env.REPO_NAME }}_${{ matrix.build_type_name }}_${{ steps.date.outputs.date }}_B${{ github.run_number || github.run_id }} - if-no-files-found: error - path: ${{ env.ZIP_FILENAME }} - - - name: Upload metadata artifact - uses: actions/upload-artifact@v2 - with: - name: metadata - if-no-files-found: error - path: | - playbooks/artifacts/* - !${{ env.ZIP_FILENAME }} - - - name: Upload OS zip to GCS - uses: google-github-actions/upload-cloud-storage@v0.4.0 - with: - credentials: ${{ secrets.GOOGLE_CLOUD_UPLOAD_JSON_CREDENTIALS }} - path: ${{ env.ZIP_FILENAME }} - destination: ${{ secrets.GOOGLE_CLOUD_OS_UPLOAD_BUCKET }}/pi-topOS-${{ env.DISTRO_NAME }}/ diff --git a/.github/workflows/experimental.yml b/.github/workflows/experimental.yml new file mode 100644 index 0000000..c88ac16 --- /dev/null +++ b/.github/workflows/experimental.yml @@ -0,0 +1,133 @@ +name: Experimental Build + +on: + push: + branches: + - "**" + paths: + - "playbooks/**" + - "inventory" + - "ansible.cfg" + - ".github/workflows/experimental.yml" + workflow_dispatch: + # No inputs defined here so that push behaviour matches all manual builds + schedule: + # Run daily at midnight + - cron: '0 0 * * *' + pull_request: + branches: + - master + + +env: + DISTRO_NAME: "bullseye" + REPO_NAME: "experimental" + +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + build_type_suffix: ["", "-lite"] + architecture: ["armhf", "arm64"] + + steps: + - name: GitHub Environment Variables Action + uses: FranzDiebold/github-env-vars-action@v1.2.1 + + - name: Checkout code + uses: actions/checkout@v2.2.0 + with: + fetch-depth: 0 + + - uses: aarcangeli/load-dotenv@v1.0.0 + + - name: Get build type and RPi OS image name + run: | + build_type="${{ matrix.architecture }}${{ matrix.build_type_suffix }}" + echo "BUILD_TYPE=${build_type}" >> $GITHUB_ENV + echo "IMAGE_NAME=${{ env.RASPIOS_BUILD_DATE }}-raspios-${{ env.DISTRO_NAME }}-${build_type}" >> $GITHUB_ENV + + - name: Install ansible and playbook dependencies + # Install 'qemu-user-static' >v5 to allow 'arm64' chroot + # 'ubuntu-20.04' (currently latest) does not have an up-to-date version, so we install from `ubuntu-security` repo + run: | + wget https://mirror.ip-projects.de/ubuntu-security/pool/universe/q/qemu/qemu-user-static_5.2+dfsg-9ubuntu3.1_amd64.deb + + sudo apt-get update && sudo apt-get install -y \ + ansible \ + unzip \ + zerofree \ + ./qemu-user-static_5.2+dfsg-9ubuntu3.1_amd64.deb + + - name: Build + run: | + export ANSIBLE_FORCE_COLOR=true + export TERM=xterm-color + # chroot connection requires running as root + # 'ansible-playbook' is not in root user's PATH + ANSIBLE="sudo $(which ansible-playbook) -i inventory -vv" + + build_type_dir="raspios_$(echo ${{ env.BUILD_TYPE }} | python3 -c "import sys; print('_'.join(reversed(sys.stdin.read().strip().split('-'))))")" + url="https://downloads.raspberrypi.org/${build_type_dir}/images/${build_type_dir}-${{ env.RASPIOS_RELEASE_DATE }}/${{ env.IMAGE_NAME }}.img.xz" + + echo "==> Running get_raspios playbook..." + ${ANSIBLE} --extra-vars "raspi_os_url=${url}" \ + --extra-vars "image_name=${{ env.IMAGE_NAME }}" \ + playbooks/get_raspios.yml + + echo "==> Running mount_raspios playbook..." + ${ANSIBLE} --extra-vars "image_name=${{ env.IMAGE_NAME }}" \ + playbooks/mount_raspios.yml + + echo "==> Running create_pi_top_os_image playbook..." + ${ANSIBLE} playbooks/create_pi_top_os_image.yml + + echo "==> Running mount_pi_top_os playbook..." + ${ANSIBLE} playbooks/mount_pi_top_os.yml + + echo "==> Running install_pi_top_os playbook..." + ${ANSIBLE} --extra-vars "repo_name=${{ env.REPO_NAME }}" \ + --extra-vars "distro_name=${{ env.DISTRO_NAME }}" \ + --extra-vars "top_level_pkg=pt-os${{ matrix.build_type_suffix }}" \ + --extra-vars "architecture=${{ matrix.architecture }}" \ + --extra-vars "{'full_install': ${{ matrix.build_type_suffix == '' }}}" \ + playbooks/install_pi_top_os.yml + + echo "==> Running configure_pi_top_os playbook..." + ${ANSIBLE} --extra-vars "distro_name=${{ env.DISTRO_NAME }}" \ + --extra-vars "build_number=${{ github.run_number || github.run_id }}" \ + --extra-vars "build_repo_commit=$(git rev-parse HEAD)" \ + --extra-vars "build_repo_commit_short=$(git rev-parse --short HEAD)" \ + --extra-vars "build_action_url=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ + --extra-vars "build_repo_name=${{ env.REPO_NAME }}" \ + --extra-vars "build_type=${{ env.BUILD_TYPE }}" \ + playbooks/configure_pi_top_os.yml + + echo "==> Running finalise_pi_top_image playbook..." + ${ANSIBLE} --extra-vars "distro_name=${{ env.DISTRO_NAME }}" \ + --extra-vars "build_number=${{ github.run_number || github.run_id }}" \ + --extra-vars "build_repo_name=${{ env.REPO_NAME }}" \ + --extra-vars "build_type=${{ env.BUILD_TYPE }}" \ + playbooks/finalise_pi_top_image.yml + + echo "==> Running analyse_build playbook..." + ${ANSIBLE} --extra-vars "build_number=${{ github.run_number || github.run_id }}" \ + playbooks/analyse_build.yml + + - name: Get current date + id: date + run: echo "DATE_STAMP=$(date +'%Y-%m-%d')" >> $GITHUB_ENV + + - name: Upload OS zip contents + uses: actions/upload-artifact@v2 + with: + name: pi-topOS_${{ env.DISTRO_NAME }}_${{ env.REPO_NAME }}_${{ env.BUILD_TYPE }}_${{ env.DATE_STAMP }}_B${{ github.run_number || github.run_id }} + if-no-files-found: error + path: | + playbooks/artifacts/* + !**/*.zip + + - name: Print metadata + run: cat playbooks/artifacts/metadata.txt diff --git a/.github/workflows/pt-os.yml b/.github/workflows/pt-os.yml new file mode 100644 index 0000000..d2424ff --- /dev/null +++ b/.github/workflows/pt-os.yml @@ -0,0 +1,135 @@ +name: pi-topOS Build + +on: + workflow_dispatch: + inputs: + repo_name: + description: 'Repository to build against' + required: true + default: 'release' + type: choice + options: + - unstable + - testing + - release + distro_name: + description: 'OS distribution' + required: true + default: 'bullseye' + type: string + +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + build_type_suffix: ["", "-lite"] + architecture: ["armhf", "arm64"] + + steps: + - name: GitHub Environment Variables Action + uses: FranzDiebold/github-env-vars-action@v1.2.1 + + - name: Checkout code + uses: actions/checkout@v2.2.0 + with: + fetch-depth: 0 + + - uses: aarcangeli/load-dotenv@v1.0.0 + + - name: Get build type and RPi OS image name + run: | + build_type="${{ matrix.architecture }}${{ matrix.build_type_suffix }}" + echo "BUILD_TYPE=${build_type}" >> $GITHUB_ENV + echo "IMAGE_NAME=${{ env.RASPIOS_BUILD_DATE }}-raspios-${{ inputs.distro_name }}-${build_type}" >> $GITHUB_ENV + + - name: Install ansible and playbook dependencies + # Install 'qemu-user-static' >v5 to allow 'arm64' chroot + # 'ubuntu-20.04' (currently latest) does not have an up-to-date version, so we install from `ubuntu-security` repo + run: | + wget https://mirror.ip-projects.de/ubuntu-security/pool/universe/q/qemu/qemu-user-static_5.2+dfsg-9ubuntu3.1_amd64.deb + + sudo apt-get update && sudo apt-get install -y \ + ansible \ + unzip \ + zerofree \ + ./qemu-user-static_5.2+dfsg-9ubuntu3.1_amd64.deb + + - name: Build + run: | + export ANSIBLE_FORCE_COLOR=true + export TERM=xterm-color + # chroot connection requires running as root + # 'ansible-playbook' is not in root user's PATH + ANSIBLE="sudo $(which ansible-playbook) -i inventory -vv" + + build_type_dir="raspios_$(echo ${{ env.BUILD_TYPE }} | python3 -c "import sys; print('_'.join(reversed(sys.stdin.read().strip().split('-'))))")" + url="https://downloads.raspberrypi.org/${build_type_dir}/images/${build_type_dir}-${{ env.RASPIOS_RELEASE_DATE }}/${{ env.IMAGE_NAME }}.img.xz" + + echo "==> Running get_raspios playbook..." + ${ANSIBLE} --extra-vars "raspi_os_url=${url}" \ + --extra-vars "image_name=${{ env.IMAGE_NAME }}" \ + playbooks/get_raspios.yml + + echo "==> Running mount_raspios playbook..." + ${ANSIBLE} --extra-vars "image_name=${{ env.IMAGE_NAME }}" \ + playbooks/mount_raspios.yml + + echo "==> Running create_pi_top_os_image playbook..." + ${ANSIBLE} playbooks/create_pi_top_os_image.yml + + echo "==> Running mount_pi_top_os playbook..." + ${ANSIBLE} playbooks/mount_pi_top_os.yml + + echo "==> Running install_pi_top_os playbook..." + ${ANSIBLE} --extra-vars "repo_name=${{ inputs.repo_name }}" \ + --extra-vars "distro_name=${{ inputs.distro_name }}" \ + --extra-vars "top_level_pkg=pt-os${{ matrix.build_type_suffix }}" \ + --extra-vars "{'full_install': ${{ matrix.build_type_suffix == '' }}}" \ + playbooks/install_pi_top_os.yml + + echo "==> Running configure_pi_top_os playbook..." + ${ANSIBLE} --extra-vars "distro_name=${{ inputs.distro_name }}" \ + --extra-vars "build_number=${{ github.run_number || github.run_id }}" \ + --extra-vars "build_repo_commit=$(git rev-parse HEAD)" \ + --extra-vars "build_repo_commit_short=$(git rev-parse --short HEAD)" \ + --extra-vars "build_action_url=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ + --extra-vars "build_repo_name=${{ inputs.repo_name }}" \ + --extra-vars "build_type=${{ env.BUILD_TYPE }}" \ + playbooks/configure_pi_top_os.yml + + echo "==> Running finalise_pi_top_image playbook..." + ${ANSIBLE} --extra-vars "distro_name=${{ inputs.distro_name }}" \ + --extra-vars "build_number=${{ github.run_number || github.run_id }}" \ + --extra-vars "build_repo_name=${{ inputs.repo_name }}" \ + --extra-vars "build_type=${{ env.BUILD_TYPE }}" \ + playbooks/finalise_pi_top_image.yml + + echo "==> Running analyse_build playbook..." + ${ANSIBLE} --extra-vars "build_number=${{ github.run_number || github.run_id }}" \ + playbooks/analyse_build.yml + + - name: Get current date + id: date + run: echo "DATE_STAMP=$(date +'%Y-%m-%d')" >> $GITHUB_ENV + + - name: Upload OS zip contents + uses: actions/upload-artifact@v2 + with: + name: pi-topOS_${{ inputs.distro_name }}_${{ inputs.repo_name }}_${{ env.BUILD_TYPE }}_${{ env.DATE_STAMP }}_B${{ github.run_number || github.run_id }} + if-no-files-found: error + path: | + playbooks/artifacts/* + !**/*.zip + + - name: Print metadata + run: cat playbooks/artifacts/metadata.txt + + - name: Upload OS zip to GCS + uses: google-github-actions/upload-cloud-storage@v0.4.0 + with: + credentials: ${{ secrets.GOOGLE_CLOUD_UPLOAD_JSON_CREDENTIALS }} + path: 'playbooks/artifacts' + glob: '**/*.zip' + destination: ${{ secrets.GOOGLE_CLOUD_OS_UPLOAD_BUCKET }}/pi-topOS-${{ inputs.distro_name }}/ diff --git a/playbooks/configure_pi_top_os.yml b/playbooks/configure_pi_top_os.yml index 1c4df66..205c64f 100644 --- a/playbooks/configure_pi_top_os.yml +++ b/playbooks/configure_pi_top_os.yml @@ -18,8 +18,20 @@ # echo 'pi-top' | openssl passwd -5 -stdin -salt 'SomeSalt' password : $5$SomeSalt$5KBi.t.mQ9q82FXRw8DBz5NQLVEmck9OdqHSgu3Q5gA + build_type: armhf + tasks: + - name: Determine if full build + when: '"-" not in build_type' + set_fact: + full_install: true + + - name: Determine if full build + when: '"-" in build_type' + set_fact: + full_install: false + ############## # Build Info # ############## @@ -84,25 +96,41 @@ ################## # System Patches # ################## - - name: Apply patches + - name: Apply system patches patch: - # TODO: Add -vvv src: "patches/{{ item }}.diff" basedir: / strip: 1 loop: - add-post-boot-blinking-cursor - volume-max - - dpms-timeout-5mins - - disable-openbox-session-right-click-menu - empty-etc-issue - empty-etc-motd - hostname - hosts - - source-etc-profile-in-etc-zsh-zprofile - static-ip-on-usb-interface - us-keyboard - us-locale + + - name: Apply full-install patches (desktop, additional packages, etc.) + when: full_install + patch: + src: "patches/{{ item }}.diff" + basedir: / + strip: 1 + loop: + - source-etc-profile-in-etc-zsh-zprofile + - dpms-timeout-5mins + - disable-openbox-session-right-click-menu + + # TODO: confirm that this is supposed to be skipped + - name: Apply full-install 32-bit only patches + when: build_type == "armhf" + patch: + src: "patches/{{ item }}.diff" + basedir: / + strip: 1 + loop: - openbox-xdg-autostart-shebang - name: Create larger static swapfile (to speed up first boot) @@ -114,23 +142,28 @@ # Onboarding setup: systemd/dbus services # ########################################### - name: Disable notifications until onboarding is completed + when: full_install shell: | mkdir -p /usr/lib/pt-os-web-portal/bak/usr/share/dbus-1/services/ mv /usr/share/dbus-1/services/org.xfce.xfce4-notifyd.Notifications.service /usr/lib/pt-os-web-portal/bak/usr/share/dbus-1/services/ - name: Enable Onboarding (using symlink) + when: full_install shell: ln -sf /usr/lib/python3/dist-packages/pt_os_web_portal/resources/pt-os-setup.desktop /etc/xdg/autostart/pt-os-setup.desktop # Boot to openbox-session by setting priority 99 (higher than LXDE default) - name: Set openbox-session as session manager + when: full_install shell: update-alternatives --install /usr/bin/x-session-manager x-session-manager /usr/bin/openbox-session 99 - name: Disable Further Link for onboarding (using symlink) + when: full_install file: dest: /etc/systemd/system/multi-user.target.wants/further-link.service state: absent - name: Disable OLED menu until onboarding finishes (using symlink) + when: full_install file: dest: /etc/systemd/system/multi-user.target.wants/pt-miniscreen.service state: absent @@ -142,6 +175,7 @@ shell: hostname - name: Enable Wi-Fi AP-STA mode (Wi-Fi Access Point) + when: full_install shell: wifi-ap-sta enable - name: Set up virtual Ethernet driver for pi-top [4] display port @@ -209,10 +243,12 @@ state: absent - name: Set plymouth theme to 'pt-os-bootsplash' + when: full_install shell: plymouth-set-default-theme -R pt-os-bootsplash # openbox configuration is modified to prevent key-presses in openbox-session during onboarding - name: Configure openbox environment + when: full_install shell: | mkdir -p /home/pi/.config/openbox cp /etc/xdg/openbox/rc.xml /home/pi/.config/openbox/rc.xml @@ -220,6 +256,7 @@ sed -i ':a;N;$!ba; s@.*<\/keyboard>@'"${keyboard_binding}"'<\/keyboard>@g' /home/pi/.config/openbox/rc.xml - name: Enable VNC Server (using symlink) + when: full_install file: dest: /etc/systemd/system/multi-user.target.wants/vncserver-x11-serviced.service src: /usr/lib/systemd/system/vncserver-x11-serviced.service diff --git a/playbooks/finalise_pi_top_image.yml b/playbooks/finalise_pi_top_image.yml index b4c95b0..1e3a567 100644 --- a/playbooks/finalise_pi_top_image.yml +++ b/playbooks/finalise_pi_top_image.yml @@ -12,16 +12,23 @@ build_repo_name: unstable build_number: 0 distro_name: bullseye - architecture: armhf + build_type: armhf + zip_image: true tasks: - - name: Remove qemu-arm-static from OS as we have finished chrooting + - name: Clean up QEMU chrooting artifacts file: - dest: "/tmp/pi-top-os/usr/bin/qemu-arm-static" + dest: "/tmp/pi-top-os/usr/bin/qemu-*-static" state: absent + - name: Check if preload file needs restoring + stat: + path: /tmp/pi-top-os/etc/ld.so.preload.bak + register: stat_result + - name: Move preload file back as we are done here + when: stat_result.stat.exists shell: "mv /tmp/pi-top-os/etc/ld.so.preload.bak /tmp/pi-top-os/etc/ld.so.preload" args: creates: "/tmp/pi-top-os/etc/ld.so.preload" @@ -108,7 +115,7 @@ shell: "truncate --size={{ final_image_size }} new-image.img" - set_fact: - output_filename: "pi-topOS_{{ distro_name }}_{{ build_repo_name }}_{{ architecture }}_{{ ansible_date_time.date }}_B{{ build_number }}" + output_filename: "pi-topOS_{{ distro_name }}_{{ build_repo_name }}_{{ build_type }}_{{ ansible_date_time.date }}_B{{ build_number }}" - name: Create a hard link to the image to use as the output filename file: @@ -117,6 +124,7 @@ state: hard - name: Compress image into zip + when: zip_image archive: path: - "{{ output_directory }}/{{ output_filename }}.img" @@ -128,7 +136,7 @@ - name: Verify zip fail: msg: Files were missing from the output zip - when: zip_result.missing | length > 0 + when: zip_image and zip_result.missing | length > 0 - name: Remove the hard link to avoid any confusion file: diff --git a/playbooks/install_pi_top_os.yml b/playbooks/install_pi_top_os.yml index 9689729..be41d35 100644 --- a/playbooks/install_pi_top_os.yml +++ b/playbooks/install_pi_top_os.yml @@ -8,6 +8,10 @@ vars: repo_name: pi-top-os + top_level_pkg: pt-os + architecture: armhf + full_install: true + recovery_mount_to: /boot/.recovery tasks: @@ -30,12 +34,13 @@ retries: 5 until: apt_status is success - - name: Install pt-os + - name: Install top-level package apt: - name: pt-os + name: "{{ top_level_pkg }}" update_cache: true state: latest - install_recommends: true + install_recommends: "{{ full_install }}" + default_release: "{{ distro_name }}" register: apt_status retries: 5 until: apt_status is success diff --git a/playbooks/mount_raspios.yml b/playbooks/mount_raspios.yml index ca108ae..dfd085b 100644 --- a/playbooks/mount_raspios.yml +++ b/playbooks/mount_raspios.yml @@ -99,12 +99,20 @@ opts: defaults state: mounted - # Enable chroot to ARM: https://wiki.debian.org/QemuUserEmulation - - name: Copy qemu-arm-static to Raspberry Pi OS to enable chrooting + - set_fact: + qemu_file: "qemu-arm-static" + when: '"armhf" in image_name' + + - set_fact: + qemu_file: "qemu-aarch64-static" + when: '"arm64" in image_name' + + # https://wiki.debian.org/QemuUserEmulation + - name: Enable chrooting via qemu-user-static become: true copy: - src: /usr/bin/qemu-arm-static - dest: "{{ raspi_os_mount_point }}/usr/bin/qemu-arm-static" + src: "/usr/bin/{{ qemu_file }}" + dest: "{{ raspi_os_mount_point }}/usr/bin/{{ qemu_file }}" mode: '0755' remote_src: true @@ -115,6 +123,7 @@ # https://patchwork.kernel.org/patch/10807531/ # https://www.raspberrypi.org/forums/viewtopic.php?t=235594 - name: Move preload file to avoid noisy build + when: '"armhf" in image_name' become: true shell: "mv {{ raspi_os_mount_point }}/etc/ld.so.preload {{ raspi_os_mount_point }}/etc/ld.so.preload.bak" args: