ci: add PR validation workflow with Conventional Commits check
Some checks failed
Pull Request Validation / validate-pr-title (pull_request) Has been cancelled
Pull Request Validation / validate-docker (pull_request) Has been cancelled
Pull Request Validation / build-test (pull_request) Has been cancelled
Pull Request Validation / check-files (pull_request) Has been cancelled

- Add .gitea/workflows/pr-validation.yml with 4 validation jobs
- Validate PR titles follow Conventional Commits format
- Check Dockerfile and nginx.conf syntax
- Run integration tests (build image, test container, verify pages load)
- Verify required files exist and HTTrack artifacts excluded
- Update copilot-instructions.md with PR validation details
This commit is contained in:
Pat Teruel
2025-12-30 21:24:27 +08:00
parent d6d3fe4d7f
commit 499d44ba38
2 changed files with 216 additions and 2 deletions

View File

@@ -0,0 +1,196 @@
name: Pull Request Validation
on:
pull_request:
types: [opened, edited, synchronize, reopened]
jobs:
validate-pr-title:
runs-on: ubuntu-latest
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: <type>(optional scope): <description>"
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: ubuntu-latest
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: ubuntu-latest
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: ubuntu-latest
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"

View File

@@ -76,13 +76,31 @@ docker tag karaokepedia:latest your-registry/karaokepedia:latest
docker push your-registry/karaokepedia:latest
```
### CI/CD Pipeline (Gitea Actions)
### CI/CD Pipelines (Gitea Actions)
#### Build & Deploy (`.gitea/workflows/build.yml`)
- **Trigger**: Push to `main` branch or manual dispatch
- **Workflow**: `.gitea/workflows/build.yml` (GitHub Actions-compatible syntax)
- **Steps**: Checkout → Setup Buildx → Login to registry → Build & push → Output digest
- **Tags**: `:latest` and `:main-<commit-sha>`
- **Registry**: Configure via secrets (DOCKER_USERNAME/DOCKER_PASSWORD for Docker Hub, or adapt for Gitea registry)
#### PR Validation (`.gitea/workflows/pr-validation.yml`)
- **Trigger**: Pull request opened, edited, synchronized, or reopened
- **Jobs**:
- `validate-pr-title`: Enforces [Conventional Commits](https://www.conventionalcommits.org/) format
- `validate-docker`: Checks Dockerfile, nginx.conf, and .dockerignore syntax
- `build-test`: Builds image and tests container starts, pages load, assets accessible
- `check-files`: Verifies required files exist, HTTrack artifacts excluded
**Conventional Commit Types**: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`, `ci`, `build`, `revert`
**Example PR titles**:
-`feat: add user authentication`
-`fix(docker): correct nginx config path`
-`docs: update README with deployment steps`
-`Added new feature` (missing type)
-`Update files` (not descriptive)
### Registry Configuration
Edit `.gitea/workflows/build.yml` and uncomment the appropriate registry:
- **Docker Hub** (default): Uses `DOCKER_USERNAME` and `DOCKER_PASSWORD` secrets