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
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:
196
.gitea/workflows/pr-validation.yml
Normal file
196
.gitea/workflows/pr-validation.yml
Normal 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"
|
||||
22
.github/copilot-instructions.md
vendored
22
.github/copilot-instructions.md
vendored
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user