diff --git a/.mokogitea/workflows/auto-bump.yml b/.mokogitea/workflows/auto-bump.yml index fc97f73..12bbf0b 100644 --- a/.mokogitea/workflows/auto-bump.yml +++ b/.mokogitea/workflows/auto-bump.yml @@ -41,54 +41,9 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: token: ${{ secrets.MOKOGITEA_TOKEN }} - fetch-depth: 2 - - - name: Check for source changes - id: source-check - env: - MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - run: | - MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}" - REPO="${{ github.repository }}" - - # Fetch platform and entry_point from first-class repo metadata API - METADATA=$(curl -sf -H "Authorization: token ${MOKOGITEA_TOKEN}" \ - "${MOKOGITEA_URL}/api/v1/repos/${REPO}/manifest" 2>/dev/null || echo "{}") - PLATFORM=$(echo "$METADATA" | grep -oP '"platform"\s*:\s*"\K[^"]+' || true) - SOURCE_DIR=$(echo "$METADATA" | grep -oP '"entry_point"\s*:\s*"\K[^"]+' || true) - - # Default source dirs by platform if entry_point not set - if [ -z "$SOURCE_DIR" ]; then - case "$PLATFORM" in - joomla) SOURCE_DIR="src/ source/ htdocs/" ;; - dolibarr) SOURCE_DIR="src/ htdocs/" ;; - *) SOURCE_DIR="" ;; - esac - fi - - # If no platform or source dir, always bump (generic repos) - if [ -z "$SOURCE_DIR" ]; then - echo "has_source_changes=true" >> "$GITHUB_OUTPUT" - echo "No platform metadata — defaulting to bump" - exit 0 - fi - - # Check if the last commit touched any source files - CHANGED=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || true) - HAS_CHANGES=false - for DIR in $SOURCE_DIR; do - DIR="${DIR%/}" - if echo "$CHANGED" | grep -q "^${DIR}/"; then - HAS_CHANGES=true - break - fi - done - - echo "has_source_changes=$HAS_CHANGES" >> "$GITHUB_OUTPUT" - echo "Platform: ${PLATFORM:-generic}, Source: ${SOURCE_DIR}, Changes: ${HAS_CHANGES}" + fetch-depth: 1 - name: Setup mokocli tools - if: steps.source-check.outputs.has_source_changes == 'true' run: | if ! command -v composer &> /dev/null; then sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1 @@ -104,7 +59,6 @@ jobs: fi - name: Bump version - if: steps.source-check.outputs.has_source_changes == 'true' run: | php ${MOKO_CLI}/version_auto_bump.php \ --path . --branch "${GITHUB_REF_NAME}" \ diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml index c8a1257..5865324 100644 --- a/.mokogitea/workflows/auto-release.yml +++ b/.mokogitea/workflows/auto-release.yml @@ -27,7 +27,7 @@ name: "Universal: Build & Release" on: pull_request: - types: [opened, closed] + types: [opened, synchronize, closed] branches: - main paths-ignore: @@ -66,6 +66,7 @@ jobs: runs-on: release if: >- (github.event.action == 'opened' && github.event.pull_request.merged != true) || + (github.event.action == 'synchronize' && github.event.pull_request.merged != true) || (github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc') steps: diff --git a/.mokogitea/workflows/ci-generic.yml b/.mokogitea/workflows/ci-generic.yml index 18ae768..92d2685 100644 --- a/.mokogitea/workflows/ci-generic.yml +++ b/.mokogitea/workflows/ci-generic.yml @@ -13,6 +13,12 @@ name: "Generic: Project CI" on: + pull_request: + branches: + - main + - dev + - dev/** + - rc/** workflow_dispatch: permissions: diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml index 4ab9bf2..efb3d1b 100644 --- a/.mokogitea/workflows/pre-release.yml +++ b/.mokogitea/workflows/pre-release.yml @@ -7,7 +7,7 @@ # INGROUP: mokocli.Release # REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli # PATH: /templates/workflows/universal/pre-release.yml.template -# VERSION: 05.01.00 +# VERSION: 05.02.00 # BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches name: "Universal: Pre-Release" @@ -20,6 +20,7 @@ on: - 'patch/**' - 'hotfix/**' - 'bugfix/**' + - 'chore/**' - alpha - beta - rc @@ -39,7 +40,7 @@ permissions: contents: write env: - MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }} GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }} @@ -55,57 +56,16 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 token: ${{ secrets.MOKOGITEA_TOKEN }} ref: ${{ github.ref_name }} + submodules: recursive - - name: Check for source changes - id: source-check - if: github.event_name == 'push' - env: - MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} + - name: Update submodules to main run: | - MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}" - REPO="${{ github.repository }}" - - # Fetch platform and entry_point from first-class repo metadata API - METADATA=$(curl -sf -H "Authorization: token ${MOKOGITEA_TOKEN}" \ - "${MOKOGITEA_URL}/api/v1/repos/${REPO}/manifest" 2>/dev/null || echo "{}") - PLATFORM=$(echo "$METADATA" | grep -oP '"platform"\s*:\s*"\K[^"]+' || true) - SOURCE_DIR=$(echo "$METADATA" | grep -oP '"entry_point"\s*:\s*"\K[^"]+' || true) - - # Default source dirs by platform if entry_point not set - if [ -z "$SOURCE_DIR" ]; then - case "$PLATFORM" in - joomla) SOURCE_DIR="src/ source/ htdocs/" ;; - dolibarr) SOURCE_DIR="src/ htdocs/" ;; - *) SOURCE_DIR="" ;; - esac - fi - - # If no platform or source dir, always build (generic repos) - if [ -z "$SOURCE_DIR" ]; then - echo "has_source_changes=true" >> "$GITHUB_OUTPUT" - echo "No platform metadata — defaulting to build" - exit 0 - fi - - # Check if the last commit touched any source files - CHANGED=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || true) - HAS_CHANGES=false - for DIR in $SOURCE_DIR; do - DIR="${DIR%/}" - if echo "$CHANGED" | grep -q "^${DIR}/"; then - HAS_CHANGES=true - break - fi - done - - echo "has_source_changes=$HAS_CHANGES" >> "$GITHUB_OUTPUT" - echo "Platform: ${PLATFORM:-generic}, Source: ${SOURCE_DIR}, Changes: ${HAS_CHANGES}" + git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true - name: Setup mokocli tools - if: github.event_name == 'workflow_dispatch' || steps.source-check.outputs.has_source_changes == 'true' env: MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting @@ -127,16 +87,26 @@ jobs: fi - name: Detect platform - if: github.event_name == 'workflow_dispatch' || steps.source-check.outputs.has_source_changes == 'true' id: platform run: | # Auto-detect and update platform if not set in manifest php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true php ${MOKO_CLI}/manifest_read.php --path . --github-output + - name: Check platform eligibility (Joomla only) + id: eligibility + run: | + PLATFORM="${{ steps.platform.outputs.platform }}" + if [[ "$PLATFORM" == joomla* ]] || [[ "$PLATFORM" == "joomla" ]]; then + echo "proceed=true" >> "$GITHUB_OUTPUT" + else + echo "proceed=false" >> "$GITHUB_OUTPUT" + echo "::notice::Platform '$PLATFORM' — non-Joomla, skipping pre-release auto-bump" + fi + - name: Resolve metadata and bump version - if: github.event_name == 'workflow_dispatch' || steps.source-check.outputs.has_source_changes == 'true' id: meta + if: steps.eligibility.outputs.proceed == 'true' run: | # Auto-detect stability from branch name on push, or use input on dispatch if [ "${{ github.event_name }}" = "push" ]; then @@ -212,23 +182,23 @@ jobs: echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ===" - name: Create release - if: github.event_name == 'workflow_dispatch' || steps.source-check.outputs.has_source_changes == 'true' id: release + if: steps.eligibility.outputs.proceed == 'true' run: | TAG="${{ steps.meta.outputs.tag }}" VERSION="${{ steps.meta.outputs.version }}" - API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" php ${MOKO_CLI}/release_create.php \ --path . --version "$VERSION" --tag "$TAG" \ --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \ --repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease - name: Update release notes from CHANGELOG.md - if: github.event_name == 'workflow_dispatch' || steps.source-check.outputs.has_source_changes == 'true' + if: steps.eligibility.outputs.proceed == 'true' run: | TAG="${{ steps.meta.outputs.tag }}" VERSION="${{ steps.meta.outputs.version }}" - API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" # Extract [Unreleased] section from changelog (everything between [Unreleased] and next ## heading) if [ -f "CHANGELOG.md" ]; then @@ -260,12 +230,12 @@ jobs: fi - name: Build package and upload - if: github.event_name == 'workflow_dispatch' || steps.source-check.outputs.has_source_changes == 'true' id: package + if: steps.eligibility.outputs.proceed == 'true' run: | VERSION="${{ steps.meta.outputs.version }}" TAG="${{ steps.meta.outputs.tag }}" - API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" php ${MOKO_CLI}/release_package.php \ --path . --version "$VERSION" --tag "$TAG" \ --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \ @@ -275,10 +245,10 @@ jobs: # No need to build, commit, or sync updates.xml from workflows - name: "Delete lesser pre-release channels (cascade)" - if: github.event_name == 'workflow_dispatch' || steps.source-check.outputs.has_source_changes == 'true' + if: steps.eligibility.outputs.proceed == 'true' continue-on-error: true run: | - API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" php ${MOKO_CLI}/release_cascade.php \ diff --git a/.mokogitea/workflows/rc-revert.yml b/.mokogitea/workflows/rc-revert.yml index 5e61de8..8271593 100644 --- a/.mokogitea/workflows/rc-revert.yml +++ b/.mokogitea/workflows/rc-revert.yml @@ -29,12 +29,20 @@ jobs: steps: - name: Rename branch + env: + BRANCH: ${{ github.event.pull_request.head.ref }} + REPO: ${{ github.repository }} + GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} run: | - BRANCH="${{ github.event.pull_request.head.ref }}" + set -euo pipefail + # BRANCH is attacker-controlled (PR head ref). Strict allowlist before ANY use. + if ! printf '%s' "$BRANCH" | grep -Eq '^rc/[A-Za-z0-9._/-]+$'; then + echo "::error::Refusing unsafe branch name: $BRANCH"; exit 1 + fi SUFFIX="${BRANCH#rc/}" DEV_BRANCH="dev/${SUFFIX}" - API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches" - TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" + API="${GITEA_URL}/api/v1/repos/${REPO}/branches" # Create dev/ branch from rc/ branch STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \ @@ -42,25 +50,22 @@ jobs: -H "Content-Type: application/json" \ -d "{\"new_branch_name\": \"${DEV_BRANCH}\", \"old_branch_name\": \"${BRANCH}\"}" \ "${API}" 2>/dev/null || true) - if [ "$STATUS" = "201" ]; then - echo "Created branch: ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY + echo "Created branch: ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY" else - echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})" - exit 1 + echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"; exit 1 fi - # Delete rc/ branch - ENCODED=$(php -r "echo rawurlencode('${BRANCH}');") + # Read BRANCH from the environment inside PHP (getenv, no string interpolation -> no PHP injection) + ENCODED=$(php -r 'echo rawurlencode(getenv("BRANCH"));') STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \ -H "Authorization: token ${TOKEN}" \ "${API}/${ENCODED}" 2>/dev/null || true) - if [ "$STATUS" = "204" ]; then - echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY + echo "Deleted branch: ${BRANCH}" >> "$GITHUB_STEP_SUMMARY" else echo "::warning::Failed to delete ${BRANCH} (HTTP ${STATUS})" fi - echo "### RC Reverted" >> $GITHUB_STEP_SUMMARY - echo "${BRANCH} → ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY + echo "### RC Reverted" >> "$GITHUB_STEP_SUMMARY" + echo "${BRANCH} → ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY" diff --git a/.mokogitea/workflows/workflow-sync-trigger.yml b/.mokogitea/workflows/workflow-sync-trigger.yml index 28d58cf..34891e8 100644 --- a/.mokogitea/workflows/workflow-sync-trigger.yml +++ b/.mokogitea/workflows/workflow-sync-trigger.yml @@ -47,13 +47,6 @@ jobs: echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT" echo "Platform: ${PLATFORM:-all}" - - name: Setup PHP - run: | - if ! command -v php &> /dev/null; then - sudo apt-get update -qq - sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1 - fi - - name: Clone mokocli env: MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} @@ -61,6 +54,12 @@ jobs: MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}" git clone --depth 1 "${MOKOGITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli + - name: Install PHP + run: | + if ! command -v php &> /dev/null; then + apt-get update -qq && apt-get install -y -qq php-cli php-json php-curl > /dev/null 2>&1 + fi + - name: Install dependencies run: | cd /tmp/mokocli