Files
alfresco-content-app/.github/actions/deploy-local-acs/action.yml
Adam Świderski 84c8805135 [ACS-12735] Added cluster logs for failed "deploy local acs" step (#5370)
* [ACS-12735] Added cluster logs for failed "deploy local acs" step

* [ACS-12735] Added changes from acs-deployment file

* [ACS-12735] added pods logs to upload artifacts

* [ACS-12735] deleted duplicated code
2026-09-03 15:24:34 +02:00

320 lines
12 KiB
YAML

name: deploy-local-acs
description: Deploy local ACS for E2E testing
inputs:
docker_username:
description: 'Docker username'
required: true
docker_password:
description: 'Docker password'
required: true
quay_username:
description: 'Quay username'
required: true
quay_password:
description: 'Quay password'
required: true
acs_deployment_version:
description: >-
Git ref (tag, branch, or commit SHA) of the Alfresco/acs-deployment
repository to check out. Use the special value 'latest' (the default)
to resolve to the latest GA release tag at runtime.
When set to 'master', pre-release_values.yaml is included in the Helm
install to pick up pre-release image tags; any other ref uses the
chart's standard values.yaml instead.
required: false
default: 'latest'
helm_install_timeout:
description: >-
Timeout for the Helm install to wait for the chart's hooks (e.g. the
search reindexing job) and, via --wait, its Deployments, StatefulSets
and PVCs to become ready, in Helm's duration format (e.g. '5m', '10m').
required: false
default: '10m'
log_name_identifier:
description: >-
Suffix that makes the uploaded pod-logs artifact name unique. Callers in a
matrix must pass a value unique per leg (e.g. browser + suite) to avoid
artifact name collisions.
required: false
default: 'deploy-local-acs'
runs:
using: "composite"
steps:
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310
with:
version: "3.14.3"
- name: Login to Docker Hub
id: dockerhub-login
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
continue-on-error: true
with:
username: ${{ inputs.docker_username }}
password: ${{ inputs.docker_password }}
- name: Retry Docker Hub login on transient failure
if: steps.dockerhub-login.outcome == 'failure'
shell: bash
env:
DOCKER_USERNAME: ${{ inputs.docker_username }}
DOCKER_PASSWORD: ${{ inputs.docker_password }}
run: |
for attempt in 1 2 3; do
err=$(echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin 2>&1) && exit 0
# Bail out on credential errors; retrying only annoys the registry and delays the real fix.
if echo "$err" | grep -qiE "401|403|unauthorized|denied|forbidden"; then
echo "$err"
exit 1
fi
sleep_s=$((attempt * 5))
echo "docker login attempt $attempt failed: $err"
echo "retrying in ${sleep_s}s..."
sleep "$sleep_s"
done
exit 1
- name: Login to Quay.io
id: quay-login
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
continue-on-error: true
with:
registry: quay.io
username: ${{ inputs.quay_username }}
password: ${{ inputs.quay_password }}
- name: Retry Quay.io login on transient failure
if: steps.quay-login.outcome == 'failure'
shell: bash
env:
QUAY_USERNAME: ${{ inputs.quay_username }}
QUAY_PASSWORD: ${{ inputs.quay_password }}
run: |
for attempt in 1 2 3; do
err=$(echo "$QUAY_PASSWORD" | docker login quay.io -u "$QUAY_USERNAME" --password-stdin 2>&1) && exit 0
if echo "$err" | grep -qiE "401|403|unauthorized|denied|forbidden"; then
echo "$err"
exit 1
fi
sleep_s=$((attempt * 5))
echo "quay login attempt $attempt failed: $err"
echo "retrying in ${sleep_s}s..."
sleep "$sleep_s"
done
exit 1
- name: Setup cluster
uses: Alfresco/alfresco-build-tools/.github/actions/setup-kind@v18.26.0
with:
ingress-nginx-ref: controller-v1.8.2
ingress-creation-timeout: 180s
- name: Set nginx ingress config
shell: bash
run: >-
kubectl -n ingress-nginx patch cm ingress-nginx-controller
-p '{"data": {"allow-snippet-annotations":"true"}}'
- name: Create registries auth secret
shell: bash
run: >-
kubectl create secret generic regcred
--from-file=.dockerconfigjson=$HOME/.docker/config.json
--type=kubernetes.io/dockerconfigjson
- name: Add dependency chart repos
shell: bash
run: |
helm repo add self https://alfresco.github.io/alfresco-helm-charts/
helm repo add elastic https://helm.elastic.co/
- name: Resolve acs-deployment ref
id: get-acs-version
shell: bash
env:
ACS_VERSION_INPUT: ${{ inputs.acs_deployment_version }}
GITHUB_TOKEN: ${{ github.token }}
run: |
if [ "$ACS_VERSION_INPUT" != "latest" ]; then
echo "Using specified acs-deployment ref: $ACS_VERSION_INPUT"
echo "version=$ACS_VERSION_INPUT" >> "$GITHUB_OUTPUT"
exit 0
fi
auth_header=()
[ -n "$GITHUB_TOKEN" ] && auth_header=(-H "Authorization: Bearer $GITHUB_TOKEN")
max_retries=3
retry_count=0
while [ $retry_count -lt $max_retries ]; do
echo "Attempt $((retry_count + 1)) of $max_retries to fetch latest ACS deployment version..."
response=$(curl -s "${auth_header[@]}" https://api.github.com/repos/Alfresco/acs-deployment/releases/latest)
latest_tag=$(echo "$response" | jq -r .tag_name 2>/dev/null || echo "")
if [ "$latest_tag" != "null" ] && [ -n "$latest_tag" ]; then
echo "Successfully fetched latest ACS deployment version: $latest_tag"
echo "version=$latest_tag" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Warning: Received invalid response (tag_name: $latest_tag)"
retry_count=$((retry_count + 1))
if [ $retry_count -lt $max_retries ]; then
sleep_time=$((2 ** retry_count))
echo "Retrying in $sleep_time seconds..."
sleep $sleep_time
fi
done
echo "Error: Failed to fetch latest ACS deployment version after $max_retries attempts"
echo "Last response: $response"
exit 1
- name: Checkout acs-deployment ${{ steps.get-acs-version.outputs.version }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: Alfresco/acs-deployment
ref: ${{ steps.get-acs-version.outputs.version }}
path: acs-deployment
- name: Helm install
shell: bash
env:
ACS_VERSION_INPUT: ${{ inputs.acs_deployment_version }}
HELM_INSTALL_TIMEOUT: ${{ inputs.helm_install_timeout }}
run: |
[ "$ACS_VERSION_INPUT" = "master" ] && chart_values="pre-release_values.yaml" || chart_values="values.yaml"
for attempt in 1 2 3; do
if helm dep build acs-deployment/helm/alfresco-content-services; then
break
fi
if [ "$attempt" -eq 3 ]; then
echo "helm dep build failed after 3 attempts"
exit 1
fi
sleep_s=$((attempt * 10))
echo "helm dep build attempt $attempt failed, retrying in ${sleep_s}s..."
sleep "$sleep_s"
done
helm install acs acs-deployment/helm/alfresco-content-services \
--wait \
--timeout "$HELM_INSTALL_TIMEOUT" \
--set global.search.sharedSecret="$(openssl rand -hex 24)" \
--values "acs-deployment/helm/alfresco-content-services/${chart_values}" \
--values acs-deployment/test/enterprise-integration-test-values.yaml \
--values .github/acs-deployment-values-override.yaml
- name: Dump cluster state on deploy failure
if: failure()
shell: bash
run: |
echo "::group::Helm releases"
helm ls --all-namespaces --all || true
echo "::endgroup::"
echo "::group::Helm status (acs)"
helm status acs --show-resources || true
echo "::endgroup::"
echo "::group::All resources (all namespaces)"
kubectl get all --all-namespaces || true
echo "::endgroup::"
echo "::group::Node metrics"
kubectl top nodes || true
echo "::endgroup::"
echo "::group::Pod metrics (by memory)"
kubectl top pod --all-namespaces --sort-by=memory || true
echo "::endgroup::"
echo "::group::Recent cluster events"
kubectl get events -A --sort-by=.lastTimestamp | tail -n 100 || true
echo "::endgroup::"
# Filter on the Ready condition, not phase: the usual culprit is a repository pod stuck phase=Running/Ready=False on a startup-probe timeout, which a phase filter would miss.
pods=$(kubectl get pods -A \
-o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.status.phase}{"\t"}{range .status.conditions[?(@.type=="Ready")]}{.status}{end}{"\n"}{end}' \
2>/dev/null || true)
not_ready=$(echo "$pods" | awk -F'\t' '$3 != "Succeeded" && $4 != "True" { print $1" "$2 }')
if [ -z "$not_ready" ]; then
echo "No not-ready pods were found."
exit 0
fi
while read -r ns pod; do
[ -z "$ns" ] && continue
echo "::group::describe ${ns}/${pod}"
kubectl describe pod -n "$ns" "$pod" || true
echo "::endgroup::"
echo "::group::logs ${ns}/${pod} (previous)"
kubectl logs -n "$ns" "$pod" --all-containers --previous --tail=200 2>/dev/null || echo "(no previous container logs)"
echo "::endgroup::"
done <<< "$not_ready"
- name: Report deployed ACS versions
if: always()
shell: bash
env:
ACS_DEPLOYMENT_VERSION: ${{ steps.get-acs-version.outputs.version }}
run: |
pre_release_values="acs-deployment/helm/alfresco-content-services/pre-release_values.yaml"
pod_images=$(kubectl get pods -A \
-o jsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.name}{"="}{.image}{"\n"}{end}{end}' \
2>/dev/null | sort -u || true)
cluster_images=$(echo "${pod_images}" | awk -F'\t' 'NF > 1 { sub(/^[^=]*=/, "", $NF); print $NF }' | sort -u)
acs_repository_image=$(echo "${cluster_images}" | grep -m1 'alfresco-content-repository:' || echo "(alfresco-content-repository pod not found)")
acs_repository_tag="${acs_repository_image##*:}"
# ACS_DEPLOYMENT_VERSION is a git ref (branch, tag, or SHA) — resolve it to the
# exact commit SHA that was checked out so past runs can be reproduced even
# when moving refs like `master` have advanced.
acs_deployment_commit=$(git -C acs-deployment rev-parse HEAD 2>/dev/null || echo "(unknown)")
{
echo "### 🐳 Deployed ACS versions"
echo "- **ACS repository:** \`${acs_repository_tag}\`"
echo "- **acs-deployment ref:** \`${ACS_DEPLOYMENT_VERSION}\`"
echo "- **acs-deployment commit:** \`${acs_deployment_commit}\`"
echo "**Container images in cluster:**"
echo "${cluster_images:-(no pods found)}"
} >> "$GITHUB_STEP_SUMMARY"
echo "::group::ACS repository image tag"
echo "${acs_repository_image}"
echo "::endgroup::"
echo "::group::acs-deployment ref"
echo "${ACS_DEPLOYMENT_VERSION}"
echo "::endgroup::"
echo "::group::acs-deployment commit"
echo "${acs_deployment_commit}"
echo "::endgroup::"
values_path="acs-deployment/helm/alfresco-content-services/values.yaml"
[ "$ACS_DEPLOYMENT_VERSION" = "master" ] && values_path="$pre_release_values"
echo "::group::Chart values file used ($(basename "$values_path"))"
if [ -f "$values_path" ]; then
cat "$values_path"
else
echo "(file not found: $values_path)"
fi
echo "::endgroup::"
echo "::group::Actual container images running in the cluster"
echo "${pod_images:-(no pods found)}"
echo "::endgroup::"
- name: Upload pods logs
if: always()
uses: Alfresco/alfresco-build-tools/.github/actions/kubectl-keep-nslogs@d2981070adf1a68c3ddcbf0ebba193467261c9b3 # v18.26.0
with:
namespace: default
log_retention: 7
log_name_identifier: "logs-pods-${{ inputs.log_name_identifier }}"