From 848d8e8e07705afb749590134658b7d1497af0d6 Mon Sep 17 00:00:00 2001
From: xyny <60004820+xynydev@users.noreply.github.com>
Date: Tue, 3 Dec 2024 20:34:47 +0200
Subject: [PATCH] feat: rechunk support (#69)

* feat: rechunk support

* fix: sudo bluebuild

* fix: Add more checks for rechunk and change CLI install location

* fix: Pass env variables to sudo

* fix: Install cosign into /usr/bin

* docs: Clarify that `rechunk` is an experimental option

* docs: Note that `--squash` is used with Rechunk

* chore: desc rewording

* chore: reword description

---------

Co-authored-by: Gerald Pinder <gmpinder@gmail.com>
Co-authored-by: fiftydinar <65243233+fiftydinar@users.noreply.github.com>
---
 action.yml | 89 +++++++++++++++++++++++++++++++++---------------------
 1 file changed, 55 insertions(+), 34 deletions(-)

diff --git a/action.yml b/action.yml
index b3f44b8..94aa097 100644
--- a/action.yml
+++ b/action.yml
@@ -1,11 +1,11 @@
-name: 'BlueBuild'
-description: 'Build a custom OS image'
+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'
+    default: "recipe.yml"
   cosign_private_key:
     description: |
       The Sigstore/cosign secret used to sign the image.
@@ -13,14 +13,14 @@ inputs:
       Example: `&#36;{{ secrets.SIGNING_SECRET }}`
     required: true
   registry_token:
-    description: | 
+    description: |
       The token used to sign into the container registry.
 
       Example: `&#36;{{ github.token }}`
     required: false
-    default: ''
+    default: ""
   registry_username:
-    description: | 
+    description: |
       The username used to sign into the container registry.
     required: false
     default: ${{ github.repository_owner }}
@@ -35,14 +35,14 @@ inputs:
       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'
+    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'
+    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.
@@ -51,34 +51,43 @@ inputs:
     description: |
       The container registry to push the built image to.
     required: false
-    default: 'ghcr.io'
+    default: "ghcr.io"
   registry_namespace:
     description: |
-     The namespace on the registry to push to.
-     
-     Example: `ublue-os`
+      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 docker buildx cache. This is an experimental feature of docker buildx
       so it isn't guaranteed to work.
       Input must match the string 'true' for the step to be enabled.
     required: false
-    default: 'true'
+    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.
+      disables cache. Conflicts with adding `--build-driver` or `--squash` to the build opts.
     required: false
-    default: '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
+      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: ' '
+    default: " "
   working_directory:
     description: |
       Changes working directory for whole build.
@@ -86,12 +95,12 @@ inputs:
     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'
+    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"
@@ -102,7 +111,7 @@ runs:
       env:
         SQUASH_INPUT_VALUE: "${{ inputs.squash }}"
         BUILD_OPTS: "${{ inputs.build_opts }}"
-    # building custom images might take a lot of space, 
+    # 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@v1.3.1
@@ -110,7 +119,7 @@ runs:
 
     - name: Set up Docker Buildx
       uses: docker/setup-buildx-action@v3
-      if: ${{ inputs.squash != 'true' }}
+      if: ${{ inputs.squash != 'true' && inputs.rechunk != 'true' }}
       with:
         install: true
         driver: docker-container
@@ -126,7 +135,7 @@ runs:
 
     # that is compatible with BlueBuild
     - name: Setup Podman
-      if: ${{ inputs.squash == 'true' && steps.ubuntu_version.outputs.version == '22.04' }}
+      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
@@ -139,6 +148,9 @@ runs:
         sudo apt-get install -y podman
 
     - uses: sigstore/cosign-installer@v3.7.0
+      with:
+        install-dir: /usr/bin
+        use-sudo: true
 
     # clones user's repo
     - uses: actions/checkout@v4
@@ -155,7 +167,7 @@ runs:
         elif [ -n "${{ inputs.cli_version }}" ]; then
           CLI_VERSION_TAG="${{ inputs.cli_version }}"
         else
-          CLI_VERSION_TAG="v0.8"
+          CLI_VERSION_TAG="v0.9"
         fi
         echo "cli_version=${CLI_VERSION_TAG}" >> ${GITHUB_OUTPUT}
 
@@ -172,20 +184,19 @@ runs:
       env:
         CLI_VERSION_TAG: ${{ steps.build_vars.outputs.cli_version }}
       run: |
-        docker create \
+        sudo docker create \
           --name blue-build-installer \
           ghcr.io/blue-build/cli:${{ env.CLI_VERSION_TAG }}-installer
-        docker cp blue-build-installer:/out/bluebuild /usr/local/bin/bluebuild
-        docker rm blue-build-installer
+        sudo docker cp blue-build-installer:/out/bluebuild /usr/bin/bluebuild
+        sudo docker rm blue-build-installer
         bluebuild --version
 
     # Required in order for docker buildx to
     # take advantage of the GHA cache API
     - name: Expose GitHub Runtime
-      if: ${{ inputs.use_cache == 'true' && inputs.squash != 'true' }}
+      if: ${{ inputs.use_cache == 'true' && inputs.squash != 'true' && inputs.rechunk != 'true' }}
       uses: crazy-max/ghaction-github-runtime@v3
 
-
     # blue-build/cli does the heavy lifting
     - name: Build Image
       shell: bash
@@ -201,11 +212,21 @@ runs:
         BB_BUILDKIT_CACHE_GHA: ${{ inputs.use_cache }}
         RECIPE_PATH: ${{ steps.build_vars.outputs.recipe_path }}
         RUST_LOG_STYLE: always
-        CLICOLOR_FORCE: '1'
+        CLICOLOR_FORCE: "1"
         BUILD_OPTS: ${{ inputs.build_opts }}
       run: |
         if [ "${{ inputs.squash }}" = "true" ]; then
           BUILD_OPTS="--build-driver podman --squash $BUILD_OPTS"
         fi
 
-        bluebuild build -v --push ${BUILD_OPTS} ${RECIPE_PATH}
+        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