Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/actions/install-ci-deps/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Install CI dependencies
description: Install system packages and tools for ARC/Kubernetes GitHub Actions runners

inputs:
profile:
description: Dependency set to install (k8s-runner or golang-container)
required: false
default: k8s-runner
install_kind:
description: Install kind
required: false
default: "false"
install_kubectl:
description: Install kubectl
required: false
default: "false"
install_helm:
description: Install Helm
required: false
default: "false"
install_yq:
description: Install yq
required: false
default: "false"

runs:
using: composite
steps:
- name: Install dependencies
shell: bash
env:
INSTALL_KIND: ${{ inputs.install_kind }}
INSTALL_KUBECTL: ${{ inputs.install_kubectl }}
INSTALL_HELM: ${{ inputs.install_helm }}
INSTALL_YQ: ${{ inputs.install_yq }}
run: bash "${{ github.action_path }}/install-ci-deps.sh" "${{ inputs.profile }}"
184 changes: 184 additions & 0 deletions .github/actions/install-ci-deps/install-ci-deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#!/usr/bin/env bash
# Install CI dependencies for GitHub Actions on ARC/Kubernetes runners.
#
# ARC runner pods use the actions-runner image, which is minimal and typically
# runs as a non-root user without sudo. Job-level `container:` directives are
# not supported unless the runner scale set is configured for container jobs, so
# workflows install what they need directly into the runner pod.
set -euo pipefail

PROFILE="${1:-k8s-runner}"
LOCAL_ROOT="${HOME}/.local"
LOCAL_BIN="${LOCAL_ROOT}/bin"
mkdir -p "$LOCAL_BIN"

add_to_path() {
local dir="$1"
if [ -d "$dir" ] && [[ ":${PATH}:" != *":${dir}:"* ]]; then
export PATH="${dir}:${PATH}"
if [ -n "${GITHUB_PATH:-}" ]; then
echo "$dir" >> "$GITHUB_PATH"
fi
fi
}

add_to_path "$LOCAL_BIN"
add_to_path "${LOCAL_ROOT}/usr/bin"

install_apt_packages() {
local packages=("$@")
if [ "${#packages[@]}" -eq 0 ]; then
return 0
fi

if [ "$(id -u)" -eq 0 ] && command -v apt-get >/dev/null 2>&1; then
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "${packages[@]}"
return 0
fi

if command -v sudo >/dev/null 2>&1 && sudo -n true 2>/dev/null && command -v apt-get >/dev/null 2>&1; then
sudo apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "${packages[@]}"
return 0
fi

if ! command -v dpkg-deb >/dev/null 2>&1; then
echo "dpkg-deb is required to install packages without root." >&2
exit 1
fi

local workdir
workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"' RETURN

cd "$workdir"
for pkg in "${packages[@]}"; do
if apt-get download "$pkg" 2>/dev/null; then
dpkg-deb -x "${pkg}"_*.deb "$LOCAL_ROOT"
rm -f "${pkg}"_*.deb
continue
fi

case "$pkg" in
make)
curl -fsSL "http://archive.ubuntu.com/ubuntu/pool/main/m/make-dfsg/make_4.3-4.1build1_amd64.deb" -o make.deb
dpkg-deb -x make.deb "$LOCAL_ROOT"
;;
*)
echo "Failed to install ${pkg} without root." >&2
exit 1
;;
esac
done
}

ensure_command() {
command -v "$1" >/dev/null 2>&1
}

install_kind() {
ensure_command kind && return 0
local arch="amd64"
case "$(uname -m)" in
x86_64) arch="amd64" ;;
aarch64|arm64) arch="arm64" ;;
*)
echo "Unsupported architecture for kind: $(uname -m)" >&2
exit 1
;;
esac
curl -fsSL "https://kind.sigs.k8s.io/dl/latest/kind-linux-${arch}" -o "${LOCAL_BIN}/kind"
chmod +x "${LOCAL_BIN}/kind"
}

install_kubectl() {
ensure_command kubectl && return 0
local arch="amd64"
case "$(uname -m)" in
x86_64) arch="amd64" ;;
aarch64|arm64) arch="arm64" ;;
*)
echo "Unsupported architecture for kubectl: $(uname -m)" >&2
exit 1
;;
esac
local version
version="$(curl -fsSL https://dl.k8s.io/release/stable.txt)"
curl -fsSL "https://dl.k8s.io/release/${version}/bin/linux/${arch}/kubectl" -o "${LOCAL_BIN}/kubectl"
chmod +x "${LOCAL_BIN}/kubectl"
}

install_helm() {
ensure_command helm && return 0
local arch="amd64"
case "$(uname -m)" in
x86_64) arch="amd64" ;;
aarch64|arm64) arch="arm64" ;;
*)
echo "Unsupported architecture for helm: $(uname -m)" >&2
exit 1
;;
esac
local version
version="$(curl -fsSL https://get.helm.sh/helm-latest-version)"
curl -fsSL "https://get.helm.sh/helm-${version}-linux-${arch}.tar.gz" | tar xz -C "${RUNNER_TEMP:-/tmp}"
mv "${RUNNER_TEMP:-/tmp}/linux-${arch}/helm" "${LOCAL_BIN}/helm"
chmod +x "${LOCAL_BIN}/helm"
}

