config/justfile
Timothée Ravier 8301eaad96
All checks were successful
Validate manifests / validate (pull_request) Successful in 27s
Daily comps-sync check / validate (pull_request) Successful in 27s
Compose tests / testing-farm (pull_request_target) Successful in 27m7s
justfile: Drop volume_id_substitutions (was used by lorax)
We removed the recipe using lorax for building our installer images so
we can remove this one too.
2026-06-10 15:30:56 +02:00

481 lines
14 KiB
Makefile

# SPDX-FileCopyrightText: Fedora Atomic Desktops maintainers
# SPDX-License-Identifier: MIT
# This is a justfile. See https://github.com/casey/just
# This is only used for local development. The builds made on the Fedora
# infrastructure are run via Pungi in a Koji runroot.
# Just doesn't have a native dict type, but quoted bash dictionary works fine
pretty_names := '(
[silverblue]="Silverblue"
[kinoite]="Kinoite"
[kinoite-nightly]="Kinoite"
[kinoite-beta]="Kinoite"
[kinoite-mobile]="Kinoite"
[sway-atomic]="Sway Atomic"
[budgie-atomic]="Budgie Atomic"
[xfce-atomic]="XFCE Atomic"
[lxqt-atomic]="LXQt Atomic"
[base-atomic]="Base Atomic"
[cosmic-atomic]="COSMIC Atomic"
)'
# Define a 'release_ver' shortcut for use in recipes
release_ver := '''
"$(rpm-ostree compose tree --print-only "silverblue.yaml" | jq -r '."mutate-os-release"')"
'''
# Define a 'is_rawhide' shortcut for use in recipes
is_rawhide := '''
"$(rpm-ostree compose tree --print-only "silverblue.yaml" | jq -r '.repos[]')" == "fedora-rawhide"
'''
# Define a retry function for use in recipes
retry_function := '
retry() {
if [[ "${#}" -lt 3 ]]; then
echo "retry usage: <number of tries> <time between retries> <command> ..."
return 1
fi
tries="${1}"
sleep="${2}"
shift 2
for i in $(seq 1 ${tries}); do
if [[ ${i} -gt 1 ]]; then
# echo "[+] Command failed. Waiting for ${sleep} seconds"
sleep ${sleep}
fi
# echo "[+] Running (try: ${i}): ${@}"
"${@}" && r=0 && break || r=$?
done
return $r
}
'
# Default is to only validate the manifests
all: validate
# Basic validation to make sure the manifests are not completely broken
validate:
./ci/validate
branch:
#!/bin/bash
set -euo pipefail
git checkout main
version={{release_ver}}
# recipe will exit if branching the repo fails, such as if branch already exists
git branch f${version}
sed -i "s/${version}/$(( version + 1 ))/g" comps-sync.py README.md
sed -i "s/releasever: ${version}/releasever: $(( version + 1 ))/" common.yaml
git add comps-sync.py common.yaml README.md
git commit -m "Update main branch to $(( version + 1 ))"
git checkout f${version}
sed -i --follow-symlinks "/- fedora-rawhide/d" *.yaml
sed -i --follow-symlinks "s/# - fedora/- fedora/" *.yaml
sed -i --follow-symlinks "s/# - updates/- updates/" *.yaml
sed -i "s/releasever_ref: \"rawhide\"/releasever_ref: \"${version}\"/" common.yaml
git add *.yaml
git commit -m "Update configs for branch f${version}"
# Sync the manifests with the content from the Fedora comps repo
# Use a shallow clone, pull latest changes and save the result by default
[arg("checkonly", short="c", long="checkonly", value="true"), arg("nopull", short="n", long="nopull", value="true")]
comps checkonly="false" nopull="false":
#!/bin/bash
set -euo pipefail
if [[ ! -d fedora-comps ]]; then
git clone --depth 1 https://forge.fedoraproject.org/releng/fedora-comps.git
else
if [[ "{{nopull}}" == "false" ]]; then
pushd fedora-comps > /dev/null || exit 1
if [[ "$(git rev-parse --is-shallow-repository)" == "true" ]]; then
git fetch --unshallow
else
git fetch
fi
git reset --hard origin/main
popd > /dev/null || exit 1
fi
fi
save=""
if [[ "{{checkonly}}" == "false" ]]; then
save="--save"
fi
version={{release_ver}}
./comps-sync.py ${save} fedora-comps/comps-f${version}.xml.in
# Output the processed manifest for a given variant (defaults to Silverblue)
manifest variant="silverblue":
#!/bin/bash
set -euo pipefail
rpm-ostree compose tree --print-only --repo=repo {{variant}}.yaml
# Perform dependency resolution for a given variant (defaults to Silverblue)
compose-dry-run variant="silverblue":
#!/bin/bash
set -euxo pipefail
mkdir -p repo cache logs
if [[ ! -f "repo/config" ]]; then
pushd repo > /dev/null || exit 1
ostree init --repo . --mode=bare-user
popd > /dev/null || exit 1
fi
rpm-ostree compose tree --unified-core --repo=repo --dry-run {{variant}}.yaml
# Alias/shortcut for compose-image command
compose variant="silverblue": (compose-image variant)
# Compose a variant using the legacy non container path (defaults to Silverblue)
compose-legacy variant="silverblue":
#!/bin/bash
set -euxo pipefail
declare -A pretty_names={{pretty_names}}
variant={{variant}}
variant_pretty=${pretty_names[$variant]-}
if [[ -z $variant_pretty ]]; then
echo "Unknown variant"
exit 1
fi
just validate > /dev/null || (echo "Failed manifest validation" && exit 1)
mkdir -p repo cache logs
if [[ ! -f "repo/config" ]]; then
pushd repo > /dev/null || exit 1
ostree init --repo . --mode=archive-z2
popd > /dev/null || exit 1
fi
# Set option to reduce fsync for transient builds
ostree --repo=repo config set 'core.fsync' 'false'
buildid="$(date '+%Y%m%d.0')"
timestamp="$(date --iso-8601=sec)"
echo "${buildid}" > .buildid
version={{release_ver}}
echo "Composing ${variant_pretty} ${version}.${buildid} ..."
ARGS=(
"--repo=repo"
"--cachedir=cache"
"--unified-core"
"--force-nocache"
)
CMD="rpm-ostree"
if [[ ${EUID} -ne 0 ]]; then
CMD="sudo rpm-ostree"
fi
${CMD} compose tree "${ARGS[@]}" \
--add-metadata-string="version=${variant_pretty} ${version}.${buildid}" \
"${variant}-ostree.yaml" \
|& tee "logs/${variant}_${version}_${buildid}.${timestamp}.log"
if [[ ${EUID} -ne 0 ]]; then
sudo chown --recursive "$(id --user --name):$(id --group --name)" repo cache
fi
ostree summary --repo=repo --update
# Compose an Ostree Native Container OCI image
compose-image variant="silverblue":
#!/bin/bash
set -euxo pipefail
declare -A pretty_names={{pretty_names}}
variant={{variant}}
variant_pretty=${pretty_names[$variant]-}
if [[ -z $variant_pretty ]]; then
echo "Unknown variant"
exit 1
fi
just validate > /dev/null || (echo "Failed manifest validation" && exit 1)
mkdir -p cache
buildid="$(date '+%Y%m%d.0')"
timestamp="$(date --iso-8601=sec)"
echo "${buildid}" > .buildid
version={{release_ver}}
echo "Composing ${variant_pretty} ${version}.${buildid} ..."
ARGS=(
"--cachedir=cache"
"--initialize"
"--label=quay.expires-after=4w"
"--max-layers=96"
"--force-nocache"
)
# To debug with gdb, use: gdb --args ...
CMD="rpm-ostree"
if [[ ${EUID} -ne 0 ]]; then
CMD="sudo rpm-ostree"
fi
${CMD} compose image "${ARGS[@]}" \
"${variant}.yaml" \
"${variant}.ociarchive"
# Clean up everything
clean-all:
just clean-repo
just clean-cache
# Only clean the ostree repo
clean-repo:
rm -rf ./repo
# Only clean the package and repo caches
clean-cache:
rm -rf ./cache
# Upload a container to a registry and sign it. Used in CI
upload-container variant="silverblue" arch="default":
#!/bin/bash
set -euxo pipefail
{{retry_function}}
variant={{variant}}
arch={{arch}}
declare -A pretty_names={{pretty_names}}
variant_pretty=${pretty_names[$variant]-}
if [[ -z $variant_pretty ]]; then
echo "Unknown variant"
exit 1
fi
if [[ "${CI}" != "true" ]]; then
echo "Skipping: Not in CI"
exit 1
fi
if [[ -z ${REGISTRY+x} ]] || [[ -z ${RELEASE_REPO+x} ]]; then
echo "Skipping: No REGISTRY or RELEASE_REPO set"
exit 1
fi
if [[ -z ${CI_REGISTRY_USER+x} ]] || [[ -z ${CI_REGISTRY_PASSWORD+x} ]]; then
echo "Skipping: No CI_REGISTRY_USER or CI_REGISTRY_PASSWORD set"
exit 1
fi
buildid=""
if [[ -f ".buildid" ]]; then
buildid="$(< .buildid)"
else
echo "Skipping: No '.buildid' file"
exit 1
fi
# Login to the registry
retry 5 60 skopeo login --username "${CI_REGISTRY_USER}" --password "${CI_REGISTRY_PASSWORD}" "${REGISTRY}"
# Login to the registry again for cosign
retry 5 60 skopeo login --username "${CI_REGISTRY_USER}" --password "${CI_REGISTRY_PASSWORD}" \
--authfile="${HOME}/.docker/config.json" "${REGISTRY}"
image="${REGISTRY}/${RELEASE_REPO}/${variant}"
# Only append arch suffix if requested
suffix=""
if [[ ${arch} != "default" ]]; then
suffix="-${arch}"
fi
# Support for the zstd:chunked format is not ready yet
SKOPEO_ARGS=(
"--retry-times" "3"
"--dest-compress-format" "zstd"
)
version={{release_ver}}
# Push fully versioned tag (major version, build date/id, arch)
retry 5 60 skopeo copy "${SKOPEO_ARGS[@]}" \
"oci-archive:${variant}.ociarchive" \
"docker://${image}:${version}.${buildid}${suffix}"
# Decode private key
printenv "COSIGN_PRIVATE_KEY" > private.key.b64
base64 --decode private.key.b64 > private.key
# Sign images recursively
retry 5 60 cosign sign -y --key private.key ${image}:${version}.${buildid}${suffix}
# Cleanup private key
rm private.key.b64 private.key
# Upload a container to an anonymous registry. Useful for local builds
upload-container-local variant="silverblue" arch="default":
#!/bin/bash
set -euxo pipefail
{{retry_function}}
variant={{variant}}
arch={{arch}}
declare -A pretty_names={{pretty_names}}
variant_pretty=${pretty_names[$variant]-}
if [[ -z $variant_pretty ]]; then
echo "Unknown variant"
exit 1
fi
if [[ -z ${REGISTRY+x} ]] || [[ -z ${RELEASE_REPO+x} ]]; then
echo "Skipping: No REGISTRY or RELEASE_REPO set"
exit 1
fi
buildid=""
if [[ -f ".buildid" ]]; then
buildid="$(< .buildid)"
else
echo "Skipping: No '.buildid' file"
exit 1
fi
if [[ -n ${CI_REGISTRY_USER+x} ]] || [[ -n ${CI_REGISTRY_PASSWORD+x} ]]; then
# Login to the registry
retry 5 60 skopeo login --username "${CI_REGISTRY_USER}" --password "${CI_REGISTRY_PASSWORD}" "${REGISTRY}"
fi
image="${REGISTRY}/${RELEASE_REPO}/${variant}"
# Only append arch suffix if requested
suffix=""
if [[ ${arch} != "default" ]]; then
suffix="-${arch}"
fi
# Support for the zstd:chunked format is not ready yet
SKOPEO_ARGS=(
"--retry-times" "3"
"--dest-tls-verify=false"
"--dest-compress-format" "zstd"
)
version={{release_ver}}
# Push fully versioned tag (major version, build date/id, arch)
retry 5 60 skopeo copy "${SKOPEO_ARGS[@]}" \
"oci-archive:${variant}.ociarchive" \
"docker://${image}:${version}.${buildid}${suffix}"
# Push under the rawhide name as needed
if [[ {{is_rawhide}} ]]; then
retry 5 60 skopeo copy "${SKOPEO_ARGS[@]}" \
"oci-archive:${variant}.ociarchive" \
"docker://${image}:rawhide.${buildid}${suffix}"
fi
# Create a multi-arch manifest for a given variant, push it to a registry and sign it
multi-arch-manifest variant="silverblue":
#!/bin/bash
set -euxo pipefail
{{retry_function}}
variant={{variant}}
declare -A pretty_names={{pretty_names}}
variant_pretty=${pretty_names[$variant]-}
if [[ -z $variant_pretty ]]; then
echo "Unknown variant"
exit 1
fi
if [[ "${CI}" != "true" ]]; then
echo "Skipping: Not in CI"
exit 1
fi
if [[ -z ${REGISTRY+x} ]] || [[ -z ${RELEASE_REPO+x} ]]; then
echo "Skipping: No REGISTRY or RELEASE_REPO set"
exit 1
fi
if [[ -z ${CI_REGISTRY_USER+x} ]] || [[ -z ${CI_REGISTRY_PASSWORD+x} ]]; then
echo "Skipping: No CI_REGISTRY_USER or CI_REGISTRY_PASSWORD set"
exit 1
fi
buildid=""
if [[ -f ".buildid" ]]; then
buildid="$(< .buildid)"
else
echo "Skipping: No '.buildid' file"
exit 1
fi
# Login to the registry
retry 5 60 skopeo login --username "${CI_REGISTRY_USER}" --password "${CI_REGISTRY_PASSWORD}" "${REGISTRY}"
# Login to the registry again for cosign
retry 5 60 skopeo login --username "${CI_REGISTRY_USER}" --password "${CI_REGISTRY_PASSWORD}" \
--authfile="${HOME}/.docker/config.json" "${REGISTRY}"
image="${REGISTRY}/${RELEASE_REPO}/${variant}"
version={{release_ver}}
# Create manifest with full version tags
buildah manifest create "${image}:${version}.${buildid}" \
"${image}:${version}.${buildid}-x86_64" \
"${image}:${version}.${buildid}-aarch64"
# Decode private key
printenv "COSIGN_PRIVATE_KEY" > private.key.b64
base64 --decode private.key.b64 > private.key
# Push fully versioned dual arch manifest tag (major version, build date/id)
retry 5 60 buildah manifest push \
"${image}:${version}.${buildid}" \
"docker://${image}:${version}.${buildid}"
# Push under the rawhide name as needed
if [[ {{is_rawhide}} ]]; then
retry 5 60 buildah manifest push \
"${image}:${version}.${buildid}" \
"docker://${image}:rawhide.${buildid}"
fi
# Sign manifest
retry 5 60 cosign sign -y --key private.key ${image}:${version}.${buildid}
# Update "un-versioned" tag (only major version)
retry 5 60 buildah manifest push \
"${image}:${version}.${buildid}" \
"docker://${image}:${version}"
# Push under the rawhide name as needed
if [[ {{is_rawhide}} ]]; then
retry 5 60 buildah manifest push \
"${image}:${version}.${buildid}" \
"docker://${image}:rawhide"
fi
# Sign manifest
retry 5 60 cosign sign -y --key private.key ${image}:${version}
if [[ "${variant}" == "kinoite-nightly" ]]; then
# Update latest tag for kinoite-nightly only
buildah manifest push \
"${image}:${version}.${buildid}" \
"docker://${image}:latest"
# Sign manifest
cosign sign -y --key private.key ${image}:latest
fi
# Cleanup private key
rm private.key.b64 private.key