From 40b557b18e1ffde9403475475a57ddb7a94efe17 Mon Sep 17 00:00:00 2001 From: Cristovao Cordeiro Date: Fri, 9 Feb 2024 09:22:37 +0100 Subject: [PATCH] feat: add recipe and CI for rockcraft rock This includes the rockcraft.yaml, plus automations, to build, test and upload a Rockcraft rocks everytime there is a new tag in the upstream repo. --- .github/workflows/rockcraft-rock.yml | 95 +++++++++++++ .gitignore | 3 +- renovate.json | 19 ++- rockcraft_rock/rockcraft.yaml | 129 ++++++++++++++++++ .../scripts/rockcraft-entrypoint.sh | 12 ++ 5 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/rockcraft-rock.yml create mode 100644 rockcraft_rock/rockcraft.yaml create mode 100755 rockcraft_rock/scripts/rockcraft-entrypoint.sh diff --git a/.github/workflows/rockcraft-rock.yml b/.github/workflows/rockcraft-rock.yml new file mode 100644 index 0000000..94fd97b --- /dev/null +++ b/.github/workflows/rockcraft-rock.yml @@ -0,0 +1,95 @@ +name: Rockcraft rock + +on: + push: + paths: + - "rockcraft_rock/rockcraft.y*ml" + +jobs: + build: + name: Build Rockcraft rock + runs-on: ubuntu-latest + outputs: + oci-archive: ${{ steps.rockcraft.outputs.rock }} + image-tag: ${{ steps.get-version.outputs.tag }} + steps: + - uses: actions/checkout@v4 + - id: get-version + run: | + tag="$(cat rockcraft_rock/rockcraft.yaml \ + | grep "source-tag: " \ + | grep -v " v"\ + | awk -F' ' '{print $NF}')" + + echo "tag=$tag" >> $GITHUB_OUTPUT + - name: Build rock + id: rockcraft + uses: canonical/craft-actions/rockcraft-pack@main + with: + path: rockcraft_rock + verbosity: debug + - uses: actions/cache/save@v3 + with: + path: ${{ steps.rockcraft.outputs.rock }} + key: ${{ github.run_id }} + + test: + name: Test Rockcraft rock + runs-on: ubuntu-latest + needs: [build] + env: + TEST_DOCKER_IMAGE: "test:latest" + steps: + - uses: actions/cache/restore@v3 + with: + path: ${{ needs.build.outputs.oci-archive }} + key: ${{ github.run_id }} + fail-on-cache-miss: true + - name: Install Skopeo + run: | + # skopeo comes inside rockcraft + sudo snap install rockcraft + - run: | + /snap/rockcraft/current/bin/skopeo copy \ + oci-archive:${{ needs.build.outputs.oci-archive }} \ + docker-daemon:${{ env.TEST_DOCKER_IMAGE }} + - name: Functional test + run: | + docker run --rm ${{ env.TEST_DOCKER_IMAGE }} \ + exec /usr/libexec/rockcraft/rockcraft help + + upload: + name: Upload Rockcraft rock + runs-on: ubuntu-latest + needs: [build, test] + if: ${{ github.event_name != 'pull_request' }} + steps: + - uses: actions/cache/restore@v3 + with: + path: ${{ needs.build.outputs.oci-archive }} + key: ${{ github.run_id }} + fail-on-cache-miss: true + - name: Upload rock + uses: actions/upload-artifact@v3 + with: + name: rock + path: ${{ needs.build.outputs.oci-archive }} + - name: Login to GHCR + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Install Skopeo + run: | + # skopeo comes inside rockcraft + sudo snap install rockcraft + - name: Publish rock to GHCR + run: | + /snap/rockcraft/current/bin/skopeo copy \ + oci-archive:${{ needs.build.outputs.oci-archive }} \ + docker://ghcr.io/${{ github.repository }}/rockcraft-rock:latest + + /snap/rockcraft/current/bin/skopeo copy \ + oci-archive:${{ needs.build.outputs.oci-archive }} \ + docker://ghcr.io/${{ github.repository }}/rockcraft-rock:${{ needs.build.outputs.image-tag}} diff --git a/.gitignore b/.gitignore index 600d2d3..4e2993f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.vscode \ No newline at end of file +.vscode +*.rock \ No newline at end of file diff --git a/renovate.json b/renovate.json index 39a2b6e..3f62022 100644 --- a/renovate.json +++ b/renovate.json @@ -2,5 +2,22 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:base" + ], + "prHourlyLimit": 0, + "ignorePaths": [ + ".github/*" + ], + "customManagers": [ + { + "customType": "regex", + "fileMatch": [ + "^rockcraft_rock/rockcraft.yaml$" + ], + "matchStrings": [ + "source-tag: (?.*?)\\s" + ], + "datasourceTemplate": "github-releases", + "depNameTemplate": "canonical/chisel" + } ] -} +} \ No newline at end of file diff --git a/rockcraft_rock/rockcraft.yaml b/rockcraft_rock/rockcraft.yaml new file mode 100644 index 0000000..f672fb8 --- /dev/null +++ b/rockcraft_rock/rockcraft.yaml @@ -0,0 +1,129 @@ +# Run the container: +# docker run --rm -v $PWD:/project \ +# --device /dev/fuse \ +# --cap-add SYS_ADMIN \ +# --security-opt apparmor:unconfined \ +# +name: rockcraft + +# Other bases are automatically built by the CI +base: ubuntu@22.04 + +# Until adopt-info is supported, we'll just build dev images based on whatever +# is committed to the main branch +version: "dev" +summary: A Rockcraft rock +description: | + This is a rock that offers Rockcraft's capabilities from inside a container. + The default behavior is to pack a rock in destructive mode. +license: GPL-3.0 +platforms: + amd64: + +services: + rockcraft: + override: replace + startup: enabled + command: /usr/libexec/rockcraft/rockcraft-entrypoint.sh [ -v ] + working-dir: /workdir + on-success: shutdown + on-failure: shutdown + +parts: + rockcraft: + plugin: python + source: https://github.com/canonical/rockcraft.git + source-tag: 1.2.0 + python-packages: + - wheel + - pip + - setuptools + python-requirements: + - requirements-jammy.txt + - requirements.txt + build-environment: + - "CFLAGS": "$(pkg-config python-3.10 yaml-0.1 --cflags)" + build-attributes: + - enable-patchelf + build-packages: + - libapt-pkg-dev + - aspell + - aspell-en + stage-packages: + - binutils + - snapd + - python3-venv + - fuse-overlayfs + - rsync + - g++ + organize: + bin/craftctl: usr/libexec/rockcraft/craftctl + bin/rockcraft: usr/libexec/rockcraft/rockcraft + + # The custom script makes sure the build happens in a different path from + # the host's bind mount, to avoid polluting that space. + startup-script: + plugin: dump + source: scripts + organize: + rockcraft-entrypoint.sh: usr/libexec/rockcraft/rockcraft-entrypoint.sh + prime: + - usr/libexec/rockcraft/rockcraft-entrypoint.sh + + workdirs: + plugin: nil + override-build: | + # This is where Rockcraft projects on the host should be mounted + mkdir -p ${CRAFT_PART_INSTALL}/project + # This is where Rockcraft actually builds the rocks, to avoid polluting + # the host + mkdir -p ${CRAFT_PART_INSTALL}/workdir + + umoci: + plugin: make + source: https://github.com/opencontainers/umoci.git + source-tag: v0.4.7 + make-parameters: + - umoci.static + override-build: | + make umoci.static + mkdir "$CRAFT_PART_INSTALL"/bin + install -m755 umoci.static "$CRAFT_PART_INSTALL"/bin/umoci + build-packages: + - golang-go + - make + + skopeo: + plugin: nil + source: https://github.com/containers/skopeo.git + source-tag: v1.9.0 + override-build: | + CGO=1 go build -ldflags -linkmode=external ./cmd/skopeo + mkdir -p "$CRAFT_PART_INSTALL"/bin + install -m755 skopeo "$CRAFT_PART_INSTALL"/bin/skopeo + stage-packages: + - libgpgme11 + - libassuan0 + - libbtrfs0 + - libdevmapper1.02.1 + build-attributes: + - enable-patchelf + build-snaps: + - go/1.17/stable + build-packages: + - libgpgme-dev + - libassuan-dev + - libbtrfs-dev + - libdevmapper-dev + - pkg-config + overlay-packages: + - ca-certificates + + chisel: + plugin: nil + stage-snaps: + - chisel/latest/candidate + organize: + bin/chisel: usr/libexec/rockcraft/chisel + stage: + - usr/libexec/rockcraft/chisel diff --git a/rockcraft_rock/scripts/rockcraft-entrypoint.sh b/rockcraft_rock/scripts/rockcraft-entrypoint.sh new file mode 100755 index 0000000..82dc94d --- /dev/null +++ b/rockcraft_rock/scripts/rockcraft-entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/bash -ex + +apt update &>/dev/null + +export PATH="$PATH:/usr/libexec/rockcraft" + +rsync -a --exclude="*.rock" /project/ /workdir + +/usr/libexec/rockcraft/rockcraft pack --destructive-mode "$@" + +(ls /workdir/*.rock &>/dev/null && cp /workdir/*.rock /project/) || \ + echo "No rocks were built. Exiting..."