Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions .github/workflows/composer-version-guard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
name: Guard composer.json version

on:
pull_request:
branches: [develop]

env:
GITHUB_TOKEN: ${{ secrets.GH_AUTOMATION_TOKEN }}

jobs:
no-manual-version-bump:
name: Disallow manual composer.json version bumps
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # zum Kommentieren/Löschen
issues: write # PR-Kommentare sind Issue-Kommentare

env:
GH_TOKEN: ${{ github.token }} # gh CLI Auth
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
BASE_REF: ${{ github.base_ref }}

steps:
- name: Checkout (current PR head)
uses: actions/checkout@v6

- name: Ensure jq and gh are available
run: |
jq --version
gh --version

- name: Compare composer.json version via jq
id: check
run: |
set -euo pipefail

# composer.json im Base-Branch RAW abrufen (stabiler als Git-Fetch)
base_json="$(gh api -H 'Accept: application/vnd.github.raw' \
repos/${REPO}/contents/composer.json?ref=${BASE_REF} || true)"

# Falls composer.json im Base nicht existiert (Mono-Repos, Erst-Add etc.)
if [ -z "${base_json}" ]; then
base_ver=""
else
base_ver="$(printf '%s' "${base_json}" | jq -r '.version // empty')"
fi

# Head-Version aus dem Arbeitsverzeichnis
head_ver="$(jq -r '.version // empty' composer.json)"

echo "Base version: ${base_ver}"
echo "Head version: ${head_ver}"

if [ "${base_ver}" != "${head_ver}" ]; then
echo "has_version_change=true" >> "$GITHUB_OUTPUT"
else
echo "has_version_change=false" >> "$GITHUB_OUTPUT"
fi

- name: Upsert PR comment if version changed
if: steps.check.outputs.has_version_change == 'true'
run: |
set -euo pipefail
MARK="<!-- composer-version-guard -->"

# Prüfen, ob schon ein Kommentar mit unserem Marker existiert
existing_ids=$(gh api --paginate \
repos/${REPO}/issues/${PR_NUMBER}/comments \
--jq "[ .[] | select( (.body // \"\") | contains(\"${MARK}\") ) | .id ] | .[]" || true)

# Kommentar-Text vorbereiten (mit Marker, damit wir ihn später sicher finden/löschen)
cat > /tmp/comment.md <<'EOF'
<!-- composer-version-guard -->
⚠️ **Bitte die `version` in `composer.json` nicht manuell ändern.**

Releases werden automatisch erstellt (.github/workflows/release.yml).
Dieser PR ändert die Eigenschaft `version` – bitte die Änderung zurücknehmen.
Sobald die Version wieder unverändert ist, wird dieser Hinweis automatisch entfernt.
EOF

if [ -z "${existing_ids}" ]; then
# Neuen Kommentar erstellen
gh pr comment "${PR_NUMBER}" --body-file /tmp/comment.md
else
# Optional: vorhandene(n) Kommentar auf den aktuellen Text setzen (idempotent)
for id in ${existing_ids}; do
gh api \
--method PATCH \
"repos/${REPO}/issues/comments/${id}" \
-f body="@/tmp/comment.md"
done
fi

- name: Remove previous PR comments when resolved
if: steps.check.outputs.has_version_change != 'true'
run: |
set -euo pipefail
MARK="<!-- composer-version-guard -->"

# Alle Kommentare mit unserem Marker einsammeln
ids=$(gh api --paginate \
repos/${REPO}/issues/${PR_NUMBER}/comments \
--jq "[ .[] | select( (.body // \"\") | contains(\"${MARK}\") ) | .id ] | .[]" || true)

if [ -n "${ids}" ]; then
echo "Removing ${ids}..."
for id in ${ids}; do
gh api -X DELETE "repos/${REPO}/issues/comments/${id}" || true
done
else
echo "No previous guard comments to remove."
fi

