chore: Sync MokoStandards 04.01.00 #100
103
.github/workflows/deploy-dev.yml
vendored
103
.github/workflows/deploy-dev.yml
vendored
@@ -22,7 +22,7 @@
|
|||||||
# INGROUP: MokoStandards.Deploy
|
# INGROUP: MokoStandards.Deploy
|
||||||
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||||
# PATH: /templates/workflows/shared/deploy-dev.yml
|
# 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
|
# 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.
|
# 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.
|
# 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:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
|
||||||
- master
|
|
||||||
- 'dev/**'
|
- 'dev/**'
|
||||||
- develop
|
- develop
|
||||||
- development
|
- development
|
||||||
|
paths:
|
||||||
|
- 'src/**'
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened, closed]
|
types: [opened, synchronize, reopened, closed]
|
||||||
branches:
|
branches:
|
||||||
- main
|
|
||||||
- master
|
|
||||||
- 'dev/**'
|
- 'dev/**'
|
||||||
- develop
|
- develop
|
||||||
- development
|
- development
|
||||||
|
paths:
|
||||||
|
- 'src/**'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
clear_remote:
|
clear_remote:
|
||||||
@@ -89,52 +89,82 @@ jobs:
|
|||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
ORG="${{ github.repository_owner }}"
|
ORG="${{ github.repository_owner }}"
|
||||||
|
|
||||||
# Try the per-repo collaborator endpoint first.
|
METHOD=""
|
||||||
# This returns 404 for org owners who are not listed as explicit
|
AUTHORIZED="false"
|
||||||
# collaborators, so we fall back to the org membership role check.
|
|
||||||
|
# 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"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# For other actors, check repo/org permissions via API
|
||||||
|
if [ "$AUTHORIZED" != "true" ]; then
|
||||||
PERMISSION=$(gh api "repos/${REPO}/collaborators/${ACTOR}/permission" \
|
PERMISSION=$(gh api "repos/${REPO}/collaborators/${ACTOR}/permission" \
|
||||||
--jq '.permission' 2>/dev/null)
|
--jq '.permission' 2>/dev/null)
|
||||||
|
METHOD="repo collaborator API"
|
||||||
|
|
||||||
if [ -z "$PERMISSION" ]; then
|
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}" \
|
ORG_ROLE=$(gh api "orgs/${ORG}/memberships/${ACTOR}" \
|
||||||
--jq '.role' 2>/dev/null)
|
--jq '.role' 2>/dev/null)
|
||||||
|
METHOD="org membership API"
|
||||||
if [ "$ORG_ROLE" = "owner" ]; then
|
if [ "$ORG_ROLE" = "owner" ]; then
|
||||||
PERMISSION="admin"
|
PERMISSION="admin"
|
||||||
echo "ℹ️ ${ACTOR} is an org owner — granting admin access"
|
|
||||||
else
|
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"
|
PERMISSION="none"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "$PERMISSION" in
|
case "$PERMISSION" in
|
||||||
admin|maintain)
|
admin|maintain) AUTHORIZED="true" ;;
|
||||||
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
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 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:
|
deploy:
|
||||||
name: SFTP Deploy → Dev
|
name: SFTP Deploy → Dev
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [check-permission]
|
needs: [check-permission]
|
||||||
if: >-
|
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 == 'push' ||
|
||||||
(github.event_name == 'pull_request' &&
|
(github.event_name == 'pull_request' &&
|
||||||
(github.event.action == 'opened' ||
|
(github.event.action == 'opened' ||
|
||||||
github.event.action == 'synchronize' ||
|
github.event.action == 'synchronize' ||
|
||||||
github.event.action == 'reopened' ||
|
github.event.action == 'reopened' ||
|
||||||
github.event.pull_request.merged == true))
|
github.event.pull_request.merged == true)))
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
@@ -214,9 +244,11 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
$SKIP && continue
|
$SKIP && continue
|
||||||
if [ -f ".gitignore" ] && git check-ignore -q "$rel" 2>/dev/null; then
|
if [ -f ".gitignore" ]; then
|
||||||
|
git check-ignore -q "$rel" 2>/dev/null && {
|
||||||
IGNORED_FILES+=("$rel | .gitignore")
|
IGNORED_FILES+=("$rel | .gitignore")
|
||||||
continue
|
continue
|
||||||
|
} || true
|
||||||
fi
|
fi
|
||||||
WILL_UPLOAD+=("$rel")
|
WILL_UPLOAD+=("$rel")
|
||||||
done < <(find "$SOURCE_DIR" -type f -print0 | sort -z)
|
done < <(find "$SOURCE_DIR" -type f -print0 | sort -z)
|
||||||
@@ -542,6 +574,25 @@ jobs:
|
|||||||
DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD")
|
DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD")
|
||||||
fi
|
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 '<extension' {} \; 2>/dev/null | while read -r manifest; do
|
||||||
|
sed -i "s|<version>[^<]*</version>|<version>development</version>|" "$manifest" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
|
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
|
||||||
# (deploy-sftp.php handles dotfile skipping and .ftp_ignore natively)
|
# (deploy-sftp.php handles dotfile skipping and .ftp_ignore natively)
|
||||||
# Remove temp files that should never be left behind
|
# Remove temp files that should never be left behind
|
||||||
|
|||||||
Reference in New Issue
Block a user