ci: add dry-run check and release artifact; matrix runners

This commit is contained in:
alex-local
2025-09-05 23:53:41 +02:00
parent a0085d75e3
commit 29621df44e
2 changed files with 113 additions and 20 deletions

View File

@@ -9,7 +9,10 @@ on:
jobs: jobs:
lint: lint:
name: Lint scripts & YAML name: Lint scripts & YAML
runs-on: ubuntu-latest runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-20.04]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -49,6 +52,12 @@ jobs:
echo "No YAML files found to lint" echo "No YAML files found to lint"
fi fi
- name: Dry-run setup script
run: |
set -e
chmod +x awx-local-setup/setup_awx_local.sh
./awx-local-setup/setup_awx_local.sh --dry-run --repo-root="$(pwd)"
kustomize-validate: kustomize-validate:
name: Validate kustomize builds (if any) name: Validate kustomize builds (if any)
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -75,3 +84,21 @@ jobs:
fi fi
done done
$ok || (echo "One or more kustomize builds failed" && exit 1) $ok || (echo "One or more kustomize builds failed" && exit 1)
release:
name: Create release artifact
runs-on: ubuntu-latest
needs: [lint, kustomize-validate]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create tarball
run: |
tar -czf awx-local-setup.tar.gz awx-local-setup
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: awx-local-setup
path: awx-local-setup.tar.gz

View File

