Files
plex-playlist/.gitea/workflows/renovate.yml
Xlorep DarkHelm 1f6cafa1bc
Some checks failed
CICD Start / Sanity and Base Decision (push) Failing after 11m34s
Renovate Dependency Updates / Renovate Dependencies (push) Failing after 1h42m33s
TASK: Replace integration lane with post-build backend runtime black-box tests (#72)
## Summary

Replace the existing source-context integration lane with backend runtime black-box integration checks that run against started deployable containers.

This change wires deployable backend image references (both commit tag and immutable digest) from the build workflow into the tests workflow, then validates runtime behavior over network endpoints.

## Why

Integration confidence should come from testing running service artifacts, not only source-mounted or in-process execution.

## What Changed

- Build workflow now:
  - Publishes deployable backend image tag reference and digest reference
  - Exposes both as job outputs
  - Passes both references into CICD Tests dispatch inputs

- CICD Tests workflow now:
  - Accepts deployable backend tag and digest inputs
  - Propagates these through setup outputs
  - Replaces previous integration lane behavior with runtime black-box execution:
    - Starts isolated Docker network
    - Starts Postgres container
    - Starts backend container from digest-pinned deployable image
    - Enforces tag-to-digest consistency before running checks
    - Runs endpoint checks against live container:
      - GET /
      - GET /compatibility
      - GET /health
    - Captures backend/db logs and container state on failure
    - Cleans up containers and network via trap

- Documentation updated:
  - Runtime contract enforcement section now includes runtime black-box integration checks
  - CI success summary now reflects runtime integration lane behavior

## Scope

Included:
- Backend runtime black-box integration replacement for the existing integration lane
- Digest + tag identity enforcement
- Failure diagnostics for triage

Out of scope:
- Frontend runtime smoke checks
- E2E lane redesign

## Acceptance Criteria Mapping

- Integration tests execute against runtime container endpoints: 
- Integration lane consumes built image references (not source-mounted execution): 
- Failures surface service logs and test logs for triage: 

## Verification

- Workflow files pass local validation checks
- Pre-commit hooks pass on committed changes
- Branch pushed and ready for PR review

## Related

- Issue: #61
- Dependency context: #66

Co-authored-by: copilotcoder <copilotcoder@darkhelm.org>
Reviewed-on: #72
2026-07-05 22:48:57 -04:00

391 lines
15 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: Setup Node.js for Renovate
run: |
echo "=== Setting up Node.js 24 for Renovate ==="
# Check existing Node.js
if command -v node &> /dev/null; then
echo "Current Node.js version: $(node --version)"
fi
if command -v npm &> /dev/null; then
echo "Current npm version: $(npm --version)"
fi
# Aggressive cleanup of all Node.js/npm installations
echo "Performing complete Node.js cleanup..."
# Stop any Node.js processes
sudo pkill -f node || true
# Remove all package-managed Node.js installations
sudo apt-get remove -y --purge nodejs npm node || true
sudo apt-get autoremove -y --purge || true
# Remove all manual installations and caches
sudo rm -rf /usr/local/bin/node* /usr/local/bin/npm* || true
sudo rm -rf /usr/local/lib/node* /usr/local/include/node* || true
sudo rm -rf ~/.npm ~/.nvm ~/.node* || true
sudo rm -rf /root/.npm /root/.nvm /root/.node* || true
sudo rm -rf /usr/share/nodejs || true
sudo rm -rf /etc/apt/sources.list.d/nodesource.list* || true
# Clear npm environment variables that might conflict
unset npm_config_prefix npm_config_cache npm_config_globalconfig npm_config_init_module || true
echo "✓ Cleanup completed"
# Install Node.js 24 from NodeSource with error handling
echo "Installing Node.js 24..."
# Remove any existing NodeSource repository
sudo rm -f /etc/apt/sources.list.d/nodesource.list || true
# Add NodeSource repository
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
# Install with DEBIAN_FRONTEND to avoid interactive prompts
echo "Installing Node.js package..."
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs
# Verify and fix installation
echo "=== Verifying Node.js Installation ==="
# Check Node.js
if command -v node &> /dev/null; then
NODE_VERSION=$(node --version)
echo "✓ Node.js installed: $NODE_VERSION"
else
echo "❌ Node.js installation failed"
exit 1
fi
# Check npm and fix if needed
if command -v npm &> /dev/null && npm --version &> /dev/null; then
NPM_VERSION=$(npm --version)
echo "✓ npm working: $NPM_VERSION"
else
echo "⚠️ npm not working properly, reinstalling..."
# Method 1: Try to fix npm with the bundled version
if [ -f "/usr/bin/node" ] && [ -f "/usr/lib/node_modules/npm/bin/npm-cli.js" ]; then
echo "Using bundled npm..."
sudo ln -sf /usr/lib/node_modules/npm/bin/npm-cli.js /usr/bin/npm || true
sudo chmod +x /usr/bin/npm || true
fi
# Method 2: If that doesn't work, reinstall npm manually
if ! npm --version &> /dev/null; then
echo "Manual npm installation..."
curl -L https://www.npmjs.com/install.sh | sudo sh
fi
# Method 3: Last resort - use npx to bootstrap npm
if ! npm --version &> /dev/null; then
echo "Using node to run npm directly..."
# Create npm wrapper script
echo '#!/bin/bash' | sudo tee /usr/bin/npm > /dev/null
echo 'exec /usr/bin/node /usr/lib/node_modules/npm/bin/npm-cli.js "$@"' | sudo tee -a /usr/bin/npm > /dev/null
sudo chmod +x /usr/bin/npm
fi
# Final verification
if npm --version &> /dev/null; then
echo "✓ npm recovered successfully: $(npm --version)"
else
echo "❌ npm recovery failed"
exit 1
fi
fi
# Test npm basic functionality
echo "Testing npm functionality..."
if npm config get registry &> /dev/null; then
echo "✓ npm configuration accessible"
else
echo "⚠️ npm configuration issues, but continuing..."
fi
# Check version compatibility for Renovate
NODE_VERSION=$(node --version | cut -d'v' -f2)
echo "=== Version Compatibility Check ==="
echo "Node.js version: $NODE_VERSION"
if [[ $(echo "$NODE_VERSION 24.10.0" | awk '{print ($1 >= $2)}') == 1 ]]; then
echo "✅ Node.js version $NODE_VERSION meets Renovate latest requirements"
echo "RENOVATE_VERSION=latest" >> $GITHUB_ENV
else
echo "⚠️ Node.js version $NODE_VERSION - will use compatible Renovate version"
echo "RENOVATE_VERSION=40.3.2" >> $GITHUB_ENV
fi
- name: Install Renovate
run: |
echo "=== Installing Renovate ==="
# Set npm configuration for memory efficiency
npm config set fund false
npm config set audit false
npm config set progress false
npm config set maxsockets 3
npm config set fetch-retry-mintimeout 2000
npm config set fetch-retry-maxtimeout 10000
# Use the version determined in previous step
echo "Installing Renovate version: $RENOVATE_VERSION"
# Check available memory
echo "Memory info:"
free -h || echo "free command not available"
# Install with retry logic and memory-efficient options
for i in 1 2 3; do
echo "Renovate installation attempt $i/3..."
# Clear npm cache and temp files
npm cache clean --force || true
rm -rf /tmp/npm-* || true
# Use memory-efficient installation with longer timeout
if NODE_OPTIONS="--max-old-space-size=2048" timeout 600 npm install -g "renovate@$RENOVATE_VERSION" \
--no-audit \
--no-fund \
--no-optional \
--production \
--maxsockets=3 \
--fetch-timeout=30000; then
echo "✓ Renovate installation successful on attempt $i"
break
else
exit_code=$?
echo "⚠️ Renovate installation attempt $i failed (exit code: $exit_code)"
# Check if it was killed due to memory
if [ $exit_code -eq 137 ] || [ $exit_code -eq 143 ]; then
echo " Process was killed (likely out of memory)"
fi
if [ $i -eq 3 ]; then
echo "❌ All Renovate installation attempts failed"
echo "Debugging information:"
echo "Node.js version: $(node --version)"
echo "npm version: $(npm --version)"
echo "Memory status:"
free -h || echo "Memory info unavailable"
echo "npm config:"
npm config list || echo "npm config failed"
exit 1
fi
echo "Waiting 30 seconds before retry..."
sleep 30
fi
done
# Verify Renovate installation
echo "✓ Renovate version: $(renovate --version)"
echo "✓ Renovate location: $(which renovate)"
- 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',
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}"
RENOVATE_ENDPOINT_EFFECTIVE="${RENOVATE_ENDPOINT_EFFECTIVE%/api/v1}"
else
API_ENDPOINT="${RENOVATE_ENDPOINT_EFFECTIVE}/api/v1"
fi
export RENOVATE_ENDPOINT="${RENOVATE_ENDPOINT_EFFECTIVE}"
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
renovate --platform "${RENOVATE_PLATFORM}" --endpoint "${RENOVATE_ENDPOINT}" DarkHelm.org/plex-playlist
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"