install_yq() {
ensure_command yq && return 0
local arch="amd64"
case "$(uname -m)" in
x86_64) arch="amd64" ;;
aarch64|arm64) arch="arm64" ;;
*)
echo "Unsupported architecture for yq: $(uname -m)" >&2
exit 1
;;
esac
curl -fsSL "https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${arch}" -o "${LOCAL_BIN}/yq"
chmod +x "${LOCAL_BIN}/yq"
}

case "$PROFILE" in
k8s-runner)
missing=()
ensure_command make || missing+=(make)
ensure_command curl || missing+=(curl)
ensure_command git || missing+=(git)
install_apt_packages "${missing[@]}"
add_to_path "${LOCAL_ROOT}/usr/bin"
;;
golang-container)
install_apt_packages make git curl ca-certificates
add_to_path "${LOCAL_ROOT}/usr/bin"
;;
*)
echo "Unknown profile: ${PROFILE}" >&2
exit 1
;;
esac

if [ "${INSTALL_KIND:-false}" = "true" ]; then
install_kind
fi
if [ "${INSTALL_KUBECTL:-false}" = "true" ]; then
install_kubectl
fi
if [ "${INSTALL_HELM:-false}" = "true" ]; then
install_helm
fi
if [ "${INSTALL_YQ:-false}" = "true" ]; then
install_yq
fi

echo "Installed CI dependencies (profile=${PROFILE})"
command -v make >/dev/null && make --version | head -1 || true
command -v go >/dev/null && go version || true
command -v kind >/dev/null && kind version || true
command -v kubectl >/dev/null && kubectl version --client=true || true
command -v helm >/dev/null && helm version --short || true
command -v yq >/dev/null && yq --version || true
command -v docker >/dev/null && docker version --format '{{.Client.Version}}' 2>/dev/null || true
29 changes: 20 additions & 9 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
name: Lint

on:
push:
pull_request:

concurrency:
group: lint-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
lint:
name: Lint
runs-on: self-hosted
container:
image: golang:1.25-bookworm
runs-on: hyperbytedb-operator-controller
steps:
- name: Clone the code
uses: actions/checkout@v4

# The job container runs as root, but the checkout files are owned by the
# runner user. Without marking the workspace as a safe directory, any
# `git` invocation (including the one Go uses for VCS stamping during
# typecheck) fails with `exit status 128`, which surfaces as a typecheck
# error from golangci-lint.
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25"
cache-dependency-path: go.sum

# Checkout files are owned by the runner user. Without marking the workspace
# as a safe directory, any `git` invocation (including the one Go uses for
# VCS stamping during typecheck) fails with `exit status 128`, which
# surfaces as a typecheck error from golangci-lint.
- name: Configure git safe directory
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"

- name: Install CI dependencies
uses: ./.github/actions/install-ci-deps
with:
profile: k8s-runner

- name: Check linter configuration
run: make lint-config

- name: Run linter
run: make lint
50 changes: 15 additions & 35 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ env:
jobs:
versions:
name: Compute versions
runs-on: self-hosted
container:
image: debian:bookworm-slim
runs-on: hyperbytedb-operator-controller
outputs:
chart_version: ${{ steps.compute.outputs.chart_version }}
image_tag: ${{ steps.compute.outputs.image_tag }}
Expand All @@ -67,22 +65,16 @@ jobs:
image:
name: Build & push operator image
needs: versions
runs-on: self-hosted
container:
image: golang:1.25-bookworm
volumes:
- /var/run/docker.sock:/var/run/docker.sock
runs-on: hyperbytedb-operator-controller
steps:
- name: Install Docker CLI
run: curl -fsSL https://get.docker.com | sh

- uses: actions/checkout@v4

- name: Configure git safe directory
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"

- name: Login to GHCR
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login "$REGISTRY" -u "${{ github.actor }}" --password-stdin
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build & push image
env:
Expand All @@ -101,21 +93,16 @@ jobs:
chart:
name: Package & push helm chart
needs: [versions, image]
runs-on: self-hosted
container:
image: alpine:3.20
runs-on: hyperbytedb-operator-controller
steps:
- name: Install dependencies
run: apk add --no-cache bash ca-certificates curl git tar yq

- name: Install Helm
run: |
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

- uses: actions/checkout@v4

- name: Configure git safe directory
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Install CI dependencies
uses: ./.github/actions/install-ci-deps
with:
profile: k8s-runner
install_helm: "true"
install_yq: "true"

- name: Login to GHCR
run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login "$REGISTRY" -u "${{ github.actor }}" --password-stdin
Expand Down Expand Up @@ -160,15 +147,8 @@ jobs:
name: GitHub Release
needs: [versions, chart]
if: needs.versions.outputs.is_release == 'true'
runs-on: self-hosted
container:
image: debian:bookworm-slim
runs-on: hyperbytedb-operator-controller
steps:
- name: Install dependencies
run: |
apt-get update
apt-get install -y ca-certificates curl

- uses: actions/download-artifact@v4
with:
name: hyperbytedb-operator-chart
Expand Down
Loading
Loading