Public Access
CICD / Build and Publish CICD Base Image (push) Successful in 37s
CICD / Build and Push CICD Image (push) Successful in 26m6s
CICD / Build CICD Image Failure Postmortem (push) Has been skipped
CICD / Pre-commit Checks (push) Successful in 2m54s
CICD / Frontend Tests (push) Successful in 33s
CICD / Backend Doctests (push) Successful in 39s
CICD / Backend Tests (push) Successful in 23m40s
CICD / Source Lanes Failure Postmortem (push) Has been skipped
CICD / CICD Tests Complete (push) Successful in 7s
CICD / Build Backend Base Image (push) Successful in 2m9s
CICD / Build Integration Tester Image (push) Successful in 1m16s
CICD / Build Frontend Base Image (push) Successful in 8m54s
CICD / Build and Publish Runtime Images (Legacy Disabled) (push) Has been skipped
CICD / Build Backend Main Image (push) Successful in 6m17s
CICD / Build Frontend Main Image (push) Successful in 6m3s
CICD / Build E2E Tester Image (push) Successful in 17m43s
CICD / Runtime Images Failure Postmortem (push) Has been skipped
CICD / Production Images Complete (push) Successful in 4s
CICD / Runtime Black-Box Integration Tests (push) Successful in 1m39s
CICD / Integration Tests Failure Postmortem (push) Has been skipped
CICD / End-to-End Tests (push) Failing after 5m40s
CICD / E2E Tests Failure Postmortem (push) Successful in 11s
257 lines
9.5 KiB
YAML
257 lines
9.5 KiB
YAML
name: Renovate Dependency Updates
|
|
|
|
on:
|
|
schedule:
|
|
# Run Renovate every Monday at 8 AM UTC
|
|
- cron: '0 8 * * 1'
|
|
workflow_dispatch: # Allow manual triggering
|
|
inputs:
|
|
dry_run:
|
|
description: 'Run in dry-run mode (no changes made)'
|
|
required: false
|
|
default: 'false'
|
|
type: boolean
|
|
|
|
jobs:
|
|
renovate:
|
|
name: Renovate Dependencies
|
|
# Non-heavy workflow: allow any host exposing the generic ubuntu-act label.
|
|
runs-on: ubuntu-act
|
|
timeout-minutes: 90
|
|
|
|
steps:
|
|
- name: Prepare Renovate container image
|
|
env:
|
|
RENOVATE_IMAGE: ghcr.io/renovatebot/renovate:41
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
retry_cmd() {
|
|
attempts="${1:-3}"
|
|
backoff="${2:-10}"
|
|
shift 2
|
|
|
|
attempt=1
|
|
while [ "${attempt}" -le "${attempts}" ]; do
|
|
if "$@"; then
|
|
return 0
|
|
fi
|
|
|
|
if [ "${attempt}" -lt "${attempts}" ]; then
|
|
sleep_seconds=$((backoff * attempt))
|
|
echo "Command failed (attempt ${attempt}/${attempts}): $*"
|
|
echo "Retrying in ${sleep_seconds}s"
|
|
sleep "${sleep_seconds}"
|
|
fi
|
|
attempt=$((attempt + 1))
|
|
done
|
|
|
|
echo "Command failed after ${attempts} attempts: $*"
|
|
return 1
|
|
}
|
|
|
|
echo "=== Preparing Renovate container ==="
|
|
echo "Using Renovate image: ${RENOVATE_IMAGE}"
|
|
free -h || true
|
|
|
|
retry_cmd 3 15 docker pull "${RENOVATE_IMAGE}"
|
|
docker run --rm "${RENOVATE_IMAGE}" --version
|
|
|
|
echo "RENOVATE_IMAGE=${RENOVATE_IMAGE}" >> "$GITHUB_ENV"
|
|
|
|
- name: Configure Renovate for Gitea
|
|
run: |
|
|
echo "=== Configuring Renovate for Gitea ==="
|
|
|
|
# Renovate reads RENOVATE_TOKEN, RENOVATE_PLATFORM, RENOVATE_ENDPOINT,
|
|
# and RENOVATE_GIT_AUTHOR directly from the environment at runtime.
|
|
# Keeping the config file minimal avoids repeated migration warnings.
|
|
cat > renovate-config.js << 'EOF'
|
|
module.exports = {
|
|
platform: 'gitea',
|
|
endpoint: 'https://dogar.darkhelm.org/api/v1',
|
|
gitAuthor: 'Renovate Bot <renovate@darkhelm.org>',
|
|
repositories: ['DarkHelm.org/plex-playlist'],
|
|
onboarding: false,
|
|
requireConfig: 'required',
|
|
extends: ['local>DarkHelm.org/plex-playlist'],
|
|
prConcurrentLimit: 3,
|
|
branchConcurrentLimit: 5,
|
|
};
|
|
EOF
|
|
|
|
echo "✓ Renovate configuration created"
|
|
|
|
- name: Run Renovate
|
|
env:
|
|
# Prefer dedicated Renovate token, then fall back to existing CI tokens.
|
|
RENOVATE_TOKEN_SECRET: ${{ secrets.RENOVATE_TOKEN }}
|
|
ACTIONS_TRIGGER_TOKEN: ${{ secrets.ACTIONS_TRIGGER_TOKEN }}
|
|
PACKAGE_ACCESS_TOKEN: ${{ secrets.PACKAGE_ACCESS_TOKEN }}
|
|
RENOVATE_DRY_RUN: ${{ inputs.dry_run }}
|
|
RENOVATE_CONFIG_FILE: renovate-config.js
|
|
RENOVATE_PLATFORM: gitea
|
|
RENOVATE_ENDPOINT: https://dogar.darkhelm.org
|
|
RENOVATE_ALLOW_INSECURE_TLS: "true"
|
|
LOG_LEVEL: info
|
|
run: |
|
|
echo "=== Running Renovate Bot ==="
|
|
TARGET_REPO="DarkHelm.org/plex-playlist"
|
|
TARGET_ORG="${TARGET_REPO%%/*}"
|
|
|
|
RENOVATE_ENDPOINT_EFFECTIVE="${RENOVATE_ENDPOINT%/}"
|
|
if [[ "${RENOVATE_ENDPOINT_EFFECTIVE}" == */api/v1 ]]; then
|
|
API_ENDPOINT="${RENOVATE_ENDPOINT_EFFECTIVE}"
|
|
else
|
|
API_ENDPOINT="${RENOVATE_ENDPOINT_EFFECTIVE}/api/v1"
|
|
fi
|
|
|
|
export RENOVATE_ENDPOINT="${API_ENDPOINT}"
|
|
echo "Renovate endpoint: ${RENOVATE_ENDPOINT}"
|
|
echo "Preflight API endpoint: ${API_ENDPOINT}"
|
|
|
|
CURL_INSECURE_FLAG=""
|
|
if [ "${RENOVATE_ALLOW_INSECURE_TLS:-false}" = "true" ]; then
|
|
echo "⚠ Renovate insecure TLS mode enabled for self-signed certificate endpoint"
|
|
CURL_INSECURE_FLAG="--insecure"
|
|
export NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
fi
|
|
|
|
select_token_with_repo_access() {
|
|
for candidate_name in RENOVATE_TOKEN_SECRET ACTIONS_TRIGGER_TOKEN PACKAGE_ACCESS_TOKEN; do
|
|
candidate_value="${!candidate_name:-}"
|
|
if [ -z "${candidate_value}" ]; then
|
|
continue
|
|
fi
|
|
|
|
USER_STATUS=$(curl -sS -o /tmp/renovate-auth-check-user.json -w "%{http_code}" \
|
|
${CURL_INSECURE_FLAG} \
|
|
-H "Authorization: token ${candidate_value}" \
|
|
"${API_ENDPOINT}/user" || true)
|
|
|
|
REPO_STATUS=$(curl -sS -o /tmp/renovate-auth-check-repo.json -w "%{http_code}" \
|
|
${CURL_INSECURE_FLAG} \
|
|
-H "Authorization: token ${candidate_value}" \
|
|
"${API_ENDPOINT}/repos/${TARGET_REPO}" || true)
|
|
|
|
ORG_STATUS=$(curl -sS -o /tmp/renovate-auth-check-org.json -w "%{http_code}" \
|
|
${CURL_INSECURE_FLAG} \
|
|
-H "Authorization: token ${candidate_value}" \
|
|
"${API_ENDPOINT}/orgs/${TARGET_ORG}" || true)
|
|
|
|
if [ "${USER_STATUS}" = "200" ] && [ "${REPO_STATUS}" = "200" ] && [ "${ORG_STATUS}" = "200" ]; then
|
|
echo "${candidate_name}:${candidate_value}"
|
|
return 0
|
|
fi
|
|
|
|
echo "⚠ Token candidate ${candidate_name} rejected (user=${USER_STATUS}, repo=${REPO_STATUS}, org=${ORG_STATUS})"
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
if ! SELECTED_TOKEN_RESULT="$(select_token_with_repo_access)"; then
|
|
echo "❌ No token available for Renovate authentication with repository access"
|
|
echo "Configure RENOVATE_TOKEN with repo+issue write and organization/user read scopes."
|
|
echo "Token preflight checks attempted: ${API_ENDPOINT}/user, ${API_ENDPOINT}/repos/${TARGET_REPO}, and ${API_ENDPOINT}/orgs/${TARGET_ORG}"
|
|
if [ -s /tmp/renovate-auth-check-user.json ]; then
|
|
echo "Last user endpoint response body:"
|
|
cat /tmp/renovate-auth-check-user.json || true
|
|
fi
|
|
if [ -s /tmp/renovate-auth-check-repo.json ]; then
|
|
echo "Last repo endpoint response body:"
|
|
cat /tmp/renovate-auth-check-repo.json || true
|
|
fi
|
|
if [ -s /tmp/renovate-auth-check-org.json ]; then
|
|
echo "Last org endpoint response body:"
|
|
cat /tmp/renovate-auth-check-org.json || true
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
SELECTED_TOKEN_SOURCE="${SELECTED_TOKEN_RESULT%%:*}"
|
|
SELECTED_TOKEN="${SELECTED_TOKEN_RESULT#*:}"
|
|
export RENOVATE_TOKEN="${SELECTED_TOKEN}"
|
|
unset SELECTED_TOKEN RESULT_TOKEN
|
|
|
|
echo "✓ Renovate auth preflight passed with ${SELECTED_TOKEN_SOURCE}"
|
|
|
|
# Run Renovate with configuration
|
|
if [ "${RENOVATE_DRY_RUN}" = "true" ]; then
|
|
export RENOVATE_DRY_RUN="full"
|
|
echo "🔍 Running in DRY-RUN mode (no changes will be made)"
|
|
else
|
|
unset RENOVATE_DRY_RUN
|
|
fi
|
|
|
|
docker run --rm \
|
|
-v "$PWD:/work" \
|
|
-w /work \
|
|
-e LOG_LEVEL \
|
|
-e NODE_TLS_REJECT_UNAUTHORIZED \
|
|
-e RENOVATE_TOKEN \
|
|
-e RENOVATE_PLATFORM \
|
|
-e RENOVATE_ENDPOINT \
|
|
-e RENOVATE_DRY_RUN \
|
|
-e RENOVATE_CONFIG_FILE=/work/renovate-config.js \
|
|
"${RENOVATE_IMAGE}" \
|
|
--platform "${RENOVATE_PLATFORM}" \
|
|
--endpoint "${RENOVATE_ENDPOINT}" \
|
|
DarkHelm.org/plex-playlist | tee /tmp/renovate.log
|
|
|
|
echo "✓ Renovate execution completed"
|
|
|
|
- name: Failure diagnostics
|
|
if: failure()
|
|
run: |
|
|
echo "=== Failure Diagnostics ==="
|
|
date -u '+timestamp_utc=%Y-%m-%dT%H:%M:%SZ'
|
|
echo "runner_name=${RUNNER_NAME:-unknown}"
|
|
echo "runner_hostname=${HOSTNAME:-unknown}"
|
|
uname -a || true
|
|
cat /etc/os-release 2>/dev/null || true
|
|
df -h || true
|
|
free -h || true
|
|
ps aux --sort=-%mem | head -n 30 || true
|
|
|
|
if command -v docker >/dev/null 2>&1; then
|
|
echo "=== Docker Diagnostics ==="
|
|
docker version || true
|
|
docker info || true
|
|
docker ps -a || true
|
|
docker images --digests | head -n 50 || true
|
|
else
|
|
echo "docker not available on this runner"
|
|
fi
|
|
|
|
echo "=== Kernel Tail ==="
|
|
dmesg | tail -n 120 || true
|
|
|
|
- name: Upload Renovate logs
|
|
if: always()
|
|
run: |
|
|
if [ -f "/tmp/renovate.log" ]; then
|
|
echo "=== Renovate Log Output ==="
|
|
echo "Last 50 lines of Renovate log:"
|
|
tail -50 /tmp/renovate.log
|
|
|
|
# Save log as artifact (if GitHub Actions artifact support exists)
|
|
mkdir -p /tmp/artifacts
|
|
cp /tmp/renovate.log /tmp/artifacts/renovate-$(date +%Y%m%d-%H%M%S).log
|
|
else
|
|
echo "No Renovate log file found"
|
|
fi
|
|
|
|
- name: Report Results
|
|
if: always()
|
|
run: |
|
|
echo "=== Renovate Execution Summary ==="
|
|
echo "Repository: DarkHelm.org/plex-playlist"
|
|
echo "Execution time: $(date)"
|
|
echo "Dry run mode: ${RENOVATE_DRY_RUN:-false}"
|
|
echo ""
|
|
echo "Check the Dependency Dashboard issue in your repository for detailed results:"
|
|
echo "https://dogar.darkhelm.org/DarkHelm.org/plex-playlist/issues"
|
|
echo ""
|
|
echo "Next scheduled run: Next Monday at 8 AM UTC"
|