fix: refuse Caddy /load over a config owned by another instance (#191) #441
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build & Release | |
| on: | |
| push: | |
| branches: [master] | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| REGISTRY: ghcr.io | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| permissions: | |
| contents: write | |
| packages: write | |
| jobs: | |
| security-gate: | |
| name: Security Gate | |
| runs-on: ubuntu-latest | |
| if: "!startsWith(github.event.head_commit.message, 'chore: bump version')" | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| registry-url: https://npm.pkg.github.com/ | |
| scope: '@callmetechie' | |
| - run: npm ci | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} | |
| - name: npm audit (high/critical) | |
| run: | | |
| CRITICAL=$(npm audit --json 2>/dev/null | node -e "try{const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));console.log((d.metadata?.vulnerabilities?.critical||0))}catch{console.log(0)}") | |
| if [ "$CRITICAL" -gt 0 ]; then echo "::error::Critical vulnerabilities found"; exit 1; fi | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| registry-url: https://npm.pkg.github.com/ | |
| scope: '@callmetechie' | |
| - run: npm ci | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} | |
| - run: npm test | |
| env: | |
| NODE_ENV: test | |
| release: | |
| needs: [test, security-gate] | |
| runs-on: ubuntu-latest | |
| # Skip version-bump commits to prevent infinite loop | |
| if: "!startsWith(github.event.head_commit.message, 'chore: bump version')" | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| - name: Determine version bump | |
| id: bump | |
| env: | |
| COMMIT_MSG: ${{ github.event.head_commit.message }} | |
| run: | | |
| CURRENT=$(node -p "require('./package.json').version") | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" | |
| FIRST_LINE=$(echo "$COMMIT_MSG" | head -1) | |
| if echo "$FIRST_LINE" | grep -qE "^feat(\(.+\))?:"; then | |
| MINOR=$((MINOR + 1)) | |
| PATCH=0 | |
| BUMP="minor" | |
| else | |
| PATCH=$((PATCH + 1)) | |
| BUMP="patch" | |
| fi | |
| NEW="${MAJOR}.${MINOR}.${PATCH}" | |
| echo "current=$CURRENT" >> "$GITHUB_OUTPUT" | |
| echo "new=$NEW" >> "$GITHUB_OUTPUT" | |
| echo "bump=$BUMP" >> "$GITHUB_OUTPUT" | |
| echo "tag=v$NEW" >> "$GITHUB_OUTPUT" | |
| echo "Version: $CURRENT → $NEW ($BUMP)" | |
| - name: Check if tag already exists | |
| id: check_tag | |
| env: | |
| TAG: ${{ steps.bump.outputs.tag }} | |
| run: | | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "exists=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "exists=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Update version in package.json | |
| if: steps.check_tag.outputs.exists == 'false' | |
| env: | |
| NEW_VERSION: ${{ steps.bump.outputs.new }} | |
| run: npm version "$NEW_VERSION" --no-git-tag-version | |
| - name: Update CHANGELOG.md | |
| if: steps.check_tag.outputs.exists == 'false' | |
| env: | |
| NEW_VERSION: ${{ steps.bump.outputs.new }} | |
| BUMP_TYPE: ${{ steps.bump.outputs.bump }} | |
| COMMIT_MSG: ${{ github.event.head_commit.message }} | |
| run: | | |
| FIRST_LINE=$(echo "$COMMIT_MSG" | head -1) | |
| DATE=$(date +%Y-%m-%d) | |
| if echo "$FIRST_LINE" | grep -qE "^feat"; then | |
| SECTION="Features" | |
| ENTRY=$(echo "$FIRST_LINE" | sed 's/^feat[^:]*: //') | |
| elif echo "$FIRST_LINE" | grep -qE "^fix"; then | |
| SECTION="Fixes" | |
| ENTRY=$(echo "$FIRST_LINE" | sed 's/^fix[^:]*: //') | |
| elif echo "$FIRST_LINE" | grep -qE "^docs"; then | |
| SECTION="Dokumentation" | |
| ENTRY=$(echo "$FIRST_LINE" | sed 's/^docs[^:]*: //') | |
| else | |
| SECTION="Änderungen" | |
| ENTRY=$(echo "$FIRST_LINE" | sed 's/^[a-z]*[^:]*: //') | |
| fi | |
| NEW_BLOCK="## [$NEW_VERSION] — $DATE | |
| ### $SECTION | |
| - $ENTRY" | |
| # Remove leading whitespace from heredoc | |
| NEW_BLOCK=$(echo "$NEW_BLOCK" | sed 's/^ //') | |
| if [ -f CHANGELOG.md ]; then | |
| TEMP=$(mktemp) | |
| awk -v block="$NEW_BLOCK" ' | |
| /^# Changelog/ { print; print ""; print block; print ""; print "---"; next } | |
| { print } | |
| ' CHANGELOG.md > "$TEMP" | |
| mv "$TEMP" CHANGELOG.md | |
| fi | |
| - name: Commit version bump | |
| if: steps.check_tag.outputs.exists == 'false' | |
| env: | |
| TAG: ${{ steps.bump.outputs.tag }} | |
| NEW_VERSION: ${{ steps.bump.outputs.new }} | |
| run: | | |
| git config user.name "github-actions" | |
| git config user.email "github-actions@github.com" | |
| git add package.json package-lock.json CHANGELOG.md 2>/dev/null || true | |
| git add package.json | |
| git commit -m "chore: bump version to $NEW_VERSION" | |
| git tag "$TAG" | |
| git push origin master --tags | |
| # ─── GHCR: Build & Push ─────────────────────────── | |
| - name: Set image name | |
| if: steps.check_tag.outputs.exists == 'false' | |
| run: echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV" | |
| - uses: docker/login-action@v4 | |
| if: steps.check_tag.outputs.exists == 'false' | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: docker/build-push-action@v7 | |
| if: steps.check_tag.outputs.exists == 'false' | |
| with: | |
| context: . | |
| push: true | |
| build-args: | | |
| NODE_AUTH_TOKEN=${{ secrets.GH_PACKAGES_TOKEN }} | |
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.bump.outputs.new }},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest | |
| # ─── Release: Offline-Paket ─────────────────────── | |
| - name: Build image for offline package | |
| if: steps.check_tag.outputs.exists == 'false' | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} | |
| run: docker build --build-arg "NODE_AUTH_TOKEN=$NODE_AUTH_TOKEN" -t gatecontrol:latest . | |
| - name: Export image | |
| if: steps.check_tag.outputs.exists == 'false' | |
| run: docker save gatecontrol:latest | gzip > gatecontrol-image.tar.gz | |
| - name: Create GitHub Release | |
| if: steps.check_tag.outputs.exists == 'false' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.bump.outputs.tag }} | |
| name: GateControl ${{ steps.bump.outputs.tag }} | |
| generate_release_notes: true | |
| files: | | |
| gatecontrol-image.tar.gz | |
| deploy/docker-compose.yml | |
| deploy/setup.sh | |
| .env.example |