name: Pull Request Validation on: pull_request: types: [opened, edited, synchronize, reopened] jobs: validate-pr-title: runs-on: linux steps: - name: Validate PR title follows Conventional Commits run: | PR_TITLE="${{ github.event.pull_request.title }}" echo "Validating PR title: $PR_TITLE" # Conventional Commits pattern: type(scope): description # Types: feat, fix, docs, style, refactor, perf, test, chore, ci, build, revert PATTERN="^(feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert)(\(.+\))?: .+" if echo "$PR_TITLE" | grep -qE "$PATTERN"; then echo "✅ PR title follows Conventional Commits format" exit 0 else echo "❌ PR title does not follow Conventional Commits format" echo "" echo "Expected format: (optional scope): " echo "" echo "Valid types:" echo " - feat: A new feature" echo " - fix: A bug fix" echo " - docs: Documentation only changes" echo " - style: Code style changes (formatting, missing semi-colons, etc)" echo " - refactor: Code change that neither fixes a bug nor adds a feature" echo " - perf: Performance improvements" echo " - test: Adding or updating tests" echo " - chore: Changes to build process or auxiliary tools" echo " - ci: CI/CD configuration changes" echo " - build: Changes to build system or dependencies" echo " - revert: Reverts a previous commit" echo "" echo "Examples:" echo " - feat: add user authentication" echo " - fix(api): handle null pointer exception" echo " - docs: update installation instructions" echo " - ci: add Docker build workflow" exit 1 fi validate-docker: runs-on: linux steps: - name: Checkout code uses: actions/checkout@v4 - name: Validate Dockerfile syntax run: | if [ -f "Dockerfile" ]; then echo "✅ Dockerfile exists" # Basic syntax check by attempting to parse it docker build --no-cache --target="" -f Dockerfile . 2>&1 | head -5 || true echo "✅ Dockerfile syntax appears valid" else echo "❌ Dockerfile not found" exit 1 fi - name: Check .dockerignore exists run: | if [ -f ".dockerignore" ]; then echo "✅ .dockerignore exists" else echo "⚠️ Warning: .dockerignore not found (recommended)" fi - name: Validate nginx config run: | if [ -f "nginx.conf" ]; then echo "✅ nginx.conf exists" # Test nginx config syntax using alpine nginx image docker run --rm -v "$(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro" nginx:alpine nginx -t echo "✅ nginx.conf syntax is valid" else echo "⚠️ Warning: nginx.conf not found" fi build-test: runs-on: linux steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build Docker image (no push) uses: docker/build-push-action@v5 with: context: . push: false tags: karaokepedia:pr-${{ github.event.pull_request.number }} cache-from: type=gha cache-to: type=gha,mode=max - name: Test container starts run: | docker build -t karaokepedia:test . CONTAINER_ID=$(docker run -d -p 8080:80 karaokepedia:test) echo "Container started: $CONTAINER_ID" # Wait for container to be healthy echo "Waiting for container to start..." sleep 5 # Test homepage if curl -f -s -o /dev/null http://localhost:8080/; then echo "✅ Homepage loads successfully" else echo "❌ Homepage failed to load" docker logs $CONTAINER_ID exit 1 fi # Test songs page if curl -f -s -o /dev/null http://localhost:8080/songs.html; then echo "✅ Songs page loads successfully" else echo "❌ Songs page failed to load" exit 1 fi # Test assets if curl -f -s -o /dev/null http://localhost:8080/assets/application-b504973bc673ef9f09352588c7d791495f9fa7b652e6bf0d71ea86a094aa4007.css; then echo "✅ CSS assets load successfully" else echo "❌ CSS assets failed to load" exit 1 fi # Cleanup docker stop $CONTAINER_ID docker rm $CONTAINER_ID echo "✅ All container tests passed" check-files: runs-on: linux steps: - name: Checkout code uses: actions/checkout@v4 - name: Check required files exist run: | REQUIRED_FILES=( "karaoke.karaniwan.org/index.html" "karaoke.karaniwan.org/songs.html" "karaoke.karaniwan.org/assets/application-b504973bc673ef9f09352588c7d791495f9fa7b652e6bf0d71ea86a094aa4007.css" "Dockerfile" "nginx.conf" ".dockerignore" ) MISSING_FILES=() for file in "${REQUIRED_FILES[@]}"; do if [ -f "$file" ]; then echo "✅ $file exists" else echo "❌ $file is missing" MISSING_FILES+=("$file") fi done if [ ${#MISSING_FILES[@]} -gt 0 ]; then echo "" echo "❌ Missing required files:" printf ' - %s\n' "${MISSING_FILES[@]}" exit 1 fi echo "" echo "✅ All required files present" - name: Check for HTTrack artifacts in content run: | echo "Checking that HTTrack artifacts are not included in Docker context..." # These should be in .dockerignore if [ -d "hts-cache" ]; then if grep -q "hts-cache" .dockerignore; then echo "✅ hts-cache/ directory excluded in .dockerignore" else echo "❌ hts-cache/ should be in .dockerignore" exit 1 fi fi echo "✅ HTTrack artifacts properly excluded"