ci: add dry-run check and release artifact; matrix runners
This commit is contained in:
29
.github/workflows/ci.yml
vendored
29
.github/workflows/ci.yml
vendored
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user