From 2076815ac3d23bffc364b64a85d7ee93bcd55c85 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <230051081+jmiller-moko@users.noreply.github.com> Date: Thu, 26 Mar 2026 18:11:39 -0500 Subject: [PATCH] chore: update .github/workflows/deploy-dev.yml from MokoStandards --- .github/workflows/deploy-dev.yml | 127 ++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 38 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index d5bc6c5..5fa6a23 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -22,7 +22,7 @@ # INGROUP: MokoStandards.Deploy # REPO: https://github.com/mokoconsulting-tech/MokoStandards # PATH: /templates/workflows/shared/deploy-dev.yml -# VERSION: 04.00.27 +# VERSION: 04.01.00 # BRIEF: SFTP deployment workflow for development server — synced to all governed repos # NOTE: Synced via bulk-repo-sync to .github/workflows/deploy-dev.yml in all governed repos. # Port is resolved in order: DEV_FTP_PORT variable → :port suffix in DEV_FTP_HOST → 22. @@ -48,19 +48,19 @@ name: Deploy to Dev Server (SFTP) on: push: branches: - - main - - master - 'dev/**' - develop - development + paths: + - 'src/**' pull_request: types: [opened, synchronize, reopened, closed] branches: - - main - - master - 'dev/**' - develop - development + paths: + - 'src/**' workflow_dispatch: inputs: clear_remote: @@ -89,52 +89,82 @@ jobs: REPO="${{ github.repository }}" ORG="${{ github.repository_owner }}" - # Try the per-repo collaborator endpoint first. - # This returns 404 for org owners who are not listed as explicit - # collaborators, so we fall back to the org membership role check. - PERMISSION=$(gh api "repos/${REPO}/collaborators/${ACTOR}/permission" \ - --jq '.permission' 2>/dev/null) + METHOD="" + AUTHORIZED="false" - if [ -z "$PERMISSION" ]; then - # Collaborator endpoint returned nothing — try org membership. - # Requires a token with read:org scope (secrets.GH_TOKEN). - # github.token alone is insufficient for this endpoint. - ORG_ROLE=$(gh api "orgs/${ORG}/memberships/${ACTOR}" \ - --jq '.role' 2>/dev/null) - if [ "$ORG_ROLE" = "owner" ]; then + # Hardcoded authorized users — always allowed to deploy + AUTHORIZED_USERS="jmiller-moko github-actions[bot]" + for user in $AUTHORIZED_USERS; do + if [ "$ACTOR" = "$user" ]; then + AUTHORIZED="true" + METHOD="hardcoded allowlist" PERMISSION="admin" - echo "ℹ️ ${ACTOR} is an org owner — granting admin access" - else - # Both checks failed — token may lack read:org scope. - echo "⚠️ Could not determine permission for ${ACTOR}." - echo " Add GH_TOKEN (PAT with read:org scope) as an org secret to fix this." - PERMISSION="none" + break fi + done + + # For other actors, check repo/org permissions via API + if [ "$AUTHORIZED" != "true" ]; then + PERMISSION=$(gh api "repos/${REPO}/collaborators/${ACTOR}/permission" \ + --jq '.permission' 2>/dev/null) + METHOD="repo collaborator API" + + if [ -z "$PERMISSION" ]; then + ORG_ROLE=$(gh api "orgs/${ORG}/memberships/${ACTOR}" \ + --jq '.role' 2>/dev/null) + METHOD="org membership API" + if [ "$ORG_ROLE" = "owner" ]; then + PERMISSION="admin" + else + PERMISSION="none" + fi + fi + + case "$PERMISSION" in + admin|maintain) AUTHORIZED="true" ;; + esac fi - case "$PERMISSION" in - admin|maintain) - echo "✅ ${ACTOR} has '${PERMISSION}' permission — authorized to deploy" - ;; - *) - echo "❌ Deployment requires admin or maintain role." - echo " ${ACTOR} has '${PERMISSION}' — contact your org administrator." - exit 1 - ;; - esac + # Write detailed summary + { + echo "## 🔐 Deploy Authorization" + echo "" + echo "| Field | Value |" + echo "|-------|-------|" + echo "| **Actor** | \`${ACTOR}\` |" + echo "| **Repository** | \`${REPO}\` |" + echo "| **Permission** | \`${PERMISSION}\` |" + echo "| **Method** | ${METHOD} |" + echo "| **Authorized** | ${AUTHORIZED} |" + echo "| **Trigger** | \`${{ github.event_name }}\` |" + echo "| **Branch** | \`${{ github.ref_name }}\` |" + echo "" + } >> "$GITHUB_STEP_SUMMARY" + + if [ "$AUTHORIZED" = "true" ]; then + echo "✅ ${ACTOR} authorized to deploy (${METHOD})" >> "$GITHUB_STEP_SUMMARY" + else + echo "❌ ${ACTOR} is NOT authorized to deploy." >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "Deployment requires one of:" >> "$GITHUB_STEP_SUMMARY" + echo "- Being in the hardcoded allowlist" >> "$GITHUB_STEP_SUMMARY" + echo "- Having \`admin\` or \`maintain\` role on the repository" >> "$GITHUB_STEP_SUMMARY" + exit 1 + fi deploy: name: SFTP Deploy → Dev runs-on: ubuntu-latest needs: [check-permission] if: >- - github.event_name == 'workflow_dispatch' || + !startsWith(github.head_ref || github.ref_name, 'chore/') && + (github.event_name == 'workflow_dispatch' || github.event_name == 'push' || (github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.action == 'reopened' || - github.event.pull_request.merged == true)) + github.event.pull_request.merged == true))) steps: - name: Checkout repository @@ -214,9 +244,11 @@ jobs: fi done $SKIP && continue - if [ -f ".gitignore" ] && git check-ignore -q "$rel" 2>/dev/null; then - IGNORED_FILES+=("$rel | .gitignore") - continue + if [ -f ".gitignore" ]; then + git check-ignore -q "$rel" 2>/dev/null && { + IGNORED_FILES+=("$rel | .gitignore") + continue + } || true fi WILL_UPLOAD+=("$rel") done < <(find "$SOURCE_DIR" -type f -print0 | sort -z) @@ -542,6 +574,25 @@ jobs: DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD") fi + # ── For Dolibarr (crm-module): set version to "development" before deploy ─ + PLATFORM="" + if [ -f ".moko-standards" ]; then + PLATFORM=$(grep -E '^platform:' .moko-standards | sed 's/.*:[[:space:]]*//' | tr -d '"') + fi + + if [ "$PLATFORM" = "crm-module" ]; then + echo "📦 Dolibarr dev deploy — setting module version to 'development'" + find "$SOURCE_DIR" -path "*/core/modules/mod*.class.php" -exec \ + sed -i "s/\(\$this->version\s*=\s*\)['\"][^'\"]*['\"]/\1'development'/" {} + 2>/dev/null || true + fi + + if [ "$PLATFORM" = "waas-component" ]; then + echo "📦 Joomla dev deploy — setting manifest version to 'development'" + find "$SOURCE_DIR" -maxdepth 2 -name "*.xml" -exec grep -l '/dev/null | while read -r manifest; do + sed -i "s|[^<]*|development|" "$manifest" 2>/dev/null || true + done + fi + php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}" # (deploy-sftp.php handles dotfile skipping and .ftp_ignore natively) # Remove temp files that should never be left behind