Skip to content

Commit

Permalink
try without maximize build space
Browse files Browse the repository at this point in the history
  • Loading branch information
neoaggelos committed Apr 4, 2024
1 parent 153458a commit 09d48c5
Show file tree
Hide file tree
Showing 2 changed files with 299 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ on:
jobs:
build-and-push-arch-specifics:
name: Build Rocks and Push Arch Specific Images
uses: canonical/k8s-workflows/.github/workflows/build_rocks.yaml@main
uses: ./dev/workflow.yaml
with:
owner: ${{ github.repository_owner }}
trivy-image-config: "trivy.yaml"
multiarch-awareness: true
cache-action: ${{ (github.event_name == 'push') && 'save' || 'restore' }}
platform-labels: '{"arm64": "Ubuntu_ARM64_4C_16G_01"}'
maximize-build-space: false
scan-images:
uses: canonical/k8s-workflows/.github/workflows/scan_images.yaml@main
needs: [build-and-push-arch-specifics]
Expand Down
297 changes: 297 additions & 0 deletions dev/workflow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
# Copyright 2024 Canonical Ltd.
# See LICENSE file for licensing details.

name: Build images

on:
workflow_call:
inputs:
owner:
type: string
description: Registry owner to push the built images
default: ${{ github.repository_owner }}
registry:
type: string
description: Registry to push the built images
default: "ghcr.io"
runs-on:
type: string
description: Image runner for building the images
default: ubuntu-22.04
trivy-image-config:
type: string
description: Trivy YAML configuration for image testing that is checked in as part of the repo
working-directory:
type: string
description: The working directory for jobs
default: "./"
cache-action:
type: string
description: The cache action can either be "save" or "restore".
default: restore
multiarch-awareness:
type: boolean
description: Maintain the architecture labels on the container names
default: false
maximize-build-space:
type: boolean
default: true
platform-labels:
type: string
description: |-
JSON mapping of rockcraft arches to gh runner labels
The key should be one of the platforms in rockcraft.yaml (amd64, arm64...)
the values should be a list of labels to use in the runs-on field of a gh action
default: '{}'
outputs:
images:
description: List of images built
value: ${{ jobs.get-rocks.outputs.images }}
rock-metas:
description: List of maps featuring the built {name, version, path, arch, image}
value: ${{ jobs.get-rocks.outputs.rock-metas }}

