mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 03:38:23 +00:00
Merge remote-tracking branch 'upstream/main' into feature/self-host-runners
# Conflicts: # .github/workflows/test-deploy-universal.yml # .github/workflows/test-deploy-workstation.yml
This commit is contained in:
597 files changed
+19255
-5920
No files matched your search
@@ -8,7 +8,9 @@ This directory holds the shell helpers that GitHub Actions workflows under [`.gi
|
||||
|---|---|
|
||||
| [runner/](runner/) | Host-runner hygiene around image builds and deploys (disk, swap, Docker daemon, diagnostics). |
|
||||
| [cancel/](cancel/) | Cancellation of in-progress workflow runs on PR-close and branch-delete events. |
|
||||
| [cleanup/](cleanup/) | Scheduled repository maintenance that prunes stale GitHub resources. |
|
||||
| [resolve/](resolve/) | Derivation of structured workflow inputs and outputs from repository state. |
|
||||
| [sync/](sync/) | Ref synchronization before workflow jobs derive CI scope from git history. |
|
||||
| [update/](update/) | The scheduled `Update: Versions` pipeline (version bumps and PR open/refresh). |
|
||||
| [release/](release/) | Release-time gates that decide whether a tagged commit may be released. |
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Repository Cleanup 🧹
|
||||
|
||||
Shell helpers for scheduled repository-maintenance workflows that prune stale GitHub resources.
|
||||
|
||||
## Scope 📋
|
||||
|
||||
Helpers in this directory are invoked by maintenance workflows under [`.github/workflows/`](../../../.github/workflows/).
|
||||
They may call the GitHub API through `gh`, but MUST keep destructive selection criteria inside scripts so workflow files remain orchestration-only.
|
||||
CI image cleanup derives distro-specific package names from `INFINITO_DISTROS`, whose default comes from [default.env](../../../default.env) through the environment loader.
|
||||
|
||||
For the workflow catalog that drives these calls see [workflows.md](../../../docs/contributing/tools/github/actions/workflows.md).
|
||||
Executable
+101
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../../.." && pwd)"
|
||||
|
||||
# shellcheck source=scripts/meta/env/load.sh
|
||||
# shellcheck disable=SC1091
|
||||
source "${REPO_ROOT}/scripts/meta/env/load.sh"
|
||||
|
||||
: "${GH_TOKEN:?Missing GH_TOKEN}"
|
||||
: "${ORG:?Missing ORG}"
|
||||
|
||||
package_prefix="${PACKAGE_PREFIX:-core}"
|
||||
max_age_days="${MAX_AGE_DAYS:-30}"
|
||||
tag_prefix="${TAG_PREFIX:-ci-}"
|
||||
|
||||
if [[ ! "${max_age_days}" =~ ^[0-9]+$ ]]; then
|
||||
echo "ERROR: MAX_AGE_DAYS must be a non-negative integer." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${tag_prefix}" ]]; then
|
||||
echo "ERROR: TAG_PREFIX must not be empty." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v gh >/dev/null 2>&1; then
|
||||
echo "ERROR: gh CLI not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v jq >/dev/null 2>&1; then
|
||||
echo "ERROR: jq not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
encode_package_name() {
|
||||
local package="${1}"
|
||||
jq -rn --arg value "${package}" '$value | @uri'
|
||||
}
|
||||
|
||||
resolve_packages() {
|
||||
if [[ -n "${PACKAGES:-}" ]]; then
|
||||
printf '%s\n' "${PACKAGES}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
: "${INFINITO_DISTROS:?Missing INFINITO_DISTROS}"
|
||||
|
||||
for distro in ${INFINITO_DISTROS}; do
|
||||
printf '%s/%s\n' "${package_prefix}" "${distro}"
|
||||
done
|
||||
}
|
||||
|
||||
is_deletable_ci_version() {
|
||||
local version="${1}"
|
||||
local tags
|
||||
|
||||
tags="$(jq -r '.tags[]?' <<<"${version}")"
|
||||
|
||||
[[ -n "${tags}" ]] || return 1
|
||||
|
||||
# Keep release tags even when the version also has ci-* tags.
|
||||
grep -q "^${tag_prefix}" <<<"${tags}" || return 1
|
||||
grep -Eq "^(latest|v.*)$" <<<"${tags}" && return 1
|
||||
grep -vq "^${tag_prefix}" <<<"${tags}" && return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
cutoff="$(date -u -d "${max_age_days} days ago" +%s)"
|
||||
|
||||
while IFS= read -r package; do
|
||||
package="${package#"${package%%[![:space:]]*}"}"
|
||||
package="${package%"${package##*[![:space:]]}"}"
|
||||
[[ -n "${package}" ]] || continue
|
||||
|
||||
encoded_package="$(encode_package_name "${package}")"
|
||||
|
||||
gh api --paginate \
|
||||
"/orgs/${ORG}/packages/container/${encoded_package}/versions" \
|
||||
--jq '.[] | {id: .id, updated_at: .updated_at, tags: .metadata.container.tags}' |
|
||||
jq -c '.' |
|
||||
while IFS= read -r version; do
|
||||
id="$(jq -r '.id' <<<"${version}")"
|
||||
updated_at="$(jq -r '.updated_at' <<<"${version}")"
|
||||
updated_ts="$(date -u -d "${updated_at}" +%s)"
|
||||
|
||||
if [[ "${updated_ts}" -ge "${cutoff}" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
is_deletable_ci_version "${version}" || continue
|
||||
|
||||
echo "Deleting ${package} version ${id} updated at ${updated_at}"
|
||||
gh api \
|
||||
--method DELETE \
|
||||
"/orgs/${ORG}/packages/container/${encoded_package}/versions/${id}"
|
||||
done
|
||||
done < <(resolve_packages)
|
||||
@@ -6,9 +6,18 @@
|
||||
# INFINITO_WHITELIST — optional space-separated allowlist
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
||||
cd "${REPO_ROOT}"
|
||||
|
||||
# shellcheck source=scripts/meta/env/python.sh
|
||||
source "${REPO_ROOT}/scripts/meta/env/python.sh"
|
||||
|
||||
apps="$(./scripts/meta/resolve/apps.sh)"
|
||||
[[ -n "$apps" ]] || apps='[]'
|
||||
|
||||
echo "apps=$apps" >>"$GITHUB_OUTPUT"
|
||||
echo "apps_json=$apps" >>"$GITHUB_OUTPUT"
|
||||
echo "apps_json=$apps"
|
||||
matrix="$(printf '%s' "$apps" | "${PYTHON}" -m utils.github.variant_bundles)"
|
||||
[[ -n "$matrix" ]] || matrix='[]'
|
||||
|
||||
echo "apps=$matrix" >>"$GITHUB_OUTPUT"
|
||||
echo "apps=$matrix"
|
||||
@@ -17,11 +17,14 @@ version_tag="$1"
|
||||
|
||||
owner="$(_helpers/scripts/meta/resolve/repository/owner.sh)"
|
||||
repo_prefix="$(_helpers/scripts/meta/resolve/repository/name.sh)"
|
||||
distros="$(_helpers/scripts/meta/resolve/distros.sh)"
|
||||
# shellcheck source=scripts/meta/env/load.sh
|
||||
# shellcheck disable=SC1091
|
||||
source "_helpers/scripts/meta/env/load.sh"
|
||||
: "${INFINITO_DISTROS:?Missing INFINITO_DISTROS}"
|
||||
|
||||
{
|
||||
echo "version_tag=${version_tag}"
|
||||
echo "distros=${distros}"
|
||||
echo "distros=${INFINITO_DISTROS}"
|
||||
echo "repo_prefix=${repo_prefix}"
|
||||
echo "owner=${owner}"
|
||||
} >>"$GITHUB_OUTPUT"
|
||||
@@ -0,0 +1,3 @@
|
||||
# GitHub Sync Helpers 🔄
|
||||
|
||||
This directory contains shell helpers that synchronize repository refs before later workflow jobs derive CI scope from git history.
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
: "${GITHUB_REPOSITORY:?Missing GITHUB_REPOSITORY}"
|
||||
|
||||
default_source="${CI_SYNC_MAIN_SOURCE_REPOSITORY_DEFAULT:-infinito-nexus/core}"
|
||||
configured_source="${CI_SYNC_MAIN_SOURCE_REPOSITORY:-}"
|
||||
configured_source_is_set="${CI_SYNC_MAIN_SOURCE_REPOSITORY_IS_SET:-false}"
|
||||
|
||||
if [[ "${configured_source_is_set}" == "true" ]]; then
|
||||
source_repository="${configured_source}"
|
||||
else
|
||||
source_repository="${default_source}"
|
||||
fi
|
||||
|
||||
source_trimmed="${source_repository//[[:space:]]/}"
|
||||
source_lower="$(printf '%s' "${source_trimmed}" | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
case "${source_lower}" in
|
||||
"" | "false" | "0" | "no" | "off" | "none")
|
||||
echo "Main sync skipped because CI_SYNC_MAIN_SOURCE_REPOSITORY is disabled."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
normalize_repository() {
|
||||
local value="${1}"
|
||||
value="${value#https://github.com/}"
|
||||
value="${value#http://github.com/}"
|
||||
value="${value#ssh://git@github.com/}"
|
||||
value="${value#git@github.com:}"
|
||||
value="${value%.git}"
|
||||
printf '%s' "${value}" | tr '[:upper:]' '[:lower:]'
|
||||
}
|
||||
|
||||
target_repository="$(normalize_repository "${GITHUB_REPOSITORY}")"
|
||||
source_repository="$(normalize_repository "${source_trimmed}")"
|
||||
|
||||
if [[ "${source_repository}" == "${target_repository}" ]]; then
|
||||
echo "Main sync skipped because source repository matches current repository: ${GITHUB_REPOSITORY}."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${source_repository}" != */* ]]; then
|
||||
echo "ERROR: CI_SYNC_MAIN_SOURCE_REPOSITORY must be '<owner>/<repo>', a GitHub URL, or a disabled value." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Syncing ${GITHUB_REPOSITORY}:main from ${source_repository}:main."
|
||||
git fetch "https://github.com/${source_repository}.git" main:refs/remotes/main-sync-source/main --force
|
||||
git push origin refs/remotes/main-sync-source/main:refs/heads/main --force
|
||||
Reference in new issue
Block a user