Public Access
feat: add gitignore validation, move bulk-repo-sync workflow here
- Add REQUIRED_GITIGNORE_ENTRIES constant with mandatory patterns: Sublime project/workspace, sftp-config, IDE dirs, secrets, vendor, logs - Add validateGitignoreEntries() method for checking required entries - mergeGitConfigFile() still appends missing entries (non-destructive) - Add .gitea/workflows/bulk-repo-sync.yml (moved from MokoStandards) - Runs from this repo directly (checkout self, not remote) - Org updated to MokoConsulting (Gitea) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoStandards-API.Automation
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
# PATH: /.gitea/workflows/bulk-repo-sync.yml
|
||||
# VERSION: 04.06.12
|
||||
# BRIEF: Bulk repo sync — runs from API repo, syncs standards to all governed repos
|
||||
|
||||
name: Bulk Repository Sync
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 1 * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Preview mode (no changes)'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
repos:
|
||||
description: 'Comma-separated repo names (empty = all)'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
exclude:
|
||||
description: 'Comma-separated repos to skip'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
force:
|
||||
description: 'Force overwrite protected files'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
bulk-sync:
|
||||
name: Sync Standards to Repositories
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.1'
|
||||
extensions: json, mbstring, curl
|
||||
tools: composer
|
||||
coverage: none
|
||||
|
||||
- name: Install Dependencies
|
||||
run: composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
|
||||
|
||||
- name: Build CLI Arguments
|
||||
id: args
|
||||
run: |
|
||||
ARGS="--org MokoConsulting"
|
||||
if [ "${{ inputs.dry_run }}" = "true" ] || [ "${{ gitea.event_name }}" = "schedule" ]; then
|
||||
ARGS="$ARGS --dry-run"
|
||||
fi
|
||||
if [ -n "${{ inputs.repos }}" ]; then
|
||||
ARGS="$ARGS --repos ${{ inputs.repos }}"
|
||||
fi
|
||||
if [ -n "${{ inputs.exclude }}" ]; then
|
||||
ARGS="$ARGS --exclude ${{ inputs.exclude }}"
|
||||
fi
|
||||
if [ "${{ inputs.force }}" = "true" ]; then
|
||||
ARGS="$ARGS --force"
|
||||
fi
|
||||
ARGS="$ARGS --yes"
|
||||
echo "args=$ARGS" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Run Bulk Sync
|
||||
run: |
|
||||
echo "Running: php automation/bulk_sync.php ${{ steps.args.outputs.args }}"
|
||||
php automation/bulk_sync.php ${{ steps.args.outputs.args }} 2>&1 | tee /tmp/bulk_sync.log
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
GIT_PLATFORM: gitea
|
||||
GITEA_URL: https://git.mokoconsulting.tech
|
||||
GITEA_ORG: MokoConsulting
|
||||
|
||||
- name: Commit Updated Definitions
|
||||
if: success() && inputs.dry_run != 'true'
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain definitions/sync/)" ]; then
|
||||
git config user.name "gitea-actions[bot]"
|
||||
git config user.email "gitea-actions[bot]@git.mokoconsulting.tech"
|
||||
git add definitions/sync/*.def.tf
|
||||
git commit -m "chore: update synced repository definitions" || true
|
||||
git push || true
|
||||
fi
|
||||
|
||||
- name: Upload Sync Log
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bulk-sync-log-${{ gitea.run_number }}
|
||||
path: /tmp/bulk_sync.log
|
||||
retention-days: 30
|
||||
@@ -903,6 +903,77 @@ HCL;
|
||||
return $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required .gitignore entries that MUST exist in every governed repo.
|
||||
* The sync validates these exist (appending if missing) without
|
||||
* overwriting custom entries. Repos can add their own patterns freely.
|
||||
*/
|
||||
private const REQUIRED_GITIGNORE_ENTRIES = [
|
||||
// Secrets & environment
|
||||
'.env',
|
||||
'.env.local',
|
||||
'.env.*.local',
|
||||
'secrets/',
|
||||
'*.secrets.*',
|
||||
|
||||
// Sublime Text project files
|
||||
'*.sublime-project',
|
||||
'*.sublime-workspace',
|
||||
'*.sublime-settings',
|
||||
|
||||
// SFTP config (Sublime SFTP, VS Code SFTP, etc.)
|
||||
'sftp-config*.json',
|
||||
'sftp-config.json.template',
|
||||
'sftp-settings.json',
|
||||
|
||||
// IDE / editor
|
||||
'.idea/',
|
||||
'.vscode/*',
|
||||
'.claude/',
|
||||
'*.code-workspace',
|
||||
|
||||
// OS cruft
|
||||
'.DS_Store',
|
||||
'Thumbs.db',
|
||||
|
||||
// Task tracking
|
||||
'TODO.md',
|
||||
|
||||
// Vendor / dependencies
|
||||
'/vendor/',
|
||||
'node_modules/',
|
||||
|
||||
// Logs
|
||||
'*.log',
|
||||
];
|
||||
|
||||
/**
|
||||
* Validate that required .gitignore entries exist in a repo.
|
||||
* Returns array of missing entries, empty if all present.
|
||||
*
|
||||
* @param string $existingContent Current .gitignore content from repo
|
||||
* @return array<string> Missing required entries
|
||||
*/
|
||||
public function validateGitignoreEntries(string $existingContent): array
|
||||
{
|
||||
$existingLines = array_map('trim', explode("\n", $existingContent));
|
||||
$existingSet = [];
|
||||
foreach ($existingLines as $line) {
|
||||
if ($line !== '' && !str_starts_with($line, '#')) {
|
||||
$existingSet[$line] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$missing = [];
|
||||
foreach (self::REQUIRED_GITIGNORE_ENTRIES as $entry) {
|
||||
if (!isset($existingSet[$entry])) {
|
||||
$missing[] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
return $missing;
|
||||
}
|
||||
|
||||
private function mergeGitConfigFile(string $existing, string $template): string
|
||||
{
|
||||
$existingLines = array_map('rtrim', explode("\n", $existing));
|
||||
|
||||
Reference in New Issue
Block a user