jobs:
get-rocks:
name: Get rocks
runs-on: ${{ inputs.runs-on }}
outputs:
rock-paths: ${{ steps.gen-rock-paths-and-images.outputs.rock-paths }}
images: "${{ steps.gen-rock-paths-and-images.outputs.images }}"
rock-metas: ${{ steps.gen-rock-paths-and-images.outputs.rock-metas }}
steps:
- name: Validate inputs
run: |
if [ "${{ inputs.cache-action }}" != "save" ] && [ "${{ inputs.cache-action }}" != "restore" ]; then
echo "Invalid value for cache-action. It must be 'save' or 'restore'"
exit 1
fi
- uses: actions/[email protected]
- name: Generate rock paths and images
id: gen-rock-paths-and-images
uses: actions/[email protected]
with:
script: |
const path = require('path')
const inputs = ${{ toJSON(inputs) }}
const workingDir = inputs['working-directory']
const multiarch = inputs['multiarch-awareness']
const rockcraftGlobber = await glob.create(
path.join(workingDir, '**/rockcraft.yaml')
)
const rockPaths = []
const images = []
const rockMetas = []
const defaultArch = 'amd64'
const platformLabels = JSON.parse(inputs['platform-labels'])
core.info(`Multiarch Awareness is ${multiarch ? "on" : "off" }`)
for (const rockcraftFile of await rockcraftGlobber.glob()) {
const rockPath = path.relative('.', path.dirname(rockcraftFile)) || "./"
core.info(`found rockcraft.yaml in ${rockPath}`)
const fileHash = await glob.hashFiles(path.join(rockPath, '**'))
const [rockName, rockVersion] = (
await exec.getExecOutput('yq', ['.name,.version', rockcraftFile])
).stdout.trim().split("\n")
const platforms = (
await exec.getExecOutput('yq', ['.platforms | keys', '-o=json', rockcraftFile])
).stdout.trim()
if (multiarch && platforms) {
const arches = JSON.parse(platforms)
for (arch of arches) {
const image = `${{ inputs.registry }}/${{ inputs.owner }}/${rockName}:${fileHash}-${arch}`
core.info(`generate multi-arch image name: ${image}`)
images.push(image)
rockMetas.push({
name: rockName,
version: rockVersion,
path: rockPath,
arch: arch,
image: image,
"runs-on-labels": platformLabels[arch] || [inputs["runs-on"]]
})
}
} else {
const image = `${{ inputs.registry }}/${{ inputs.owner }}/${rockName}:${fileHash}`
core.info(`generate image name: ${image}`)
images.push(image)
rockMetas.push({
name: rockName,
version: rockVersion,
path: rockPath,
arch: defaultArch,
image: image,
"runs-on-labels": platformLabels[defaultArch] || [inputs["runs-on"]]
})
}
rockPaths.push(rockPath)
}
core.setOutput('rock-metas', JSON.stringify(rockMetas))
core.setOutput('rock-paths', JSON.stringify(rockPaths))
core.setOutput('images', JSON.stringify(images))
build-rocks:
name: Build rock
needs: [get-rocks]
if: ${{ needs.get-rocks.outputs.rock-metas != '[]' }}
strategy:
matrix:
rock: ${{ fromJSON(needs.get-rocks.outputs.rock-metas) }}
runs-on: ${{ matrix.rock.runs-on-labels }}
permissions:
contents: read
packages: write
steps:
- name: Ensure LXD storage pools path
run: |
sudo mkdir -p /var/snap/lxd/common/lxd/storage-pools
- name: Maximize build space
uses: easimon/maximize-build-space@v10
with:
root-reserve-mb: 2048
temp-reserve-mb: 2048
overprovision-lvm: 'true'
remove-dotnet: 'true'
remove-android: 'true'
remove-haskell: 'true'
build-mount-path: "/var/snap/lxd/common/lxd/storage-pools"
build-mount-path-ownership: "root:root"
if: inputs.maximize-build-space
- uses: actions/[email protected]
with:
fetch-depth: 0
- name: Ensure tools on Runner
run: |
if ! which yq; then sudo snap install yq; fi
echo "path to yq=$(which yq)"
- name: Extract rock information
run: |
IMAGE_ARCH="${{ matrix.rock.arch }}"
IMAGE_NAME="${{ matrix.rock.name }}"
IMAGE_BASE=$(yq '.base' "${{ matrix.rock.path }}/rockcraft.yaml")
IMAGE_BUILD_BASE=$(yq '.["build-base"] // .base' "${{ matrix.rock.path }}/rockcraft.yaml")
IMAGE_REF=${{ matrix.rock.image }}
INODE_NUM=$(ls -id ${{ matrix.rock.path }} | cut -f 1 -d " ")
ROCKCRAFT_CONTAINER_NAME=rockcraft-$IMAGE_NAME-on-$IMAGE_ARCH-for-$IMAGE_ARCH-$INODE_NUM
echo "IMAGE_NAME=$IMAGE_NAME" >> $GITHUB_ENV
echo "IMAGE_BASE=$IMAGE_BASE" >> $GITHUB_ENV
echo "IMAGE_BUILD_BASE=$IMAGE_BUILD_BASE" >> $GITHUB_ENV
echo "IMAGE_REF=$IMAGE_REF" >> $GITHUB_ENV
echo "IMAGE_ARCH=$IMAGE_ARCH" >> $GITHUB_ENV
echo "ROCKCRAFT_CONTAINER_NAME=$ROCKCRAFT_CONTAINER_NAME" >> $GITHUB_ENV
- name: Generate rockcraft cache key
run: |
ROCKCRAFT_PATH="${{ matrix.rock.path }}"
ROCKCRAFT_PATH="${ROCKCRAFT_PATH%/}"
ROCKCRAFT_CACHE_KEY_BASE="$ROCKCRAFT_PATH/rockcraft-cache?name=${{ env.IMAGE_NAME }}&base=${{ env.IMAGE_BUILD_BASE }}&build-base=${{ env.IMAGE_BUILD_BASE }}"
ROCK_CACHE_KEY_BASE="$ROCKCRAFT_PATH/${{ env.IMAGE_NAME }}.rock?filehash=${{ hashFiles(format('{0}/{1}', matrix.rock.path, '**')) }}"
if [ "${{ inputs.multiarch-awareness }}" == "true" ]; then
ROCKCRAFT_CACHE_KEY_BASE="${ROCKCRAFT_CACHE_KEY_BASE}&arch=${{ env.IMAGE_ARCH }}"
ROCK_CACHE_KEY_BASE="${ROCK_CACHE_KEY_BASE}&arch=${{ env.IMAGE_ARCH }}"
fi
echo "ROCKCRAFT_CACHE_KEY=$ROCKCRAFT_CACHE_KEY_BASE&date=$(date +%Y-%m-%d)" >> $GITHUB_ENV
echo 'ROCKCRAFT_CACHE_ALT_KEYS<<EOF' >> $GITHUB_ENV
for d in {1..2}
do echo "$ROCKCRAFT_CACHE_KEY_BASE&date=$(date -d"-$d days" +%Y-%m-%d)" >> $GITHUB_ENV
done
echo 'EOF' >> $GITHUB_ENV
echo "ROCK_CACHE_KEY=$ROCK_CACHE_KEY_BASE=$(date +%Y-%m-%d)" >> $GITHUB_ENV
echo 'ROCK_CACHE_ALT_KEYS<<EOF' >> $GITHUB_ENV
for d in {1..2}
do echo "$ROCK_CACHE_KEY_BASE&date=$(date -d"-$d days" +%Y-%m-%d)" >> $GITHUB_ENV
done
echo 'EOF' >> $GITHUB_ENV
- name: Restore rock cache
if: inputs.cache-action == 'restore'
uses: actions/cache/[email protected]
id: rock-cache
with:
path: ~/.rock-cache
key: ${{ env.ROCK_CACHE_KEY }}
restore-keys: ${{ env.ROCK_CACHE_ALT_KEYS }}
- name: Restore rockcraft container cache
if: steps.rock-cache.outputs.cache-hit != 'true' && inputs.cache-action == 'restore'
uses: actions/cache/[email protected]
id: rockcraft-cache
with:
path: ~/.rockcraft-cache/
key: ${{ env.ROCKCRAFT_CACHE_KEY }}
restore-keys: ${{ env.ROCKCRAFT_CACHE_ALT_KEYS }}
- name: Setup lxd
if: steps.rockcraft-cache.outputs.cache-hit == 'true'
run: |
sudo groupadd --force --system lxd
sudo usermod --append --groups lxd runner
sudo snap refresh lxd --channel latest/stable
sudo lxd init --auto
sudo iptables -P FORWARD ACCEPT
- name: Import rockcraft container cache
if: steps.rockcraft-cache.outputs.cache-hit == 'true'
working-directory: ${{ inputs.working-directory }}
run: |
sudo lxc project create rockcraft -c features.images=false -c features.profiles=false
sudo lxc --project rockcraft import ~/.rockcraft-cache/${{ env.IMAGE_NAME }}.tar ${{ env.ROCKCRAFT_CONTAINER_NAME }}
find . -exec touch '{}' ';'
- name: Build rock
if: steps.rock-cache.outputs.cache-hit != 'true' || inputs.cache-action == 'save'
uses: canonical/craft-actions/rockcraft-pack@main
with:
path: ${{ matrix.rock.path }}
- name: Generate rockcraft container cache
if: inputs.cache-action == 'save'
run: |
mkdir -p ~/.rockcraft-cache
mkdir -p ~/.rock-cache
touch ~/.rock-cache/.gitkeep
sudo lxc --project rockcraft export ${{ env.ROCKCRAFT_CONTAINER_NAME }} --compression none ~/.rockcraft-cache/${{ env.IMAGE_NAME }}.tar
- name: Delete rockcraft container cache
if: inputs.cache-action == 'save'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api \
--method DELETE \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/actions/caches?key=$(printf %s "${{ env.ROCKCRAFT_CACHE_KEY }}"|jq -sRr @uri) || :
for key in $(echo $ROCKCRAFT_CACHE_ALT_KEYS)
do gh api \
--method DELETE \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/actions/caches?key=$(printf %s "$key"|jq -sRr @uri) || :
done
- name: Save rockcraft container cache
if: inputs.cache-action == 'save'
uses: actions/cache/[email protected]
with:
path: ~/.rockcraft-cache/
key: ${{ env.ROCKCRAFT_CACHE_KEY }}
- name: Delete rock cache
if: inputs.cache-action == 'save'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api \
--method DELETE \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/actions/caches?key=$(printf %s "${{ env.ROCK_CACHE_KEY }}"|jq -sRr @uri) || :
for key in $(echo $ROCK_CACHE_ALT_KEYS)
do gh api \
--method DELETE \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/actions/caches?key=$(printf %s "$key"|jq -sRr @uri) || :
done
- name: Save rock cache
if: inputs.cache-action == 'save'
uses: actions/cache/[email protected]
with:
path: ~/.rock-cache
key: ${{ env.ROCK_CACHE_KEY }}
- name: Upload rock to ${{ inputs.registry }}
if: steps.rock-cache.outputs.cache-hit != 'true' || inputs.cache-action == 'save'
run: |
/snap/rockcraft/current/bin/skopeo --insecure-policy copy oci-archive:$(ls "${{ matrix.rock.path }}"/*.rock) docker://$IMAGE_REF --dest-creds "${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}"

0 comments on commit 09d48c5

Please sign in to comment.