@@ -9,6 +9,7 @@ PORT=8082
NODEPORT=30081 NODEPORT=30081
AWX_NAMESPACE=awx AWX_NAMESPACE=awx
REPO_ROOT="$(pwd)" REPO_ROOT="$(pwd)"
DRY_RUN=0
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
@@ -16,6 +17,7 @@ while [[ $# -gt 0 ]]; do
--nodeport) NODEPORT="$2"; shift 2 ;; --nodeport) NODEPORT="$2"; shift 2 ;;
--namespace) AWX_NAMESPACE="$2"; shift 2 ;; --namespace) AWX_NAMESPACE="$2"; shift 2 ;;
--repo-root) REPO_ROOT="$2"; shift 2 ;; --repo-root) REPO_ROOT="$2"; shift 2 ;;
--dry-run) DRY_RUN=1; shift 1 ;;
-h|--help) echo "Usage: $0 [--port PORT] [--nodeport NODEPORT] [--namespace NAMESPACE] [--repo-root PATH]"; exit 0 ;; -h|--help) echo "Usage: $0 [--port PORT] [--nodeport NODEPORT] [--namespace NAMESPACE] [--repo-root PATH]"; exit 0 ;;
*) echo "Unknown arg: $1"; exit 1 ;; *) echo "Unknown arg: $1"; exit 1 ;;
esac esac
@@ -25,35 +27,57 @@ echo "Running AWX local setup"
echo "Port-forward local port: ${PORT} -> service:80 (bind 0.0.0.0)" echo "Port-forward local port: ${PORT} -> service:80 (bind 0.0.0.0)"
echo "AWX NodePort to request: ${NODEPORT}" echo "AWX NodePort to request: ${NODEPORT}"
if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
echo "DRY RUN: cluster operations will be skipped"
fi
# prerequisites # prerequisites
for cmd in kubectl minikube curl ss ip; do for cmd in kubectl minikube curl ss ip; do
if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
# skip checking cluster commands in dry-run mode
break
fi
if ! command -v $cmd >/dev/null 2>&1; then if ! command -v $cmd >/dev/null 2>&1; then
echo "Missing prerequisite: $cmd"; exit 1 echo "Missing prerequisite: $cmd"; exit 1
fi fi
done done
# start minikube if needed # start minikube if needed
if ! kubectl get nodes >/dev/null 2>&1; then if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
echo "No Kubernetes cluster detected. Starting minikube..." echo "DRY RUN: skipping cluster start/check"
minikube start else
if ! kubectl get nodes >/dev/null 2>&1; then
echo "No Kubernetes cluster detected. Starting minikube..."
minikube start
fi
fi fi
# ensure namespace # ensure namespace
kubectl get ns ${AWX_NAMESPACE} >/dev/null 2>&1 || kubectl create ns ${AWX_NAMESPACE} kubectl get ns ${AWX_NAMESPACE} >/dev/null 2>&1 || kubectl create ns ${AWX_NAMESPACE}
# apply CRDs and operator manager from the awx-operator repo # apply CRDs and operator manager from the awx-operator repo
if [ -d "${REPO_ROOT}/config/crd" ]; then if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
kubectl apply -k "${REPO_ROOT}/config/crd" echo "DRY RUN: would apply CRDs and manager from ${REPO_ROOT}/config"
fi else
if [ -d "${REPO_ROOT}/config/rbac" ]; then if [ -d "${REPO_ROOT}/config/crd" ]; then
kubectl apply -k "${REPO_ROOT}/config/rbac" kubectl apply -k "${REPO_ROOT}/config/crd"
fi fi
if [ -d "${REPO_ROOT}/config/manager" ]; then if [ -d "${REPO_ROOT}/config/rbac" ]; then
kubectl apply -k "${REPO_ROOT}/config/manager" -n ${AWX_NAMESPACE} || true kubectl apply -k "${REPO_ROOT}/config/rbac"
fi
if [ -d "${REPO_ROOT}/config/manager" ]; then
kubectl apply -k "${REPO_ROOT}/config/manager" -n ${AWX_NAMESPACE} || true
fi
fi fi
# create leader-election RBAC if missing # create leader-election RBAC if missing
cat <<'EOF' | kubectl apply -n ${AWX_NAMESPACE} -f - cat <<'EOF' | (
if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
cat >/dev/null
else
kubectl apply -n ${AWX_NAMESPACE} -f -
fi
)
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: Role kind: Role
metadata: metadata:
@@ -64,7 +88,30 @@ rules:
verbs: ["get","create","update","patch","delete","watch","list"] verbs: ["get","create","update","patch","delete","watch","list"]
EOF EOF
kubectl get rolebinding awx-operator-leader-election -n ${AWX_NAMESPACE} >/dev/null 2>&1 || cat <<'EOF' | kubectl apply -n ${AWX_NAMESPACE} -f - if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
echo "DRY RUN: would ensure rolebinding awx-operator-leader-election in ${AWX_NAMESPACE}"
else
kubectl get rolebinding awx-operator-leader-election -n ${AWX_NAMESPACE} >/dev/null 2>&1 || cat <<'EOF' | kubectl apply -n ${AWX_NAMESPACE} -f -
EOF
fi
if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
:
else
cat <<'EOF' | kubectl apply -n ${AWX_NAMESPACE} -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: awx-operator-leader-election
subjects:
- kind: ServiceAccount
name: controller-manager
roleRef:
kind: Role
name: awx-operator-leader-election
apiGroup: rbac.authorization.k8s.io
EOF
fi
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding kind: RoleBinding
metadata: metadata:
@@ -80,7 +127,11 @@ EOF
# wait for operator deployment to be available # wait for operator deployment to be available
echo "Waiting for controller-manager deployment to be available..." echo "Waiting for controller-manager deployment to be available..."
kubectl -n ${AWX_NAMESPACE} wait --for=condition=available deployment/controller-manager --timeout=180s || true if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
echo "DRY RUN: skipping wait for controller-manager"
else
kubectl -n ${AWX_NAMESPACE} wait --for=condition=available deployment/controller-manager --timeout=180s || true
fi
# Create corrected AWX CR yaml in /tmp and apply # Create corrected AWX CR yaml in /tmp and apply
TMP_CR=/tmp/awx-cr-generated.yaml TMP_CR=/tmp/awx-cr-generated.yaml
@@ -101,22 +152,37 @@ spec:
EOF EOF
echo "Applying AWX CR from ${TMP_CR}" echo "Applying AWX CR from ${TMP_CR}"
kubectl apply -f ${TMP_CR} if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
echo "DRY RUN: would apply ${TMP_CR}"
else
kubectl apply -f ${TMP_CR}
fi
# force reconcile # force reconcile
kubectl -n ${AWX_NAMESPACE} annotate awx awx awx-operator-refresh=$(date +%s) --overwrite || true if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
echo "DRY RUN: would annotate AWX CR to force reconcile"
else
kubectl -n ${AWX_NAMESPACE} annotate awx awx awx-operator-refresh=$(date +%s) --overwrite || true
fi
# wait for awx-web pod readiness (give it a long timeout because migrations run) # wait for awx-web pod readiness (give it a long timeout because migrations run)
echo "Waiting for awx-web pod to become ready (this may take several minutes)..." echo "Waiting for awx-web pod to become ready (this may take several minutes)..."
# wait until a pod with label app.kubernetes.io/name=awx-web is ready if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
kubectl -n ${AWX_NAMESPACE} wait --for=condition=ready pod -l app.kubernetes.io/name=awx-web --timeout=900s || true echo "DRY RUN: skipping wait for awx-web readiness"
else
kubectl -n ${AWX_NAMESPACE} wait --for=condition=ready pod -l app.kubernetes.io/name=awx-web --timeout=900s || true
fi
# choose a free local port and start port-forward bound to 0.0.0.0 # choose a free local port and start port-forward bound to 0.0.0.0
for p in ${PORT} $(seq 18080 18090); do for p in ${PORT} $(seq 18080 18090); do
ss -ltn | awk '{print $4}' | grep -q ":$p$" || { LISTEN_PORT=$p; break; } ss -ltn | awk '{print $4}' | grep -q ":$p$" || { LISTEN_PORT=$p; break; }
done done
if [ -z "${LISTEN_PORT:-}" ]; then echo "No free port found to bind port-forward"; exit 1; fi if [ -z "${LISTEN_PORT:-}" ]; then echo "No free port found to bind port-forward"; exit 1; fi
kubectl -n ${AWX_NAMESPACE} port-forward --address 0.0.0.0 svc/awx-service ${LISTEN_PORT}:80 &>/tmp/awx-port-forward.log & echo $! > /tmp/awx-pf.pid if [ "${DRY_RUN}" = "1" ] || [ "${SKIP_CLUSTER:-0}" = "1" ]; then
echo "DRY RUN: would start port-forward: host-port ${LISTEN_PORT} -> awx-service:80"
else
kubectl -n ${AWX_NAMESPACE} port-forward --address 0.0.0.0 svc/awx-service ${LISTEN_PORT}:80 &>/tmp/awx-port-forward.log & echo $! > /tmp/awx-pf.pid
fi
sleep 1 sleep 1
echo "Port-forward started: host-port ${LISTEN_PORT} -> awx-service:80" echo "Port-forward started: host-port ${LISTEN_PORT} -> awx-service:80"