190 lines
6.4 KiB
YAML
190 lines
6.4 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main, develop]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
lint-php:
|
|
name: PHP Syntax Check
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Setup PHP
|
|
uses: shivammathur/setup-php@v2
|
|
with:
|
|
php-version: '8.2'
|
|
extensions: pdo_sqlite, curl, mbstring
|
|
|
|
- name: Check PHP syntax
|
|
run: |
|
|
find api/ -name '*.php' -exec php -l {} \;
|
|
|
|
lint-js:
|
|
name: JavaScript Lint
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Check JS syntax
|
|
run: |
|
|
node -c assets/js/app.js
|
|
|
|
docker-build:
|
|
name: Docker Build Test
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Build Docker image
|
|
run: docker build -t evershelf-test .
|
|
|
|
- name: Test container starts
|
|
run: |
|
|
docker run -d --name test-evershelf -p 8080:80 evershelf-test
|
|
sleep 5
|
|
curl -f http://localhost:8080/ || exit 1
|
|
docker stop test-evershelf
|
|
|
|
validate-translations:
|
|
name: Validate Translation Files
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Validate JSON syntax
|
|
run: |
|
|
for f in translations/*.json; do
|
|
echo "Checking $f..."
|
|
python3 -c "import json; json.load(open('$f'))" || exit 1
|
|
done
|
|
echo "All translation files valid."
|
|
|
|
- name: Check translation completeness
|
|
run: |
|
|
python3 -c "
|
|
import json, sys
|
|
base = json.load(open('translations/it.json'))
|
|
base_keys = set(base.keys())
|
|
ok = True
|
|
import glob
|
|
for f in glob.glob('translations/*.json'):
|
|
if 'it.json' in f:
|
|
continue
|
|
lang = json.load(open(f))
|
|
lang_keys = set(lang.keys())
|
|
missing = base_keys - lang_keys
|
|
if missing:
|
|
print(f'{f}: {len(missing)} missing keys')
|
|
for k in sorted(missing)[:10]:
|
|
print(f' - {k}')
|
|
if len(missing) > 10:
|
|
print(f' ... and {len(missing)-10} more')
|
|
else:
|
|
print(f'{f}: complete ✓')
|
|
"
|
|
|
|
# ── Auto-merge develop → main ────────────────────────────────────────────
|
|
# Runs automatically after ALL checks pass on develop.
|
|
# You never need to merge manually again — just push to develop.
|
|
auto-merge-to-main:
|
|
name: Auto-merge develop → main
|
|
needs: [lint-php, lint-js, docker-build, validate-translations]
|
|
if: github.ref == 'refs/heads/develop'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- name: Checkout (full history)
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
# Always use the built-in GITHUB_TOKEN for checkout (read-only fetch).
|
|
# WORKFLOW_PAT is only needed for the push step below.
|
|
token: ${{ github.token }}
|
|
|
|
- name: Configure git bot identity
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
- name: Merge develop → main
|
|
run: |
|
|
# WORKFLOW_PAT (classic PAT with repo+workflow scopes) is required to
|
|
# push commits that touch .github/workflows/ files.
|
|
# Falls back to GITHUB_TOKEN for non-workflow pushes.
|
|
PUSH_TOKEN="${{ secrets.WORKFLOW_PAT }}"
|
|
if [ -z "$PUSH_TOKEN" ]; then PUSH_TOKEN="${{ github.token }}"; fi
|
|
git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${{ github.repository }}.git"
|
|
LAST=$(git log --oneline -1 origin/develop)
|
|
git checkout main
|
|
git pull --ff-only origin main
|
|
git merge --no-ff origin/develop \
|
|
-m "chore: auto-merge develop → main
|
|
|
|
Triggered by: $LAST"
|
|
git push origin main
|
|
|
|
# ── Auto-create GitHub Release on main ───────────────────────────────────
|
|
# Runs after auto-merge succeeds. Reads version from index.html,
|
|
# creates a release tag vX.Y.Z if it doesn't exist yet.
|
|
# This powers the in-app update badge for self-hosted users.
|
|
create-release:
|
|
name: Create GitHub Release
|
|
needs: [auto-merge-to-main]
|
|
if: github.ref == 'refs/heads/develop'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- name: Checkout main
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: main
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract version from index.html
|
|
id: version
|
|
run: |
|
|
VER=$(grep -oP 'header-version">v\K[\d.]+' index.html | head -1)
|
|
echo "version=v${VER}" >> $GITHUB_OUTPUT
|
|
echo "Detected version: v${VER}"
|
|
|
|
- name: Check if tag already exists
|
|
id: tag_check
|
|
run: |
|
|
if git ls-remote --tags origin "refs/tags/${{ steps.version.outputs.version }}" | grep -q .; then
|
|
echo "exists=true" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "exists=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Read CHANGELOG entry for this version
|
|
id: changelog
|
|
if: steps.tag_check.outputs.exists == 'false'
|
|
run: |
|
|
VER="${{ steps.version.outputs.version }}"
|
|
# Extract the section for this version from CHANGELOG.md
|
|
BODY=$(awk "/^## \[?${VER#v}\]?|^## ${VER}/,/^## [0-9]/" CHANGELOG.md | head -50 | tail -n +1 | grep -v "^## [0-9]" || true)
|
|
if [ -z "$BODY" ]; then
|
|
BODY="See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) for details."
|
|
fi
|
|
# Multiline output
|
|
echo "body<<EOF" >> $GITHUB_OUTPUT
|
|
echo "$BODY" >> $GITHUB_OUTPUT
|
|
echo "EOF" >> $GITHUB_OUTPUT
|
|
|
|
- name: Create release
|
|
if: steps.tag_check.outputs.exists == 'false'
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: ${{ steps.version.outputs.version }}
|
|
name: "EverShelf ${{ steps.version.outputs.version }}"
|
|
body: ${{ steps.changelog.outputs.body }}
|
|
target_commitish: main
|
|
make_latest: true
|