Skip to content

Merge pull request #64 from Sambego/fix/next-updates #68

Merge pull request #64 from Sambego/fix/next-updates

Merge pull request #64 from Sambego/fix/next-updates #68

name: Build and Release Sample Artifacts
on:
push:
branches: [main]
paths:
- '*/*/release-config.yml'
- '*/**'
- '!.github/**'
- '!LICENSE'
- '.github/workflows/create-sample-releases.yml'
workflow_dispatch:
inputs:
force_rebuild:
description: 'Force rebuild all artifacts'
required: false
default: false
type: boolean
permissions:
contents: write
actions: read
jobs:
build-artifacts:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Create artifacts directory
run: mkdir -p artifacts
- name: Find and validate release configurations
run: |
echo "🔍 Finding release configurations..."
RELEASE_CONFIGS=$(find . -name "release-config.yml" -not -path "./.git/*" | sort)
if [ -z "$RELEASE_CONFIGS" ]; then
echo "❌ No release-config.yml files found!"
echo "📂 Available directories:"
find . -type d -maxdepth 3 | head -20
exit 1
fi
echo "✅ Found release configurations:"
echo "$RELEASE_CONFIGS"
# Validate each config file
for config_file in $RELEASE_CONFIGS; do
echo "📄 Validating: $config_file"
# Check if it has required fields and included: true
if grep -q "^category:" "$config_file" && grep -q "^framework:" "$config_file"; then
INCLUDED=$(grep "^included:" "$config_file" | sed 's/included: *//' | tr -d ' ')
if [ "$INCLUDED" = "true" ]; then
echo " ✅ Valid configuration (included: true)"
else
echo " ⏭️ Skipping (included: $INCLUDED)"
fi
else
echo " ❌ Missing required fields (category, framework) in $config_file"
exit 1
fi
done
- name: Check if changed files are in configured directories
run: |
echo "🔍 Checking if changes affect configured quickstarts..."
# Get list of directories with release-config.yml
CONFIG_DIRS=$(find . -name "release-config.yml" -not -path "./.git/*" -exec dirname {} \; | sort)
echo "📂 Directories with release-config.yml:"
echo "$CONFIG_DIRS"
# If this is a manual trigger, rebuild all
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "🔄 Manual trigger - will rebuild all configured samples"
echo "SHOULD_BUILD=true" >> $GITHUB_ENV
exit 0
fi
# Check if any changed files are in directories with release-config.yml
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || echo "")
if [ -z "$CHANGED_FILES" ]; then
echo "📝 No changed files detected, building all"
echo "SHOULD_BUILD=true" >> $GITHUB_ENV
exit 0
fi
echo "📝 Changed files:"
echo "$CHANGED_FILES"
# Check if the workflow file itself was changed
if echo "$CHANGED_FILES" | grep -q "^\.github/workflows/create-sample-releases\.yml$"; then
echo "🔧 Workflow file changed - forcing rebuild of all samples"
echo "SHOULD_BUILD=true" >> $GITHUB_ENV
exit 0
fi
SHOULD_BUILD=false
for config_dir in $CONFIG_DIRS; do
# Remove leading ./
clean_dir=$(echo "$config_dir" | sed 's|^\./||')
# Check if any changed file is in this directory
if echo "$CHANGED_FILES" | grep -q "^$clean_dir/"; then
echo "✅ Changes detected in configured directory: $clean_dir"
SHOULD_BUILD=true
break
fi
done
if [ "$SHOULD_BUILD" = "true" ]; then
echo "🔄 Will rebuild artifacts (changes in configured directories)"
echo "SHOULD_BUILD=true" >> $GITHUB_ENV
else
echo "⏭️ No changes in configured directories, skipping build"
echo "SHOULD_BUILD=false" >> $GITHUB_ENV
fi
- name: Download existing release assets (if any)
if: env.SHOULD_BUILD == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "📥 Checking for existing 'latest' release assets..."
# Get changed files
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || echo "")
# Determine if we should preserve existing assets
PRESERVE_ASSETS=true
if echo "$CHANGED_FILES" | grep -q "^\.github/workflows/create-sample-releases\.yml$"; then
echo "🔧 Workflow file changed - skipping asset preservation (full rebuild)"
PRESERVE_ASSETS=false
elif [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ github.event.inputs.force_rebuild }}" = "true" ]; then
echo "🔄 Force rebuild requested - skipping asset preservation (full rebuild)"
PRESERVE_ASSETS=false
elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "🔄 Manual trigger - skipping asset preservation (full rebuild)"
PRESERVE_ASSETS=false
fi
if [ "$PRESERVE_ASSETS" = "true" ]; then
# Check if latest release exists
if gh release view latest >/dev/null 2>&1; then
echo "✅ Found existing 'latest' release"
# Download existing assets to preserve them
mkdir -p existing_assets
gh release download latest --dir existing_assets 2>/dev/null || echo "No assets to download"
# Move existing assets to artifacts directory
for existing_zip in existing_assets/*.zip; do
if [ -f "$existing_zip" ]; then
FILENAME=$(basename "$existing_zip")
echo "📦 Preserving existing: $FILENAME"
cp "$existing_zip" "artifacts/"
fi
done
rm -rf existing_assets
else
echo "ℹ️ No existing 'latest' release found"
fi
else
echo "🧹 Skipping asset preservation - will rebuild all from scratch"
fi
- name: Build quickstart packages from configs
if: env.SHOULD_BUILD == 'true'
run: |
echo "📦 Building sample packages from configurations..."
# Store the absolute path to artifacts directory
ARTIFACTS_DIR="$(pwd)/artifacts"
# Get changed files to determine which directories to rebuild
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || echo "")
# Check if workflow file changed (rebuild all if so)
REBUILD_ALL=false
if echo "$CHANGED_FILES" | grep -q "^\.github/workflows/create-sample-releases\.yml$"; then
echo "🔧 Workflow file changed - rebuilding ALL samples"
REBUILD_ALL=true
elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "🔄 Manual trigger - rebuilding ALL samples"
REBUILD_ALL=true
elif [ "${{ github.event.inputs.force_rebuild }}" = "true" ]; then
echo "🔄 Force rebuild requested - rebuilding ALL samples"
REBUILD_ALL=true
elif [ -z "$CHANGED_FILES" ]; then
echo "📝 No changed files detected - rebuilding ALL samples"
REBUILD_ALL=true
fi
find . -name "release-config.yml" -not -path "./.git/*" | while read config_file; do
sample_dir=$(dirname "$config_file")
clean_dir=$(echo "$sample_dir" | sed 's|^\./||')
# Check if this specific directory should be rebuilt
SHOULD_REBUILD=false
if [ "$REBUILD_ALL" = "true" ]; then
SHOULD_REBUILD=true
echo "🔨 Processing: $config_file (rebuild all)"
elif echo "$CHANGED_FILES" | grep -q "^$clean_dir/"; then
SHOULD_REBUILD=true
echo "🔨 Processing: $config_file (changes detected in $clean_dir)"
else
echo "⏭️ Skipping: $config_file (no changes in $clean_dir)"
continue
fi
# Only process if this directory should be rebuilt
if [ "$SHOULD_REBUILD" = "true" ]; then
cd "$sample_dir"
# Check if this sample should be included
INCLUDED=$(grep "^included:" release-config.yml | sed 's/included: *//' | tr -d ' ')
if [ "$INCLUDED" != "true" ]; then
echo "⏭️ Skipping (included: $INCLUDED)"
cd - > /dev/null
continue
fi
# Extract configuration using basic shell parsing
CATEGORY=$(grep "^category:" release-config.yml | sed 's/category: *"//' | sed 's/"$//' | tr -d ' ')
FRAMEWORK=$(grep "^framework:" release-config.yml | sed 's/framework: *"//' | sed 's/"$//' | tr -d ' ')
if [ -z "$CATEGORY" ] || [ -z "$FRAMEWORK" ]; then
echo "❌ Missing category or framework in $config_file"
cd - > /dev/null
continue
fi
# Build zip filename from category and framework
ZIP_FILENAME="${CATEGORY}-${FRAMEWORK}-sample"
echo "📦 Building: $ZIP_FILENAME.zip"
echo "🏷️ Category: $CATEGORY, Framework: $FRAMEWORK"
echo "📁 Current directory: $(pwd)"
echo "📁 Artifacts directory: $ARTIFACTS_DIR"
# Create zip with absolute path to artifacts directory (this will overwrite existing)
zip -r "${ARTIFACTS_DIR}/${ZIP_FILENAME}.zip" . \
--exclude=".git/*" \
--exclude="node_modules/*" \
--exclude="__pycache__/*" \
--exclude="*.pyc" \
--exclude="*.pyo" \
--exclude="dist/*" \
--exclude="build/*" \
--exclude="venv/*" \
--exclude=".venv/*" \
--exclude=".pytest_cache/*" \
--exclude=".coverage" \
--exclude="coverage/*" \
--exclude="*.log" \
--exclude=".DS_Store" \
--exclude="Thumbs.db" \
--exclude=".idea/*" \
--exclude=".vscode/*" \
--exclude="temp/*" \
--exclude="tmp/*" \
--exclude="*.tmp" \
--exclude=".cache/*" \
--exclude=".next/*" \
--exclude="target/*" \
--exclude=".gradle/*" \
--exclude="bin/*" \
--exclude="obj/*" \
--exclude=".env" \
--exclude=".env.local" \
--exclude=".env.production" \
--exclude=".env.development" \
--exclude="release-config.yml"
# Add custom exclusions from config if they exist
if grep -q "^exclude_patterns:" release-config.yml; then
echo "📋 Adding custom exclusions from config..."
# Create a temporary zip with custom exclusions
TEMP_ZIP="${ARTIFACTS_DIR}/temp_${ZIP_FILENAME}.zip"
mv "${ARTIFACTS_DIR}/${ZIP_FILENAME}.zip" "$TEMP_ZIP"
# Extract and re-zip with custom exclusions
mkdir -p temp_extract
cd temp_extract
unzip -q "$TEMP_ZIP"
# Apply custom exclusions
while IFS= read -r line; do
if echo "$line" | grep -q "^ - "; then
pattern=$(echo "$line" | sed 's/^ - "//' | sed 's/"$//' | tr -d ' ')
if [ ! -z "$pattern" ]; then
echo " Excluding custom pattern: $pattern"
find . -name "$pattern" -delete 2>/dev/null || true
fi
fi
done < <(grep -A 20 "^exclude_patterns:" ../release-config.yml)
# Re-create zip with absolute path
zip -r "${ARTIFACTS_DIR}/${ZIP_FILENAME}.zip" .
cd ..
rm -rf temp_extract "$TEMP_ZIP"
fi
cd - > /dev/null
if [ -f "${ARTIFACTS_DIR}/${ZIP_FILENAME}.zip" ]; then
SIZE=$(du -h "${ARTIFACTS_DIR}/${ZIP_FILENAME}.zip" | cut -f1)
echo "✅ Created/Updated: ${ZIP_FILENAME}.zip ($SIZE)"
else
echo "❌ Failed to create: ${ZIP_FILENAME}.zip"
fi
fi
done
# Count artifacts AFTER the loop completes
ARTIFACT_COUNT=$(ls artifacts/*.zip 2>/dev/null | wc -l)
echo "ARTIFACT_COUNT=$ARTIFACT_COUNT" >> $GITHUB_ENV
echo "📊 Total artifacts for release: $ARTIFACT_COUNT"
# Debug: List what will be included in the release
echo "📦 Artifacts for release:"
ls -la artifacts/ || echo "No artifacts directory or files found"
- name: Security scan artifacts
if: env.SHOULD_BUILD == 'true'
run: |
echo "🔍 Performing security checks on artifacts..."
for zip_file in artifacts/*.zip; do
if [ -f "$zip_file" ]; then
echo "Scanning: $(basename "$zip_file")"
# Check for actual sensitive files (not config examples)
SENSITIVE_FILES=$(unzip -l "$zip_file" 2>/dev/null | grep -E "\.(key|pem|p12|pfx)$|/\.env$|\.env\.(local|production|development)$|secret\." | grep -v -E "\.(example|sample|template)" || true)
if [ ! -z "$SENSITIVE_FILES" ]; then
echo "⚠️ Warning: Potential sensitive files in $(basename "$zip_file"):"
echo "$SENSITIVE_FILES"
else
echo "✅ No sensitive files detected"
fi
fi
done
- name: Generate release notes
if: env.SHOULD_BUILD == 'true'
run: |
echo "📝 Generating release notes..."
cat > release_notes.md << EOF
# Quickstart Samples
This release contains the latest version of sample applications for various frameworks and quickstarts. See Assets below for downloadable zip files of each quickstart.
For more information, visit [auth0.com/ai/docs](https://auth0.com/ai/docs).
---
**Generated:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')
EOF
- name: Delete previous 'latest' release
if: env.SHOULD_BUILD == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "🗑️ Cleaning up previous 'latest' release..."
# Delete previous latest release (ignore errors if doesn't exist)
gh release delete latest --yes 2>/dev/null || echo "No previous 'latest' release found"
git push origin :refs/tags/latest 2>/dev/null || echo "No previous 'latest' tag found"
# Also clean up local tag
git tag -d latest 2>/dev/null || echo "No local 'latest' tag found"
- name: Create 'latest' release
if: env.SHOULD_BUILD == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "🚀 Creating 'latest' release..."
if [ "$ARTIFACT_COUNT" -eq 0 ]; then
echo "❌ No artifacts to release!"
exit 1
fi
echo "📦 Releasing $ARTIFACT_COUNT artifacts"
# Create the latest release
gh release create latest \
--title "Auth0 AI Sample Artifacts - Latest" \
--notes-file release_notes.md \
--latest \
artifacts/*.zip
echo "✅ Latest release created!"
echo "🔗 Your download URLs are now active:"
for zip_file in artifacts/*.zip; do
if [ -f "$zip_file" ]; then
FILENAME=$(basename "$zip_file")
echo " https://github.com/${{ github.repository }}/releases/latest/download/$FILENAME"
fi
done
- name: Skip build notification
if: env.SHOULD_BUILD == 'false'
run: |
echo "⏭️ Build skipped - no changes in directories with release-config.yml files"
echo "💡 To force a rebuild, use the manual workflow trigger"