- name: Fail the job if version changed
if: steps.check.outputs.has_version_change == 'true'
run: |
echo "::error::composer.json enthält eine Änderung an \"version\". Releases erfolgen automatisch – bitte diese Änderung entfernen."
exit 1

- name: Success
if: steps.check.outputs.has_version_change != 'true'
run: |
echo "OK: Keine manuelle Änderung an composer.json:version."
83 changes: 83 additions & 0 deletions .github/workflows/release-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Sync release artifacts to develop

on:
workflow_run:
workflows: ["Create release"]
types: [completed]

permissions:
contents: write

# Cannot use overall env because then the sync fails with the wrong user

jobs:
sync-to-develop:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest

steps:
- name: Checkout (full history)
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.GH_AUTOMATION_TOKEN }}

- name: Configure git & auth
run: |
git config user.name "${GIT_AUTHOR_NAME}"
git config user.email "${GIT_AUTHOR_EMAIL}"
git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git"

- name: Fetch branches (heads only, no tags; avoid ambiguous refs)
run: |
set -euo pipefail

echo "Fetching main and develop branches..."
git fetch --no-tags --prune origin \
+refs/heads/main:refs/remotes/origin/main \
+refs/heads/develop:refs/remotes/origin/develop

- name: Sync composer.json & CHANGELOG.md from main to develop
id: sync
run: |
set -euo pipefail

echo "Configuring git user for pushing changes..."
git config user.email "websolutions@netlogix.de"
git config user.name "netlogix-bot"

# Prüfe, ob sich genau diese Dateien zwischen main und develop unterscheiden
echo "Checking for differences in composer.json and CHANGELOG.md between main and develop..."
if git diff --quiet \
refs/remotes/origin/develop..refs/remotes/origin/main \
-- composer.json CHANGELOG.md; then
echo "nothing_to_sync=true" >> "$GITHUB_OUTPUT"
exit 0
fi

# Wechsle auf lokalen develop, der auf remote/develop basiert
echo "Checking out develop branch..."
git checkout -B develop refs/remotes/origin/develop

# Übernehme die zwei Dateien exakt aus main
echo "Checking out composer.json and CHANGELOG.md from main branch..."
git checkout refs/remotes/origin/main -- composer.json CHANGELOG.md

# Stage & Commit mit [skip ci], damit keine Workflows feuern
echo "Committing changes..."
git add composer.json CHANGELOG.md
git commit -m "[release-sync] chore: sync composer.json & CHANGELOG.md from main to develop [skip ci]" || {
echo "nothing_to_sync=true" >> "$GITHUB_OUTPUT"
exit 0
}

echo "Pushing changes to develop branch..."
git push origin HEAD:develop
echo "nothing_to_sync=false" >> "$GITHUB_OUTPUT"
echo "done"
env:
GITHUB_TOKEN: ${{ secrets.GH_AUTOMATION_TOKEN }}

- name: Done
if: steps.sync.outputs.nothing_to_sync == 'true'
run: echo "Nichts zu syncen (composer.json/CHANGELOG.md identisch)."
29 changes: 29 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Create release

on:
push:
branches:
- main

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install Dependencies
run: npm install
- name: Semantic Release
uses: cycjimmy/semantic-release-action@v6
id: semantic # Need an `id` for output variables
env:
GITHUB_TOKEN: ${{ secrets.GH_AUTOMATION_TOKEN }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
/.idea
vendor
composer.lock

/node_modules/
31 changes: 31 additions & 0 deletions .releaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"branches": [
"main",
],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md"
}
],
"@iwavesmedia/semantic-release-composer",
[
"@semantic-release/git",
{
"assets": [
"composer.json",
"CHANGELOG.md"
]
}
],
[
"@semantic-release/github",
{
"successCommentCondition": "<% return issue.pull_request; %>"
}
]
]
}
29 changes: 29 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"devDependencies": {
"@iwavesmedia/semantic-release-composer": "^1.0.0"
}
}