Patch and Release OTA #3069
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Patch and Release OTA | |
| on: | |
| schedule: | |
| - cron: "0 */6 * * *" # Check for update every 6 hours (UTC). GrapheneOS checks every 6 hours. | |
| # Allows you to run this workflow manually from the Actions tab | |
| workflow_dispatch: | |
| inputs: | |
| device-id: | |
| description: Device code name | |
| required: true | |
| root: | |
| description: Add root to the build | |
| required: false | |
| type: boolean | |
| default: false | |
| magisk-preinit-device: | |
| description: Magisk preinit device. For example, "sda8", "sda15" etc., | |
| required: false | |
| update-channel: | |
| description: GrapheneOS update channel. Supports `alpha`, `beta` and `stable`. Defaults to `stable` | |
| required: false | |
| release-type: | |
| description: "How to handle the release. `default`: build and publish if new. `build-only`: only build. `force-publish`: build and publish even if it exists." | |
| required: true | |
| type: choice | |
| options: | |
| - default | |
| - build-only | |
| - force-publish | |
| default: default | |
| # Allows this workflow to be called per device, see multi-release.yml | |
| workflow_call: | |
| inputs: | |
| device-id: | |
| required: true | |
| type: string | |
| root: | |
| required: false | |
| type: boolean | |
| default: false | |
| magisk-preinit-device: | |
| required: false | |
| type: string | |
| update-channel: | |
| required: false | |
| type: string | |
| release-type: | |
| required: false | |
| type: string | |
| default: default | |
| env: | |
| CARGO_INCREMENTAL: 1 | |
| DEVICE_NAME: ${{ inputs.device-id }} | |
| INTERACTIVE_MODE: false | |
| GRAPHENEOS_UPDATE_CHANNEL: ${{ inputs.update-channel }} | |
| RUST_BACKTRACE: short | |
| RUSTUP_MAX_RETRIES: 10 | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| # Required by publisher step | |
| permissions: write-all | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| with: | |
| # Allow for switching to github-pages branch | |
| fetch-depth: 0 | |
| - name: Read from `env.toml` if exist | |
| if: ${{ github.event_name == 'schedule' }} | |
| run: | | |
| # Check if the file exists | |
| source src/util_functions.sh && check_toml_env | |
| echo "DEVICE_NAME=${DEVICE_NAME}" >> $GITHUB_ENV | |
| echo "GRAPHENEOS_UPDATE_CHANNEL=${GRAPHENEOS[UPDATE_CHANNEL]}" >> $GITHUB_ENV | |
| echo "FORCE_UPDATE=${FORCE_UPDATE:-false}" >> $GITHUB_ENV | |
| # Let scheduled runs build rooted OTAs when env.toml enables it | |
| echo "ROOT=${ADDITIONALS[ROOT]}" >> $GITHUB_ENV | |
| echo "MAGISK_PREINIT=${MAGISK[PREINIT]}" >> $GITHUB_ENV | |
| - name: Check if `magisk-preinit-device` is set when `root` is true | |
| run: | | |
| # Inputs win on manual runs, env.toml supplies the values on schedule | |
| root="${{ inputs.root || env.ROOT }}" | |
| magisk_preinit_device="${{ inputs.magisk-preinit-device || env.MAGISK_PREINIT }}" | |
| # Ensure that the boolean comparison is correctly handled | |
| if [ "$root" == "true" ] && [ -z "$magisk_preinit_device" ]; then | |
| echo -e "::error:: magisk-preinit-device is required when root is true." | |
| exit 1 | |
| fi | |
| - name: Set GrapheneOS version | |
| shell: bash | |
| run: | | |
| # Device name is a required parameter | |
| if [[ -z "${DEVICE_NAME}" ]]; then | |
| echo -e "::error::Missing required param \`DEVICE_NAME\`" | |
| exit 1 | |
| fi | |
| # Fetch the latest GrapheneOS version and set up the environment | |
| source src/fetcher.sh && get_latest_version | |
| echo "GRAPHENEOS_VERSION=${VERSION[GRAPHENEOS]}" >> $GITHUB_ENV | |
| - name: Check if a build exists already and verify assets | |
| shell: bash | |
| if: github.event_name == 'schedule' || inputs.release-type == 'default' | |
| env: | |
| REPOSITORY: ${{ github.repository }} | |
| ROOT: ${{ inputs.root || env.ROOT }} | |
| run: src/ci/check_existing_build.sh | |
| - name: Setup Git | |
| env: | |
| USER_EMAIL: ${{ secrets.EMAIL }} | |
| USER_NAME: ${{ github.repository_owner }} | |
| run: | | |
| git config --global user.email "$USER_EMAIL" | |
| git config --global user.name "$USER_NAME" | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable 2 weeks ago | |
| - name: Build and Cache Rust Dependencies | |
| uses: Swatinem/rust-cache@v2.9.2 | |
| - name: Install Python | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: "3.12-dev" | |
| - name: Setup Environment variables | |
| run: | | |
| echo "KEYS_AVB_BASE64<<EOF" >> $GITHUB_ENV | |
| echo "${{ secrets.AVB_KEY }}" >> $GITHUB_ENV | |
| echo "EOF" >> $GITHUB_ENV | |
| echo "KEYS_CERT_OTA_BASE64<<EOF" >> $GITHUB_ENV | |
| echo "${{ secrets.CERT_OTA }}" >> $GITHUB_ENV | |
| echo "EOF" >> $GITHUB_ENV | |
| echo "KEYS_OTA_BASE64<<EOF" >> $GITHUB_ENV | |
| echo "${{ secrets.OTA_KEY }}" >> $GITHUB_ENV | |
| echo "EOF" >> $GITHUB_ENV | |
| - name: Patch OTA | |
| shell: bash | |
| env: | |
| ADDITIONALS_ROOT: ${{ inputs.root || env.ROOT }} | |
| CLEANUP: true | |
| MAGISK_PREINIT: ${{ inputs.magisk-preinit-device || env.MAGISK_PREINIT }} | |
| PASSPHRASE_AVB: ${{ secrets.PASSPHRASE_AVB }} | |
| PASSPHRASE_OTA: ${{ secrets.PASSPHRASE_OTA }} | |
| run: | | |
| echo -e "Running release script.." | |
| # Instead of running the script directly, | |
| # we source it to get the variables in the current shell and use them in the next steps by exporting them | |
| . src/main.sh | |
| # Export the variables for the next steps | |
| echo "GRAPHENEOS_OTA_TARGET=${GRAPHENEOS[OTA_TARGET]}" >> $GITHUB_ENV | |
| echo "OUTPUTS_PATCHED_OTA=${OUTPUTS[PATCHED_OTA]}" >> $GITHUB_ENV | |
| echo "WORKDIR=${WORKDIR}" >> $GITHUB_ENV | |
| - name: Generate Changelog | |
| run: | | |
| # Generate a changelog for the release taking the latest GrapheneOS release | |
| echo -e "See [Changelog](https://grapheneos.org/releases#${{ env.GRAPHENEOS_VERSION }})." > ${{ github.workspace }}-CHANGELOG.txt | |
| - name: Make Release | |
| uses: softprops/action-gh-release@v3 | |
| if: inputs.release-type != 'build-only' | |
| with: | |
| body_path: ${{ github.workspace }}-CHANGELOG.txt | |
| files: | | |
| ${{ env.OUTPUTS_PATCHED_OTA }} | |
| ${{ env.OUTPUTS_PATCHED_OTA }}.csig | |
| name: "${{ env.GRAPHENEOS_VERSION }}" | |
| tag_name: "${{ env.GRAPHENEOS_VERSION }}" | |
| - name: Remove superseded release assets | |
| shell: bash | |
| if: env.FORCE_REBUILD == 'true' && inputs.release-type != 'build-only' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPOSITORY: ${{ github.repository }} | |
| ROOT: ${{ inputs.root || env.ROOT }} | |
| run: src/ci/remove_superseded_assets.sh | |
| - name: Publish OTA to server | |
| shell: bash | |
| if: inputs.release-type != 'build-only' | |
| env: | |
| RELEASE_TYPE: ${{ inputs.release-type }} | |
| ROOT: ${{ inputs.root || env.ROOT }} | |
| run: src/ci/publish_ota.sh |