diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml new file mode 100644 index 0000000..0016fd2 --- /dev/null +++ b/.github/workflows/auto-release.yml @@ -0,0 +1,163 @@ +# Copyright (C) 2026 Moko Consulting +# +# This file is part of a Moko Consulting project. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: GitHub.Workflow +# INGROUP: MokoStandards.Release +# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# PATH: /templates/workflows/shared/auto-release.yml +# VERSION: 04.01.00 +# BRIEF: Auto-create a GitHub Release on every push to main with version from README.md +# NOTE: Synced via bulk-repo-sync to .github/workflows/auto-release.yml in all governed repos. +# For Dolibarr (crm-module) repos, also updates $this->version in the module descriptor. + +name: Auto Release + +on: + push: + branches: + - main + - master + +permissions: + contents: write + +jobs: + release: + name: Create Release + runs-on: ubuntu-latest + # Skip bot commits (version sync, [skip ci]) to avoid infinite loops + if: >- + !contains(github.event.head_commit.message, '[skip ci]') && + github.actor != 'github-actions[bot]' + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + token: ${{ secrets.GH_TOKEN || github.token }} + fetch-depth: 0 + + - name: Extract version from README.md + id: version + run: | + VERSION=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md | head -1) + if [ -z "$VERSION" ]; then + echo "⚠️ No VERSION found in README.md — skipping release" + echo "skip=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT" + echo "skip=false" >> "$GITHUB_OUTPUT" + echo "✅ Version: $VERSION (tag: v${VERSION})" + + - name: Check if tag already exists + if: steps.version.outputs.skip != 'true' + id: tag_check + run: | + TAG="${{ steps.version.outputs.tag }}" + if git rev-parse "$TAG" >/dev/null 2>&1; then + echo "ℹ️ Tag $TAG already exists — skipping release" + echo "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + - name: Update Dolibarr module version + if: >- + steps.version.outputs.skip != 'true' && + steps.tag_check.outputs.exists != 'true' + run: | + PLATFORM="" + if [ -f ".moko-standards" ]; then + PLATFORM=$(grep -E '^platform:' .moko-standards | sed 's/.*:[[:space:]]*//' | tr -d '"') + fi + + VERSION="${{ steps.version.outputs.version }}" + + if [ "$PLATFORM" = "crm-module" ]; then + echo "📦 Dolibarr release — setting module version to '${VERSION}'" + # Update $this->version in the module descriptor (core/modules/mod*.class.php) + find . -path "*/core/modules/mod*.class.php" -exec \ + sed -i "s/\(\$this->version\s*=\s*\)['\"][^'\"]*['\"]/\1'${VERSION}'/" {} + 2>/dev/null || true + fi + + if [ "$PLATFORM" = "waas-component" ]; then + echo "📦 Joomla release — setting manifest version to '${VERSION}'" + # Update tag in Joomla XML manifest files + find . -maxdepth 2 -name "*.xml" -exec grep -l '/dev/null | while read -r manifest; do + sed -i "s|[^<]*|${VERSION}|" "$manifest" 2>/dev/null || true + done + fi + + # Commit the version update if anything changed + if ! git diff --quiet; then + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git add -A + git commit -m "chore(release): set version to ${VERSION} [skip ci]" \ + --author="github-actions[bot] " + git push + fi + + - name: Extract changelog entry + if: >- + steps.version.outputs.skip != 'true' && + steps.tag_check.outputs.exists != 'true' + id: changelog + run: | + VERSION="${{ steps.version.outputs.version }}" + + # Try to extract the section for this version from CHANGELOG.md + NOTES="" + if [ -f "CHANGELOG.md" ]; then + # Extract text between this version's heading and the next heading + NOTES=$(awk "/^##.*${VERSION}/,/^## /" CHANGELOG.md | head -50 | sed '1d;$d') + fi + + if [ -z "$NOTES" ]; then + NOTES="Release ${VERSION}" + fi + + # Write to file to avoid shell escaping issues + echo "$NOTES" > /tmp/release_notes.md + echo "✅ Release notes prepared" + + - name: Create tag and release + if: >- + steps.version.outputs.skip != 'true' && + steps.tag_check.outputs.exists != 'true' + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + run: | + TAG="${{ steps.version.outputs.tag }}" + VERSION="${{ steps.version.outputs.version }}" + + # Create the tag + git tag "$TAG" + git push origin "$TAG" + + # Create the release + gh release create "$TAG" \ + --title "${VERSION}" \ + --notes-file /tmp/release_notes.md \ + --target main + + echo "🚀 Release ${VERSION} created: $TAG" + + - name: Summary + if: steps.version.outputs.skip != 'true' + run: | + VERSION="${{ steps.version.outputs.version }}" + TAG="${{ steps.version.outputs.tag }}" + if [ "${{ steps.tag_check.outputs.exists }}" = "true" ]; then + echo "## ℹ️ Release — ${VERSION}" >> $GITHUB_STEP_SUMMARY + echo "Tag \`${TAG}\` already exists — no new release created." >> $GITHUB_STEP_SUMMARY + else + echo "## 🚀 Release — ${VERSION}" >> $GITHUB_STEP_SUMMARY + echo "Created tag \`${TAG}\` and GitHub Release." >> $GITHUB_STEP_SUMMARY + fi