name: "BlueBuild" description: "Build a custom OS image" inputs: recipe: description: | The [recipe](https://blue-build.org/reference/recipe/) file to build the image from, relative to the `config/` or `recipes/` directory. required: true default: "recipe.yml" cosign_private_key: description: | The Sigstore/cosign secret used to sign the image. Example: `${{ secrets.SIGNING_SECRET }}` required: true registry_token: description: | The token used to sign into the container registry. Example: `${{ github.token }}` required: false default: "" registry_username: description: | The username used to sign into the container registry. required: false default: ${{ github.repository_owner }} pr_event_number: description: | The event number used to tag images pushed from pull requests. Example: `${{ github.event.number }}` required: true maximize_build_space: description: | Whether to run the unwanted software remover to maximize build space in the GitHub builder. Disable this with 'false' if your image doesn't take up a lot of space and you'd rather have shorter build times. required: false default: "true" use_unstable_cli: description: | If true, this action pulls the `main` branch of blue-build/cli instead of the stable version the current action version is configured to use by default. This feature is useful for testing new features, but should not be used in production. Input must match the string 'true' for the unstable version to be used. required: false default: "false" cli_version: description: | Set this with a tag, sha, or branch name for the blue-build/cli repo to use that particular version of the CLI tool. This will override the `use_unstable_cli` input for the action. required: false registry: description: | The container registry to push the built image to. required: false default: "ghcr.io" registry_namespace: description: | The namespace on the registry to push to. Example: `ublue-os` required: false default: ${{ github.repository_owner }} rechunk: description: | Rechunk the ostree-based result images with [github.com/hhd-dev/rechunk](https://github.com/hhd-dev/rechunk) for more efficient diffs and updates. (lower image size, better download speed, better update resuming) Will make your builds considerably slower. This is an experimental option, as it can cause issues with file permissions in some scenarios, so enable on your own risk. Internally builds squashed images with podman to further reduce the image size. required: false default: "false" use_cache: description: | Make use of layer cache by pushing the layers to the registry. Input must match the string 'true' for the step to be enabled. required: false default: "true" squash: description: | Uses buildah to squash the build's layers into a single layer. Use of this option disables cache. Conflicts with adding `--build-driver` or `--squash` to the build opts. required: false default: "false" build_opts: description: | Provide options to the call to the BlueBuild CLI build command. If you use this with the squash input set to true and provide either of the `--build-driver` or `--squash` flags an error will occur and the action will not run. required: false default: " " working_directory: description: | Changes working directory for whole build. For example, setting this to `./abc/` would cause for the recipe to be read from `./abc/recipes/recipe.yml`. required: false default: ./ skip_checkout: description: | Set to true to skip doing the actions/checkout step. This allows you to checkout manually before calling bluebuild/github-action and to modify files (such as supplying build information to other scripts) before building. required: false default: "false" runs: using: "composite" steps: - name: Validate inputs shell: bash run: "${{ github.action_path }}/build_opts_check.sh" env: SQUASH_INPUT_VALUE: "${{ inputs.squash }}" BUILD_OPTS: "${{ inputs.build_opts }}" # building custom images might take a lot of space, # so it's best to remove unneeded softawre - name: Maximize build space uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 if: ${{ inputs.maximize_build_space == 'true' }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@18ce135bb5112fa8ce4ed6c17ab05699d7f3a5e0 # v3.11.0 if: ${{ inputs.squash != 'true' && inputs.rechunk != 'true' }} with: install: true driver: docker-container cache-binary: ${{ inputs.use_cache }} - name: Get Ubuntu version id: ubuntu_version shell: bash run: | VERSION=$(awk -F= '/^VERSION_ID=/ {gsub(/"/, "", $2); print $2}' /etc/os-release) echo "Ubuntu version is $VERSION" echo "version=$VERSION" >> $GITHUB_OUTPUT # that is compatible with BlueBuild - name: Setup Podman if: ${{ (inputs.squash == 'true' || inputs.rechunk == 'true') && steps.ubuntu_version.outputs.version == '22.04' }} shell: bash run: | # from https://askubuntu.com/questions/1414446/whats-the-recommended-way-of-installing-podman-4-in-ubuntu-22-04 ubuntu_version='22.04' key_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" sources_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}" echo "deb $sources_url/ /" | sudo tee /etc/apt/sources.list.d/devel-kubic-libcontainers-unstable.list curl -fsSL $key_url | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_kubic_libcontainers_unstable.gpg > /dev/null sudo apt-get update sudo apt-get install -y podman - uses: sigstore/cosign-installer@sigstore/cosign-installer # v3.9.0 with: install-dir: /usr/bin use-sudo: true # clones user's repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 if: ${{ inputs.skip_checkout == 'false' }} - name: Determine Vars id: build_vars shell: bash env: RECIPE: ${{ inputs.recipe }} run: | if [[ "${{ inputs.use_unstable_cli }}" == "true" && -z "${{ inputs.cli_version }}" ]]; then CLI_VERSION_TAG="main" elif [ -n "${{ inputs.cli_version }}" ]; then CLI_VERSION_TAG="${{ inputs.cli_version }}" else CLI_VERSION_TAG="v0.9" fi echo "cli_version=${CLI_VERSION_TAG}" >> ${GITHUB_OUTPUT} RECIPE_PATH="" if [ -f "./config/${RECIPE}" ]; then RECIPE_PATH="./config/${RECIPE}" else RECIPE_PATH="./recipes/${RECIPE}" fi echo "recipe_path=${RECIPE_PATH}" >> ${GITHUB_OUTPUT} - name: Install BlueBuild shell: bash env: CLI_VERSION_TAG: ${{ steps.build_vars.outputs.cli_version }} run: | sudo docker create \ --name blue-build-installer \ ghcr.io/blue-build/cli:${{ env.CLI_VERSION_TAG }}-installer sudo docker cp blue-build-installer:/out/bluebuild /usr/bin/bluebuild sudo docker rm blue-build-installer bluebuild --version # blue-build/cli does the heavy lifting - name: Build Image shell: bash working-directory: ${{ inputs.working_directory }} env: COSIGN_PRIVATE_KEY: ${{ inputs.cosign_private_key }} GH_TOKEN: ${{ inputs.registry_token }} BB_PASSWORD: ${{ inputs.registry_token }} BB_USERNAME: ${{ inputs.registry_username }} BB_REGISTRY: ${{ inputs.registry }} BB_REGISTRY_NAMESPACE: ${{ inputs.registry_namespace }} GH_PR_EVENT_NUMBER: ${{ inputs.pr_event_number }} BB_CACHE_LAYERS: ${{ inputs.use_cache }} RECIPE_PATH: ${{ steps.build_vars.outputs.recipe_path }} RUST_LOG_STYLE: always CLICOLOR_FORCE: "1" BUILD_OPTS: ${{ inputs.build_opts }} run: | if [ "${{ inputs.squash }}" = "true" ]; then BUILD_OPTS="--build-driver podman --squash $BUILD_OPTS" fi RUN_SUDO="" if [ "${{ inputs.rechunk }}" = "true" ]; then RUN_SUDO=1 BUILD_OPTS="--rechunk $BUILD_OPTS" fi if [ -n "$RUN_SUDO" ]; then sudo -E bluebuild build -v --push ${BUILD_OPTS} ${RECIPE_PATH} else bluebuild build -v --push ${BUILD_OPTS} ${RECIPE_PATH} fi