ci: sync workflows from main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
21
.github/.mokostandards
vendored
21
.github/.mokostandards
vendored
@@ -1,20 +1 @@
|
|||||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
platform: waas-component
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
# FILE INFORMATION
|
|
||||||
# DEFGROUP: MokoStandards.Templates.Config
|
|
||||||
# INGROUP: MokoStandards.Templates
|
|
||||||
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
|
||||||
# PATH: /templates/configs/moko-standards.yml
|
|
||||||
# VERSION: 04.04.01
|
|
||||||
# BRIEF: Governance attachment template — synced to .mokostandards in every governed repository
|
|
||||||
# NOTE: Tokens replaced at sync time: mokoconsulting-tech, MokoCassiopeia, waas-component, 04.04.00
|
|
||||||
#
|
|
||||||
# This file is managed automatically by MokoStandards bulk sync.
|
|
||||||
# Do not edit manually — changes will be overwritten on the next sync.
|
|
||||||
# To update governance settings, open a PR in MokoStandards instead:
|
|
||||||
# https://github.com/mokoconsulting-tech/MokoStandards
|
|
||||||
|
|
||||||
standards_source: "https://github.com/mokoconsulting-tech/MokoStandards"
|
|
||||||
standards_version: "04.04.00"
|
|
||||||
platform: "waas-component"
|
|
||||||
governed_repo: "mokoconsulting-tech/MokoCassiopeia"
|
|
||||||
|
|||||||
2
.github/workflows/auto-release.yml
vendored
2
.github/workflows/auto-release.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 --branch version/04.04 --quiet \
|
git clone --depth 1 --branch version/04.05 --quiet \
|
||||||
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
||||||
/tmp/mokostandards
|
/tmp/mokostandards
|
||||||
cd /tmp/mokostandards
|
cd /tmp/mokostandards
|
||||||
|
|||||||
37
.github/workflows/deploy-demo.yml
vendored
37
.github/workflows/deploy-demo.yml
vendored
@@ -36,10 +36,9 @@ name: Deploy to Demo Server (SFTP)
|
|||||||
# Optional org-level variable: DEMO_FTP_PORT (auto-detected from host or defaults to 22)
|
# Optional org-level variable: DEMO_FTP_PORT (auto-detected from host or defaults to 22)
|
||||||
# Optional org/repo variable: DEMO_FTP_SUFFIX — when set, appended to DEMO_FTP_PATH to form the
|
# Optional org/repo variable: DEMO_FTP_SUFFIX — when set, appended to DEMO_FTP_PATH to form the
|
||||||
# full remote destination: DEMO_FTP_PATH/DEMO_FTP_SUFFIX
|
# full remote destination: DEMO_FTP_PATH/DEMO_FTP_SUFFIX
|
||||||
# Ignore rules: Place a .ftp_ignore file in the repository root. Each non-empty,
|
# Ignore rules: Place a .ftpignore file in the repository root. Each non-empty,
|
||||||
# non-comment line is a regex pattern tested against the relative path
|
# non-comment line is a glob pattern tested against the relative path
|
||||||
# of each file (e.g. "subdir/file.txt"). The .gitignore is also
|
# of each file (e.g. "subdir/file.txt"). The .gitignore is NOT used.
|
||||||
# respected automatically.
|
|
||||||
# Required org-level secret: DEMO_FTP_KEY (preferred) or DEMO_FTP_PASSWORD
|
# Required org-level secret: DEMO_FTP_KEY (preferred) or DEMO_FTP_PASSWORD
|
||||||
#
|
#
|
||||||
# Access control: only users with admin or maintain role on the repository may deploy.
|
# Access control: only users with admin or maintain role on the repository may deploy.
|
||||||
@@ -195,8 +194,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
SOURCE_DIR: ${{ steps.source.outputs.dir }}
|
SOURCE_DIR: ${{ steps.source.outputs.dir }}
|
||||||
run: |
|
run: |
|
||||||
# ── Convert a gitignore-style glob line to an ERE pattern ──────────────
|
# ── Convert a ftpignore-style glob line to an ERE pattern ──────────────
|
||||||
ftp_ignore_to_regex() {
|
ftpignore_to_regex() {
|
||||||
local line="$1"
|
local line="$1"
|
||||||
local anchored=false
|
local anchored=false
|
||||||
# Strip inline comments and whitespace
|
# Strip inline comments and whitespace
|
||||||
@@ -226,15 +225,15 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Read .ftp_ignore (gitignore-style globs) ─────────────────────────
|
# ── Read .ftpignore (ftpignore-style globs) ─────────────────────────
|
||||||
IGNORE_PATTERNS=()
|
IGNORE_PATTERNS=()
|
||||||
IGNORE_SOURCES=()
|
IGNORE_SOURCES=()
|
||||||
if [ -f ".ftp_ignore" ]; then
|
if [ -f ".ftpignore" ]; then
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
[[ "$line" =~ ^[[:space:]]*$ || "$line" =~ ^[[:space:]]*# ]] && continue
|
[[ "$line" =~ ^[[:space:]]*$ || "$line" =~ ^[[:space:]]*# ]] && continue
|
||||||
regex=$(ftp_ignore_to_regex "$line")
|
regex=$(ftpignore_to_regex "$line")
|
||||||
[ -n "$regex" ] && IGNORE_PATTERNS+=("$regex") && IGNORE_SOURCES+=("$line")
|
[ -n "$regex" ] && IGNORE_PATTERNS+=("$regex") && IGNORE_SOURCES+=("$line")
|
||||||
done < ".ftp_ignore"
|
done < ".ftpignore"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Walk src/ and classify every file ────────────────────────────────
|
# ── Walk src/ and classify every file ────────────────────────────────
|
||||||
@@ -245,17 +244,11 @@ jobs:
|
|||||||
SKIP=false
|
SKIP=false
|
||||||
for i in "${!IGNORE_PATTERNS[@]}"; do
|
for i in "${!IGNORE_PATTERNS[@]}"; do
|
||||||
if echo "$rel" | grep -qE "${IGNORE_PATTERNS[$i]}" 2>/dev/null; then
|
if echo "$rel" | grep -qE "${IGNORE_PATTERNS[$i]}" 2>/dev/null; then
|
||||||
IGNORED_FILES+=("$rel | .ftp_ignore \`${IGNORE_SOURCES[$i]}\`")
|
IGNORED_FILES+=("$rel | .ftpignore \`${IGNORE_SOURCES[$i]}\`")
|
||||||
SKIP=true; break
|
SKIP=true; break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
$SKIP && continue
|
$SKIP && continue
|
||||||
if [ -f ".gitignore" ]; then
|
|
||||||
git check-ignore -q "$rel" 2>/dev/null && {
|
|
||||||
IGNORED_FILES+=("$rel | .gitignore")
|
|
||||||
continue
|
|
||||||
} || true
|
|
||||||
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)
|
||||||
|
|
||||||
@@ -426,7 +419,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 --branch version/04.04 --quiet \
|
git clone --depth 1 --branch version/04.05 --quiet \
|
||||||
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
||||||
/tmp/mokostandards
|
/tmp/mokostandards
|
||||||
cd /tmp/mokostandards
|
cd /tmp/mokostandards
|
||||||
@@ -637,8 +630,12 @@ jobs:
|
|||||||
DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD")
|
DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
|
PLATFORM=$(php /tmp/mokostandards/api/cli/platform_detect.php --path . 2>/dev/null || true)
|
||||||
# (deploy-sftp.php handles dotfile skipping and .ftp_ignore natively)
|
if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards/api/deploy/deploy-joomla.php" ]; then
|
||||||
|
php /tmp/mokostandards/api/deploy/deploy-joomla.php "${DEPLOY_ARGS[@]}"
|
||||||
|
else
|
||||||
|
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
|
||||||
|
fi
|
||||||
# Remove temp files that should never be left behind
|
# Remove temp files that should never be left behind
|
||||||
rm -f /tmp/deploy_key /tmp/sftp-config.json
|
rm -f /tmp/deploy_key /tmp/sftp-config.json
|
||||||
|
|
||||||
|
|||||||
44
.github/workflows/deploy-dev.yml
vendored
44
.github/workflows/deploy-dev.yml
vendored
@@ -37,10 +37,9 @@ name: Deploy to Dev Server (SFTP)
|
|||||||
# Optional org-level variable: DEV_FTP_PORT (auto-detected from host or defaults to 22)
|
# Optional org-level variable: DEV_FTP_PORT (auto-detected from host or defaults to 22)
|
||||||
# Optional org/repo variable: DEV_FTP_SUFFIX — when set, appended to DEV_FTP_PATH to form the
|
# Optional org/repo variable: DEV_FTP_SUFFIX — when set, appended to DEV_FTP_PATH to form the
|
||||||
# full remote destination: DEV_FTP_PATH/DEV_FTP_SUFFIX
|
# full remote destination: DEV_FTP_PATH/DEV_FTP_SUFFIX
|
||||||
# Ignore rules: Place a .ftp_ignore file in the repository root. Each non-empty,
|
# Ignore rules: Place a .ftpignore file in the repository root. Each non-empty,
|
||||||
# non-comment line is a regex pattern tested against the relative path
|
# non-comment line is a glob pattern tested against the relative path
|
||||||
# of each file (e.g. "subdir/file.txt"). The .gitignore is also
|
# of each file (e.g. "subdir/file.txt"). The .gitignore is NOT used.
|
||||||
# respected automatically.
|
|
||||||
# Required org-level secret: DEV_FTP_KEY (preferred) or DEV_FTP_PASSWORD
|
# Required org-level secret: DEV_FTP_KEY (preferred) or DEV_FTP_PASSWORD
|
||||||
#
|
#
|
||||||
# Access control: only users with admin or maintain role on the repository may deploy.
|
# Access control: only users with admin or maintain role on the repository may deploy.
|
||||||
@@ -200,8 +199,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
SOURCE_DIR: ${{ steps.source.outputs.dir }}
|
SOURCE_DIR: ${{ steps.source.outputs.dir }}
|
||||||
run: |
|
run: |
|
||||||
# ── Convert a gitignore-style glob line to an ERE pattern ──────────────
|
# ── Convert a ftpignore-style glob line to an ERE pattern ──────────────
|
||||||
ftp_ignore_to_regex() {
|
ftpignore_to_regex() {
|
||||||
local line="$1"
|
local line="$1"
|
||||||
local anchored=false
|
local anchored=false
|
||||||
# Strip inline comments and whitespace
|
# Strip inline comments and whitespace
|
||||||
@@ -231,15 +230,15 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Read .ftp_ignore (gitignore-style globs) ─────────────────────────
|
# ── Read .ftpignore (ftpignore-style globs) ─────────────────────────
|
||||||
IGNORE_PATTERNS=()
|
IGNORE_PATTERNS=()
|
||||||
IGNORE_SOURCES=()
|
IGNORE_SOURCES=()
|
||||||
if [ -f ".ftp_ignore" ]; then
|
if [ -f ".ftpignore" ]; then
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
[[ "$line" =~ ^[[:space:]]*$ || "$line" =~ ^[[:space:]]*# ]] && continue
|
[[ "$line" =~ ^[[:space:]]*$ || "$line" =~ ^[[:space:]]*# ]] && continue
|
||||||
regex=$(ftp_ignore_to_regex "$line")
|
regex=$(ftpignore_to_regex "$line")
|
||||||
[ -n "$regex" ] && IGNORE_PATTERNS+=("$regex") && IGNORE_SOURCES+=("$line")
|
[ -n "$regex" ] && IGNORE_PATTERNS+=("$regex") && IGNORE_SOURCES+=("$line")
|
||||||
done < ".ftp_ignore"
|
done < ".ftpignore"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Walk src/ and classify every file ────────────────────────────────
|
# ── Walk src/ and classify every file ────────────────────────────────
|
||||||
@@ -250,17 +249,11 @@ jobs:
|
|||||||
SKIP=false
|
SKIP=false
|
||||||
for i in "${!IGNORE_PATTERNS[@]}"; do
|
for i in "${!IGNORE_PATTERNS[@]}"; do
|
||||||
if echo "$rel" | grep -qE "${IGNORE_PATTERNS[$i]}" 2>/dev/null; then
|
if echo "$rel" | grep -qE "${IGNORE_PATTERNS[$i]}" 2>/dev/null; then
|
||||||
IGNORED_FILES+=("$rel | .ftp_ignore \`${IGNORE_SOURCES[$i]}\`")
|
IGNORED_FILES+=("$rel | .ftpignore \`${IGNORE_SOURCES[$i]}\`")
|
||||||
SKIP=true; break
|
SKIP=true; break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
$SKIP && continue
|
$SKIP && continue
|
||||||
if [ -f ".gitignore" ]; then
|
|
||||||
git check-ignore -q "$rel" 2>/dev/null && {
|
|
||||||
IGNORED_FILES+=("$rel | .gitignore")
|
|
||||||
continue
|
|
||||||
} || true
|
|
||||||
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)
|
||||||
|
|
||||||
@@ -431,7 +424,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 --branch version/04.04 --quiet \
|
git clone --depth 1 --branch version/04.05 --quiet \
|
||||||
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
||||||
/tmp/mokostandards
|
/tmp/mokostandards
|
||||||
cd /tmp/mokostandards
|
cd /tmp/mokostandards
|
||||||
@@ -583,8 +576,8 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Dev deploys skip minified files — use unminified sources for debugging
|
# Dev deploys skip minified files — use unminified sources for debugging
|
||||||
echo "*.min.js" >> .ftp_ignore
|
echo "*.min.js" >> .ftpignore
|
||||||
echo "*.min.css" >> .ftp_ignore
|
echo "*.min.css" >> .ftpignore
|
||||||
|
|
||||||
# ── Run deploy-sftp.php from MokoStandards ────────────────────────────
|
# ── Run deploy-sftp.php from MokoStandards ────────────────────────────
|
||||||
DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json)
|
DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json)
|
||||||
@@ -666,8 +659,15 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
|
# Use Joomla-aware deploy for waas-component (routes files to correct Joomla dirs)
|
||||||
# (deploy-sftp.php handles dotfile skipping and .ftp_ignore natively)
|
# Use standard SFTP deploy for everything else
|
||||||
|
PLATFORM=$(php /tmp/mokostandards/api/cli/platform_detect.php --path . 2>/dev/null || true)
|
||||||
|
if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards/api/deploy/deploy-joomla.php" ]; then
|
||||||
|
php /tmp/mokostandards/api/deploy/deploy-joomla.php "${DEPLOY_ARGS[@]}"
|
||||||
|
else
|
||||||
|
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
|
||||||
|
fi
|
||||||
|
# (both scripts handle dotfile skipping and .ftpignore natively)
|
||||||
# Remove temp files that should never be left behind
|
# Remove temp files that should never be left behind
|
||||||
rm -f /tmp/deploy_key /tmp/sftp-config.json
|
rm -f /tmp/deploy_key /tmp/sftp-config.json
|
||||||
|
|
||||||
|
|||||||
37
.github/workflows/deploy-rs.yml
vendored
37
.github/workflows/deploy-rs.yml
vendored
@@ -36,10 +36,9 @@ name: Deploy to RS Server (SFTP)
|
|||||||
# Optional org-level variable: RS_FTP_PORT (auto-detected from host or defaults to 22)
|
# Optional org-level variable: RS_FTP_PORT (auto-detected from host or defaults to 22)
|
||||||
# Optional org/repo variable: RS_FTP_SUFFIX — when set, appended to RS_FTP_PATH to form the
|
# Optional org/repo variable: RS_FTP_SUFFIX — when set, appended to RS_FTP_PATH to form the
|
||||||
# full remote destination: RS_FTP_PATH/RS_FTP_SUFFIX
|
# full remote destination: RS_FTP_PATH/RS_FTP_SUFFIX
|
||||||
# Ignore rules: Place a .ftp_ignore file in the repository root. Each non-empty,
|
# Ignore rules: Place a .ftpignore file in the repository root. Each non-empty,
|
||||||
# non-comment line is a regex pattern tested against the relative path
|
# non-comment line is a glob pattern tested against the relative path
|
||||||
# of each file (e.g. "subdir/file.txt"). The .gitignore is also
|
# of each file (e.g. "subdir/file.txt"). The .gitignore is NOT used.
|
||||||
# respected automatically.
|
|
||||||
# Required org-level secret: RS_FTP_KEY (preferred) or RS_FTP_PASSWORD
|
# Required org-level secret: RS_FTP_KEY (preferred) or RS_FTP_PASSWORD
|
||||||
#
|
#
|
||||||
# Access control: only users with admin or maintain role on the repository may deploy.
|
# Access control: only users with admin or maintain role on the repository may deploy.
|
||||||
@@ -195,8 +194,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
SOURCE_DIR: ${{ steps.source.outputs.dir }}
|
SOURCE_DIR: ${{ steps.source.outputs.dir }}
|
||||||
run: |
|
run: |
|
||||||
# ── Convert a gitignore-style glob line to an ERE pattern ──────────────
|
# ── Convert a ftpignore-style glob line to an ERE pattern ──────────────
|
||||||
ftp_ignore_to_regex() {
|
ftpignore_to_regex() {
|
||||||
local line="$1"
|
local line="$1"
|
||||||
local anchored=false
|
local anchored=false
|
||||||
# Strip inline comments and whitespace
|
# Strip inline comments and whitespace
|
||||||
@@ -226,15 +225,15 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Read .ftp_ignore (gitignore-style globs) ─────────────────────────
|
# ── Read .ftpignore (ftpignore-style globs) ─────────────────────────
|
||||||
IGNORE_PATTERNS=()
|
IGNORE_PATTERNS=()
|
||||||
IGNORE_SOURCES=()
|
IGNORE_SOURCES=()
|
||||||
if [ -f ".ftp_ignore" ]; then
|
if [ -f ".ftpignore" ]; then
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
[[ "$line" =~ ^[[:space:]]*$ || "$line" =~ ^[[:space:]]*# ]] && continue
|
[[ "$line" =~ ^[[:space:]]*$ || "$line" =~ ^[[:space:]]*# ]] && continue
|
||||||
regex=$(ftp_ignore_to_regex "$line")
|
regex=$(ftpignore_to_regex "$line")
|
||||||
[ -n "$regex" ] && IGNORE_PATTERNS+=("$regex") && IGNORE_SOURCES+=("$line")
|
[ -n "$regex" ] && IGNORE_PATTERNS+=("$regex") && IGNORE_SOURCES+=("$line")
|
||||||
done < ".ftp_ignore"
|
done < ".ftpignore"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Walk src/ and classify every file ────────────────────────────────
|
# ── Walk src/ and classify every file ────────────────────────────────
|
||||||
@@ -245,17 +244,11 @@ jobs:
|
|||||||
SKIP=false
|
SKIP=false
|
||||||
for i in "${!IGNORE_PATTERNS[@]}"; do
|
for i in "${!IGNORE_PATTERNS[@]}"; do
|
||||||
if echo "$rel" | grep -qE "${IGNORE_PATTERNS[$i]}" 2>/dev/null; then
|
if echo "$rel" | grep -qE "${IGNORE_PATTERNS[$i]}" 2>/dev/null; then
|
||||||
IGNORED_FILES+=("$rel | .ftp_ignore \`${IGNORE_SOURCES[$i]}\`")
|
IGNORED_FILES+=("$rel | .ftpignore \`${IGNORE_SOURCES[$i]}\`")
|
||||||
SKIP=true; break
|
SKIP=true; break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
$SKIP && continue
|
$SKIP && continue
|
||||||
if [ -f ".gitignore" ]; then
|
|
||||||
git check-ignore -q "$rel" 2>/dev/null && {
|
|
||||||
IGNORED_FILES+=("$rel | .gitignore")
|
|
||||||
continue
|
|
||||||
} || true
|
|
||||||
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)
|
||||||
|
|
||||||
@@ -407,7 +400,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 --branch version/04.04 --quiet \
|
git clone --depth 1 --branch version/04.05 --quiet \
|
||||||
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
||||||
/tmp/mokostandards
|
/tmp/mokostandards
|
||||||
cd /tmp/mokostandards
|
cd /tmp/mokostandards
|
||||||
@@ -564,8 +557,12 @@ jobs:
|
|||||||
DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD")
|
DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
|
PLATFORM=$(php /tmp/mokostandards/api/cli/platform_detect.php --path . 2>/dev/null || true)
|
||||||
# (deploy-sftp.php handles dotfile skipping and .ftp_ignore natively)
|
if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards/api/deploy/deploy-joomla.php" ]; then
|
||||||
|
php /tmp/mokostandards/api/deploy/deploy-joomla.php "${DEPLOY_ARGS[@]}"
|
||||||
|
else
|
||||||
|
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
|
||||||
|
fi
|
||||||
# Remove temp files that should never be left behind
|
# Remove temp files that should never be left behind
|
||||||
rm -f /tmp/deploy_key /tmp/sftp-config.json
|
rm -f /tmp/deploy_key /tmp/sftp-config.json
|
||||||
|
|
||||||
|
|||||||
95
.github/workflows/repo_health.yml
vendored
95
.github/workflows/repo_health.yml
vendored
@@ -10,7 +10,7 @@
|
|||||||
# INGROUP: MokoStandards.Validation
|
# INGROUP: MokoStandards.Validation
|
||||||
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||||
# PATH: /.github/workflows/repo_health.yml
|
# PATH: /.github/workflows/repo_health.yml
|
||||||
# VERSION: 04.01.00
|
# VERSION: 04.05.00
|
||||||
# BRIEF: Enforces repository guardrails by validating release configuration, scripts governance, tooling availability, and core repository health artifacts.
|
# BRIEF: Enforces repository guardrails by validating release configuration, scripts governance, tooling availability, and core repository health artifacts.
|
||||||
# NOTE: Field is user-managed.
|
# NOTE: Field is user-managed.
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -29,7 +29,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
profile:
|
profile:
|
||||||
description: Which configuration profile to validate. release checks SFTP variables used by release pipeline. scripts checks baseline script prerequisites. repo runs repository health only. al[...]
|
description: 'Validation profile: all, release, scripts, or repo'
|
||||||
required: true
|
required: true
|
||||||
default: all
|
default: all
|
||||||
type: choice
|
type: choice
|
||||||
@@ -39,19 +39,7 @@ on:
|
|||||||
- scripts
|
- scripts
|
||||||
- repo
|
- repo
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
|
||||||
- .github/workflows/**
|
|
||||||
- scripts/**
|
|
||||||
- docs/**
|
|
||||||
- dev/**
|
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- .github/workflows/**
|
|
||||||
- scripts/**
|
|
||||||
- docs/**
|
|
||||||
- dev/**
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -68,7 +56,7 @@ env:
|
|||||||
|
|
||||||
# Repo health policy
|
# Repo health policy
|
||||||
# Files are listed as-is; directories must end with a trailing slash.
|
# Files are listed as-is; directories must end with a trailing slash.
|
||||||
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.github/workflows/,src/
|
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.github/workflows/
|
||||||
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
|
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
|
||||||
REPO_DISALLOWED_DIRS:
|
REPO_DISALLOWED_DIRS:
|
||||||
REPO_DISALLOWED_FILES: TODO.md,todo.md
|
REPO_DISALLOWED_FILES: TODO.md,todo.md
|
||||||
@@ -82,6 +70,7 @@ env:
|
|||||||
WORKFLOWS_DIR: .github/workflows
|
WORKFLOWS_DIR: .github/workflows
|
||||||
SHELLCHECK_PATTERN: '*.sh'
|
SHELLCHECK_PATTERN: '*.sh'
|
||||||
SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml'
|
SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml'
|
||||||
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
access_check:
|
access_check:
|
||||||
@@ -412,6 +401,15 @@ jobs:
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Source directory: src/ or htdocs/ (either is valid)
|
||||||
|
if [ -d "src" ]; then
|
||||||
|
SOURCE_DIR="src"
|
||||||
|
elif [ -d "htdocs" ]; then
|
||||||
|
SOURCE_DIR="htdocs"
|
||||||
|
else
|
||||||
|
missing_required+=("src/ or htdocs/ (source directory required)")
|
||||||
|
fi
|
||||||
|
|
||||||
IFS=',' read -r -a required_artifacts <<< "${REPO_REQUIRED_ARTIFACTS}"
|
IFS=',' read -r -a required_artifacts <<< "${REPO_REQUIRED_ARTIFACTS}"
|
||||||
IFS=',' read -r -a optional_files <<< "${REPO_OPTIONAL_FILES}"
|
IFS=',' read -r -a optional_files <<< "${REPO_OPTIONAL_FILES}"
|
||||||
IFS=',' read -r -a disallowed_dirs <<< "${REPO_DISALLOWED_DIRS}"
|
IFS=',' read -r -a disallowed_dirs <<< "${REPO_DISALLOWED_DIRS}"
|
||||||
@@ -561,6 +559,73 @@ jobs:
|
|||||||
} >> "${GITHUB_STEP_SUMMARY}"
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── Joomla-specific checks ───────────────────────────────────────
|
||||||
|
joomla_findings=()
|
||||||
|
|
||||||
|
# XML manifest: find any XML file containing <extension
|
||||||
|
MANIFEST="$(find . -maxdepth 2 -name '*.xml' -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)"
|
||||||
|
if [ -z "${MANIFEST}" ]; then
|
||||||
|
joomla_findings+=("Joomla XML manifest not found (no *.xml with <extension> tag)")
|
||||||
|
else
|
||||||
|
# Check <version> tag exists
|
||||||
|
if ! grep -qP '<version>' "${MANIFEST}"; then
|
||||||
|
joomla_findings+=("XML manifest: <version> tag missing")
|
||||||
|
fi
|
||||||
|
# Check extension type attribute
|
||||||
|
if ! grep -qP 'type="(component|module|plugin|library|package|template|language)"' "${MANIFEST}"; then
|
||||||
|
joomla_findings+=("XML manifest: type attribute missing or invalid")
|
||||||
|
fi
|
||||||
|
# Check <name> tag
|
||||||
|
if ! grep -qP '<name>' "${MANIFEST}"; then
|
||||||
|
joomla_findings+=("XML manifest: <name> tag missing")
|
||||||
|
fi
|
||||||
|
# Check <author> tag
|
||||||
|
if ! grep -qP '<author>' "${MANIFEST}"; then
|
||||||
|
joomla_findings+=("XML manifest: <author> tag missing")
|
||||||
|
fi
|
||||||
|
# Check <namespace> for Joomla 5+
|
||||||
|
if ! grep -qP '<namespace' "${MANIFEST}"; then
|
||||||
|
joomla_findings+=("XML manifest: <namespace> missing (required for Joomla 5+)")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Language files: check for at least one .ini file
|
||||||
|
INI_COUNT="$(find . -name '*.ini' -type f 2>/dev/null | wc -l)"
|
||||||
|
if [ "${INI_COUNT}" -eq 0 ]; then
|
||||||
|
joomla_findings+=("No .ini language files found")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# update.xml must exist in root (Joomla update server)
|
||||||
|
if [ ! -f 'update.xml' ]; then
|
||||||
|
joomla_findings+=("update.xml missing in root (required for Joomla update server)")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# index.html files for directory listing protection
|
||||||
|
INDEX_DIRS=("${SOURCE_DIR}" "${SOURCE_DIR}/admin" "${SOURCE_DIR}/site")
|
||||||
|
for dir in "${INDEX_DIRS[@]}"; do
|
||||||
|
if [ -d "${dir}" ] && [ ! -f "${dir}/index.html" ]; then
|
||||||
|
joomla_findings+=("${dir}/index.html missing (directory listing protection)")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "${#joomla_findings[@]}" -gt 0 ]; then
|
||||||
|
{
|
||||||
|
printf '%s\n' '### Joomla extension checks'
|
||||||
|
printf '%s\n' '| Check | Status |'
|
||||||
|
printf '%s\n' '|---|---|'
|
||||||
|
for f in "${joomla_findings[@]}"; do
|
||||||
|
printf '%s\n' "| ${f} | Warning |"
|
||||||
|
done
|
||||||
|
printf '\n'
|
||||||
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf '%s\n' '### Joomla extension checks'
|
||||||
|
printf '%s\n' 'All Joomla-specific checks passed.'
|
||||||
|
printf '\n'
|
||||||
|
} >> "${GITHUB_STEP_SUMMARY}"
|
||||||
|
fi
|
||||||
|
|
||||||
extended_enabled="${EXTENDED_CHECKS:-true}"
|
extended_enabled="${EXTENDED_CHECKS:-true}"
|
||||||
extended_findings=()
|
extended_findings=()
|
||||||
|
|
||||||
|
|||||||
8
.github/workflows/standards-compliance.yml
vendored
8
.github/workflows/standards-compliance.yml
vendored
@@ -165,7 +165,9 @@ jobs:
|
|||||||
grep -v -E '(test|example|sample|getenv|getString|getArgument|config\[|/\.\*/|^\s*//|^\s*\*|CREDENTIAL_PATTERNS|SecurityValidator|SECRET_PATTERN|===|!==|ApiClient|str_contains|gen_wrappers)' | \
|
grep -v -E '(test|example|sample|getenv|getString|getArgument|config\[|/\.\*/|^\s*//|^\s*\*|CREDENTIAL_PATTERNS|SecurityValidator|SECRET_PATTERN|===|!==|ApiClient|str_contains|gen_wrappers)' | \
|
||||||
grep -v "= ''" | grep -v '= ""' | grep -v '\$this->config' | \
|
grep -v "= ''" | grep -v '= ""' | grep -v '\$this->config' | \
|
||||||
grep -v 'type="password"' | grep -v 'type="text"' | grep -v 'name="password"' | grep -v 'name="secretkey"' | \
|
grep -v 'type="password"' | grep -v 'type="text"' | grep -v 'name="password"' | grep -v 'name="secretkey"' | \
|
||||||
grep -v '<input ' | grep -v '<label ' | grep -v 'for="' > /tmp/secrets1.txt 2>/dev/null || true
|
grep -v '<input ' | grep -v '<label ' | grep -v 'for="' | \
|
||||||
|
grep -v 'index\.php?option=' | grep -v 'Route::_' | grep -v 'lostpassword' | \
|
||||||
|
grep -v 'resetpassword' | grep -v 'JRoute' | grep -v 'href=' > /tmp/secrets1.txt 2>/dev/null || true
|
||||||
scan_pattern "Secret assignments" "⚠️" /tmp/secrets1.txt
|
scan_pattern "Secret assignments" "⚠️" /tmp/secrets1.txt
|
||||||
|
|
||||||
# Pattern 2: Private keys
|
# Pattern 2: Private keys
|
||||||
@@ -2532,8 +2534,8 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
echo "✅ SUCCESS: Repository is fully MokoStandards compliant"
|
echo "✅ SUCCESS: Repository is fully MokoStandards compliant"
|
||||||
|
|
||||||
- name: Create tracking issue for standards violations
|
- name: Create or reopen tracking issue for standards violations
|
||||||
if: failure() && github.event_name == 'push'
|
if: failure()
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
2
.github/workflows/sync-version-on-merge.yml
vendored
2
.github/workflows/sync-version-on-merge.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
||||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 --branch version/04.04 --quiet \
|
git clone --depth 1 --branch version/04.05 --quiet \
|
||||||
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
|
||||||
/tmp/mokostandards
|
/tmp/mokostandards
|
||||||
cd /tmp/mokostandards
|
cd /tmp/mokostandards
|
||||||
|
|||||||
Reference in New Issue
Block a user