Compare commits

...

44 Commits

Author SHA1 Message Date
jmiller dd801ccce5 Merge pull request 'chore(sync): cascade main -> dev' (#781) from main into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 1m15s
Deploy MokoGitea (Dev) / Build & Deploy to Dev (push) Successful in 3m29s
2026-07-13 21:36:16 +00:00
jmiller b5d03ab769 Merge pull request 'chore(ci): move deploy workflows out of custom/ to root' (#780) from chore/deploy-out-of-custom into main
Generic: Standards Compliance / Secret Scanning (push) Has been cancelled
Generic: Standards Compliance / License Header Validation (push) Has been cancelled
Generic: Standards Compliance / Repository Structure Validation (push) Has been cancelled
Generic: Standards Compliance / Coding Standards Check (push) Has been cancelled
Generic: Standards Compliance / Version Consistency Check (push) Has been cancelled
Generic: Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Generic: Standards Compliance / Documentation Quality Check (push) Has been cancelled
Generic: Standards Compliance / README Completeness Check (push) Has been cancelled
Generic: Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Generic: Standards Compliance / Script Integrity Validation (push) Has been cancelled
Generic: Standards Compliance / Line Length Check (push) Has been cancelled
Generic: Standards Compliance / File Naming Standards (push) Has been cancelled
Generic: Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Generic: Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Generic: Standards Compliance / Code Duplication Detection (push) Has been cancelled
Generic: Standards Compliance / Dead Code Detection (push) Has been cancelled
Generic: Standards Compliance / File Size Limits (push) Has been cancelled
Generic: Standards Compliance / Binary File Detection (push) Has been cancelled
Generic: Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Generic: Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Generic: Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Generic: Standards Compliance / Broken Link Detection (push) Has been cancelled
Generic: Standards Compliance / API Documentation Coverage (push) Has been cancelled
Generic: Standards Compliance / Accessibility Check (push) Has been cancelled
Generic: Standards Compliance / Performance Metrics (push) Has been cancelled
Generic: Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Generic: Standards Compliance / Repository Health Check (push) Has been cancelled
Generic: Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Generic: Standards Compliance / Compliance Summary (push) Has been cancelled
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 1m2s
Generic: Project CI / Lint & Validate (pull_request) Successful in 32s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Generic: Project CI / Tests (pull_request) Successful in 27s
Universal: PR Check / Validate PR (pull_request) Successful in 7s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 59s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Deploy MokoGitea / deploy (push) Successful in 4m53s
2026-07-13 21:27:47 +00:00
jmiller 78b7c9e4af chore(ci): move deploy workflows out of custom/ to root
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 1m13s
Generic: Project CI / Lint & Validate (pull_request) Successful in 29s
Generic: Project CI / Tests (pull_request) Successful in 29s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 47s
Universal: PR Check / Validate PR (pull_request) Successful in 8s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Standards Compliance / Secret Scanning (pull_request) Failing after 8s
Generic: Standards Compliance / License Header Validation (pull_request) Successful in 8s
Universal: PR Check / Secret Scan (pull_request) Successful in 55s
Generic: Standards Compliance / Repository Structure Validation (pull_request) Successful in 7s
Universal: PR Check / Require Docs Update (pull_request) Failing after 1m3s
Generic: Standards Compliance / Coding Standards Check (pull_request) Successful in 9s
Generic: Standards Compliance / Workflow Configuration Check (pull_request) Failing after 7s
Generic: Standards Compliance / Documentation Quality Check (pull_request) Successful in 6s
Generic: Standards Compliance / README Completeness Check (pull_request) Failing after 6s
Generic: Standards Compliance / Script Integrity Validation (pull_request) Successful in 8s
Generic: Standards Compliance / Line Length Check (pull_request) Successful in 16s
Generic: Standards Compliance / Version Consistency Check (pull_request) Successful in 46s
Generic: Standards Compliance / File Naming Standards (pull_request) Successful in 6s
Generic: Standards Compliance / Insecure Code Pattern Detection (pull_request) Successful in 7s
Generic: Standards Compliance / Git Repository Hygiene (pull_request) Successful in 42s
Generic: Standards Compliance / Dead Code Detection (pull_request) Successful in 9s
Generic: Standards Compliance / File Size Limits (pull_request) Successful in 6s
Generic: Standards Compliance / Code Complexity Analysis (pull_request) Successful in 49s
Generic: Standards Compliance / TODO/FIXME Tracking (pull_request) Successful in 6s
Generic: Standards Compliance / Code Duplication Detection (pull_request) Successful in 51s
Generic: Standards Compliance / Unused Dependencies Check (pull_request) Successful in 42s
Generic: Standards Compliance / Dependency Vulnerability Scanning (pull_request) Successful in 46s
Generic: Standards Compliance / API Documentation Coverage (pull_request) Successful in 6s
Generic: Standards Compliance / Broken Link Detection (pull_request) Successful in 8s
Generic: Standards Compliance / Binary File Detection (pull_request) Successful in 1m25s
Generic: Standards Compliance / Accessibility Check (pull_request) Successful in 6s
Generic: Standards Compliance / Performance Metrics (pull_request) Successful in 6s
Generic: Standards Compliance / Terraform Configuration Validation (pull_request) Successful in 11s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Generic: Standards Compliance / Enterprise Readiness Check (pull_request) Successful in 43s
Generic: Standards Compliance / Repository Health Check (pull_request) Successful in 43s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Generic: Standards Compliance / Compliance Summary (pull_request) Has been cancelled
Deploy workflows in go/npm repos live in the workflows root, not custom/
(mirrors npm repos' npm-publish.yml in root). The sync's curated set does
not include deploy-*, so root placement is not clobbered. Moved: deploy-dev.yml, deploy-mokogitea.yml, deploy-rc.yml
2026-07-13 21:27:36 +00:00
jmiller 56d33c2e3a Merge pull request 'chore(ci): move repo-specific workflows to workflows/custom/' (#779) from chore/move-custom-workflows-to-custom into main
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 53s
Generic: Standards Compliance / Secret Scanning (push) Has been cancelled
Generic: Standards Compliance / License Header Validation (push) Has been cancelled
Generic: Standards Compliance / Repository Structure Validation (push) Has been cancelled
Generic: Standards Compliance / Coding Standards Check (push) Has been cancelled
Generic: Standards Compliance / Version Consistency Check (push) Has been cancelled
Generic: Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Generic: Standards Compliance / Documentation Quality Check (push) Has been cancelled
Generic: Standards Compliance / README Completeness Check (push) Has been cancelled
Generic: Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Generic: Standards Compliance / Script Integrity Validation (push) Has been cancelled
Generic: Standards Compliance / Line Length Check (push) Has been cancelled
Generic: Standards Compliance / File Naming Standards (push) Has been cancelled
Generic: Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Generic: Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Generic: Standards Compliance / Code Duplication Detection (push) Has been cancelled
Generic: Standards Compliance / Dead Code Detection (push) Has been cancelled
Generic: Standards Compliance / File Size Limits (push) Has been cancelled
Generic: Standards Compliance / Binary File Detection (push) Has been cancelled
Generic: Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Generic: Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Generic: Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Generic: Standards Compliance / Broken Link Detection (push) Has been cancelled
Generic: Standards Compliance / API Documentation Coverage (push) Has been cancelled
Generic: Standards Compliance / Accessibility Check (push) Has been cancelled
Generic: Standards Compliance / Performance Metrics (push) Has been cancelled
Generic: Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Generic: Standards Compliance / Repository Health Check (push) Has been cancelled
Generic: Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Generic: Standards Compliance / Compliance Summary (push) Has been cancelled
Deploy MokoGitea / deploy (push) Successful in 4m1s
2026-07-13 21:19:36 +00:00
jmiller 385b96fda7 chore(ci): move repo-specific workflows to workflows/custom/
Generic: Project CI / Lint & Validate (pull_request) Successful in 34s
Generic: Project CI / Tests (pull_request) Successful in 30s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 1m17s
Universal: PR Check / Validate PR (pull_request) Successful in 7s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 1m26s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Standards Compliance / Secret Scanning (pull_request) Failing after 8s
Universal: PR Check / Require Docs Update (pull_request) Failing after 1m8s
Generic: Standards Compliance / License Header Validation (pull_request) Successful in 7s
Generic: Standards Compliance / Repository Structure Validation (pull_request) Successful in 8s
Universal: PR Check / Secret Scan (pull_request) Successful in 1m14s
Generic: Standards Compliance / Coding Standards Check (pull_request) Successful in 8s
Generic: Standards Compliance / Documentation Quality Check (pull_request) Successful in 7s
Generic: Standards Compliance / Workflow Configuration Check (pull_request) Failing after 7s
Generic: Standards Compliance / README Completeness Check (pull_request) Failing after 6s
Generic: Standards Compliance / Script Integrity Validation (pull_request) Successful in 9s
Generic: Standards Compliance / Line Length Check (pull_request) Successful in 16s
Generic: Standards Compliance / File Naming Standards (pull_request) Successful in 6s
Generic: Standards Compliance / Version Consistency Check (pull_request) Successful in 50s
Generic: Standards Compliance / Insecure Code Pattern Detection (pull_request) Successful in 6s
Generic: Standards Compliance / Git Repository Hygiene (pull_request) Successful in 53s
Generic: Standards Compliance / Dead Code Detection (pull_request) Successful in 8s
Generic: Standards Compliance / File Size Limits (pull_request) Successful in 6s
Generic: Standards Compliance / Code Complexity Analysis (pull_request) Successful in 44s
Generic: Standards Compliance / Code Duplication Detection (pull_request) Successful in 43s
Generic: Standards Compliance / TODO/FIXME Tracking (pull_request) Successful in 6s
Generic: Standards Compliance / Dependency Vulnerability Scanning (pull_request) Successful in 43s
Generic: Standards Compliance / Unused Dependencies Check (pull_request) Successful in 42s
Generic: Standards Compliance / API Documentation Coverage (pull_request) Successful in 5s
Generic: Standards Compliance / Broken Link Detection (pull_request) Successful in 8s
Generic: Standards Compliance / Accessibility Check (pull_request) Successful in 5s
Generic: Standards Compliance / Performance Metrics (pull_request) Successful in 6s
Generic: Standards Compliance / Binary File Detection (pull_request) Successful in 1m22s
Generic: Standards Compliance / Terraform Configuration Validation (pull_request) Successful in 11s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Generic: Standards Compliance / Repository Health Check (pull_request) Successful in 44s
Generic: Standards Compliance / Enterprise Readiness Check (pull_request) Successful in 46s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Generic: Standards Compliance / Compliance Summary (pull_request) Has been cancelled
These are repo-specific (not platform-standard) and belong in custom/ so
the workflow sync never distributes/clobbers them. They still run here
(Gitea Actions executes custom/). Moved: deploy-rc.yml
2026-07-13 21:19:28 +00:00
jmiller fab2e2a2e2 Merge pull request 'chore(ci): remove template-only sync workflows from root' (#778) from chore/remove-template-sync-leaks into main
Cascade Main -> Dev / Cascade main -> dev (push) Has been cancelled
Deploy MokoGitea / deploy (push) Has been cancelled
Generic: Standards Compliance / Secret Scanning (push) Has been cancelled
Generic: Standards Compliance / License Header Validation (push) Has been cancelled
Generic: Standards Compliance / Repository Structure Validation (push) Has been cancelled
Generic: Standards Compliance / Coding Standards Check (push) Has been cancelled
Generic: Standards Compliance / Version Consistency Check (push) Has been cancelled
Generic: Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Generic: Standards Compliance / Documentation Quality Check (push) Has been cancelled
Generic: Standards Compliance / README Completeness Check (push) Has been cancelled
Generic: Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Generic: Standards Compliance / Script Integrity Validation (push) Has been cancelled
Generic: Standards Compliance / Line Length Check (push) Has been cancelled
Generic: Standards Compliance / File Naming Standards (push) Has been cancelled
Generic: Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Generic: Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Generic: Standards Compliance / Code Duplication Detection (push) Has been cancelled
Generic: Standards Compliance / Dead Code Detection (push) Has been cancelled
Generic: Standards Compliance / File Size Limits (push) Has been cancelled
Generic: Standards Compliance / Binary File Detection (push) Has been cancelled
Generic: Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Generic: Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Generic: Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Generic: Standards Compliance / Broken Link Detection (push) Has been cancelled
Generic: Standards Compliance / API Documentation Coverage (push) Has been cancelled
Generic: Standards Compliance / Accessibility Check (push) Has been cancelled
Generic: Standards Compliance / Performance Metrics (push) Has been cancelled
Generic: Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Generic: Standards Compliance / Repository Health Check (push) Has been cancelled
Generic: Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Generic: Standards Compliance / Compliance Summary (push) Has been cancelled
2026-07-13 20:45:08 +00:00
jmiller c537c63e98 chore(ci): remove template-only sync workflows from root
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 1m10s
Generic: Project CI / Lint & Validate (pull_request) Successful in 29s
Generic: Project CI / Tests (pull_request) Successful in 28s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 45s
Universal: PR Check / Validate PR (pull_request) Successful in 7s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Standards Compliance / Secret Scanning (pull_request) Failing after 7s
Generic: Standards Compliance / License Header Validation (pull_request) Successful in 7s
Universal: PR Check / Require Docs Update (pull_request) Failing after 45s
Generic: Standards Compliance / Repository Structure Validation (pull_request) Successful in 6s
Universal: PR Check / Secret Scan (pull_request) Successful in 48s
Generic: Standards Compliance / Coding Standards Check (pull_request) Successful in 8s
Generic: Standards Compliance / Workflow Configuration Check (pull_request) Failing after 6s
Generic: Standards Compliance / Documentation Quality Check (pull_request) Successful in 5s
Generic: Standards Compliance / README Completeness Check (pull_request) Failing after 6s
Generic: Standards Compliance / Script Integrity Validation (pull_request) Successful in 6s
Generic: Standards Compliance / Line Length Check (pull_request) Successful in 13s
Generic: Standards Compliance / File Naming Standards (pull_request) Successful in 6s
Generic: Standards Compliance / Version Consistency Check (pull_request) Successful in 43s
Generic: Standards Compliance / Insecure Code Pattern Detection (pull_request) Successful in 6s
Generic: Standards Compliance / Git Repository Hygiene (pull_request) Successful in 37s
Generic: Standards Compliance / Dead Code Detection (pull_request) Successful in 7s
Generic: Standards Compliance / File Size Limits (pull_request) Successful in 6s
Generic: Standards Compliance / Code Complexity Analysis (pull_request) Successful in 41s
Generic: Standards Compliance / Code Duplication Detection (pull_request) Successful in 40s
Generic: Standards Compliance / TODO/FIXME Tracking (pull_request) Successful in 6s
Generic: Standards Compliance / Dependency Vulnerability Scanning (pull_request) Successful in 43s
Generic: Standards Compliance / Unused Dependencies Check (pull_request) Successful in 40s
Generic: Standards Compliance / API Documentation Coverage (pull_request) Successful in 6s
Generic: Standards Compliance / Broken Link Detection (pull_request) Successful in 8s
Generic: Standards Compliance / Binary File Detection (pull_request) Successful in 1m21s
Generic: Standards Compliance / Accessibility Check (pull_request) Successful in 6s
Generic: Standards Compliance / Performance Metrics (pull_request) Successful in 6s
Generic: Standards Compliance / Terraform Configuration Validation (pull_request) Successful in 10s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Generic: Standards Compliance / Enterprise Readiness Check (pull_request) Successful in 46s
Generic: Standards Compliance / Repository Health Check (pull_request) Successful in 46s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Generic: Standards Compliance / Compliance Summary (pull_request) Has been cancelled
sync-on-merge.yml and workflow-sync-trigger.yml are template-only (gated
if: Template-*), dead no-ops in this child repo, inherited at scaffold time.
sync-on-merge.yml is also broken. The real sync lives in the templates'
workflows/custom/.
2026-07-13 20:44:53 +00:00
jmiller 0fc4adf1a7 chore: sync standards-compliance.yml from Template-Generic [skip ci] 2026-07-13 19:51:27 +00:00
jmiller affba0a2cd chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-13 16:21:58 +00:00
jmiller 66017e1668 chore: sync cascade-dev.yml from Template-Generic [skip ci] 2026-07-13 16:21:51 +00:00
jmiller 0a66dacb86 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-13 16:21:45 +00:00
jmiller ae1aa3e21a chore: sync standards-compliance.yml from Template-Generic [skip ci] 2026-07-13 15:58:20 +00:00
jmiller f2dd391bca chore: sync workflow-sync-trigger.yml from Template-Generic [skip ci] 2026-07-13 15:48:35 +00:00
jmiller 485d6be31c chore: sync version-set.yml from Template-Generic [skip ci] 2026-07-13 15:48:27 +00:00
jmiller 2d42b4e475 chore: sync sync-on-merge.yml from Template-Generic [skip ci] 2026-07-13 15:48:19 +00:00
jmiller b5ce7fadcc chore: sync repo-health.yml from Template-Generic [skip ci] 2026-07-13 15:48:11 +00:00
jmiller 4972cf71bc chore: sync rc-revert.yml from Template-Generic [skip ci] 2026-07-13 15:48:03 +00:00
jmiller 9e8d4c43bb chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-13 15:47:55 +00:00
jmiller c0c121dfb5 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-13 15:47:47 +00:00
jmiller 5bc475e8f5 chore: sync notify.yml from Template-Generic [skip ci] 2026-07-13 15:47:40 +00:00
jmiller 1f0fe7012d chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-13 15:47:31 +00:00
jmiller b902244949 chore: sync gitleaks.yml from Template-Generic [skip ci] 2026-07-13 15:47:24 +00:00
jmiller c37ada7874 chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-13 15:47:16 +00:00
jmiller 9496c7c42d chore: sync ci-issue-reporter.yml from Template-Generic [skip ci] 2026-07-13 15:47:08 +00:00
jmiller a049052e5a chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-13 15:47:01 +00:00
jmiller fc66f8968f chore: sync cascade-dev.yml from Template-Generic [skip ci] 2026-07-13 15:46:55 +00:00
jmiller b0885f6da3 chore: sync branch-cleanup.yml from Template-Generic [skip ci] 2026-07-13 15:46:48 +00:00
jmiller 1a2e33abb3 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-13 15:46:42 +00:00
jmiller 6aeb087613 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-07-13 15:46:35 +00:00
jmiller 94e6030e58 chore: sync standards-compliance.yml from Template-Generic [skip ci] 2026-07-13 15:28:50 +00:00
jmiller 02c2033caa chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-13 09:28:24 +00:00
jmiller 9edfeb6075 chore: sync notify.yml from Template-Generic [skip ci] 2026-07-13 09:28:19 +00:00
jmiller ada91a9bc1 Merge pull request 'chore(sync): cascade main -> dev' (#776) from main into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 1m9s
Deploy MokoGitea (Dev) / Build & Deploy to Dev (push) Successful in 3m57s
2026-07-13 00:47:23 +00:00
jmiller 3ce6fd3e08 Merge pull request 'fix(branding): app icon follows the Nav Icon upload (#773)' (#774) from fix/app-icon-follows-nav-icon into main
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 3s
Generic: Project CI / Lint & Validate (pull_request) Successful in 28s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Generic: Project CI / Tests (pull_request) Successful in 29s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Successful in 8s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 41s
Deploy MokoGitea / deploy (push) Successful in 5m3s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-13 00:43:38 +00:00
jmiller dc14a3fcfc Merge remote-tracking branch 'origin/main' into fix/app-icon-follows-nav-icon
Generic: Project CI / Lint & Validate (pull_request) Successful in 33s
Generic: Project CI / Tests (pull_request) Successful in 39s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 1m41s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 1m10s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Failing after 43s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Successful in 7s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 30s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 1m54s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
# Conflicts:
#	CHANGELOG.md
2026-07-12 19:42:54 -05:00
jmiller f991f209d1 Merge pull request 'chore(sync): cascade main -> dev' (#775) from main into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 1m12s
Deploy MokoGitea (Dev) / Build & Deploy to Dev (push) Failing after 4m36s
2026-07-13 00:41:18 +00:00
jmiller 6093300fbb Merge pull request 'fix(metadata): derive org from org profile instead of storing it (#771)' (#772) from fix/metadata-org-derived-from-profile into main
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 5s
Generic: Project CI / Lint & Validate (pull_request) Successful in 31s
Generic: Project CI / Tests (pull_request) Successful in 31s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Successful in 8s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 47s
Deploy MokoGitea / deploy (push) Successful in 5m48s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-13 00:40:52 +00:00
jmiller 793e4885e8 ci: re-trigger checks after runner recovery
Generic: Project CI / Tests (pull_request) Successful in 30s
Generic: Project CI / Lint & Validate (pull_request) Successful in 32s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 31s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Successful in 8s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 55s
Universal: PR Check / Require Docs Update (pull_request) Failing after 34s
Universal: PR Check / Secret Scan (pull_request) Successful in 35s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 1m9s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
No code change. The prior run was canceled at 0s because all ubuntu-latest
runners were offline; this re-fires CI now that a runner is back. Ref #771.
2026-07-12 19:37:51 -05:00
jmiller f4be31183f refactor(branding): write each icon target independently on upload
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 32s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 24s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Project CI / Lint & Validate (pull_request) Successful in 34s
Generic: Project CI / Tests (pull_request) Successful in 34s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Successful in 7s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Require Docs Update (pull_request) Failing after 25s
Universal: PR Check / Secret Scan (pull_request) Successful in 26s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Rewind the uploaded stream between targets and write/close each file in
turn instead of a shared io.MultiWriter, so a failure writing a later
target (e.g. logo.png) can never leave an earlier one (logo-small.png)
truncated. Addresses review feedback on #774.
2026-07-12 19:02:14 -05:00
jmiller 3d0cb7d98c fix(branding): app icon follows the Nav Icon upload
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 38s
Universal: Build & Release / Promote to RC (pull_request) Failing after 9s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Has been cancelled
Generic: Project CI / Tests (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Universal: PR Check / Require Docs Update (pull_request) Has been cancelled
Universal: PR Check / Wiki Update Reminder (pull_request) Has been cancelled
Universal: PR Check / Secret Scan (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Generic: Repo Health / Access control (pull_request) Has been cancelled
Generic: Repo Health / Site Health (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The app icon (logo.png) is the PWA/web-manifest icon and the navbar
fallback, but had no Branding control, so it stayed the shipped default
even on a fully branded instance. Uploading the Nav Icon now also writes
logo.png (single io.MultiWriter pass), and resetting the Nav Icon reverts
both to the built-in default.

Closes #773
2026-07-12 18:45:11 -05:00
jmiller 7f436128fd fix(metadata): derive org from org profile instead of storing it
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 29s
Universal: Build & Release / Promote to RC (pull_request) Failing after 8s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Has been cancelled
Generic: Project CI / Tests (pull_request) Has been cancelled
PR RC Release / Build RC Release (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Universal: PR Check / Require Docs Update (pull_request) Has been cancelled
Universal: PR Check / Wiki Update Reminder (pull_request) Has been cancelled
Universal: PR Check / Secret Scan (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Generic: Repo Health / Access control (pull_request) Has been cancelled
Generic: Repo Health / Site Health (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The repo metadata org field was a stored, editable value that snapshotted
the owner name and could drift when an organization was renamed. It is now
derived from the org profile (repository owner) on read and is read-only.

- models/repo/repo.go: add Repository.DerivedOrgName (owner FullName, falling
  back to the handle, then the denormalized OwnerName)
- models/repo/repo_manifest.go: drop the Org struct field
- models/migrations/v1_27/v369.go + migrations.go: migration #368 drops the
  repo_manifest.org column
- routers/api/v1/repo/manifest.go: derive org in the response, ignore it on write
- routers/web/repo/setting/metadata.go + templates: show org read-only (derived)
- services/updateserver/joomla.go: use DerivedOrgName for the feed maintainer

Closes #771
2026-07-12 18:35:31 -05:00
jmiller 010d3dcbcf chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-06 17:04:06 +00:00
jmiller 8242e5713a fix(ci): robust prod deploy workflow (#758) [skip ci]
Land deploy-mokogitea.yml robustness fix on main. [skip ci] — workflow-file-only change; no rebuild/redeploy needed (prod already live on stable-289 from #733).
2026-07-06 15:57:46 +00:00
jmiller a7220ddb2b fix(ci): robust prod deploy — drop dev-health gate, no tier-clobbering sed, rm -f before recreate
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 42s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Successful in 8s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 36s
Generic: Project CI / Tests (pull_request) Successful in 36s
Universal: PR Check / Secret Scan (pull_request) Successful in 56s
Universal: PR Check / Require Docs Update (pull_request) Failing after 1m11s
PR RC Release / Build RC Release (pull_request) Successful in 1m13s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The prod deploy (deploy-mokogitea.yml, on push to main) failed the #733 release and
silently corrupted the shared compose. Three fixes:
- Removed the 'Verify dev environment is healthy' gate: it curled git.dev and exit 1
  on failure, so a dev blip false-negatives the PROD deploy (wrong-tier gate; the
  dev->rc->main pipeline + RC env is the real gate).
- Replaced 'sed s|mokogitea:...|:$TAG|' (matched ALL mokogitea service lines and
  clobbered the dev+rc ${MOKOGITEA_*_TAG} env-vars with the prod tag) with the
  env-var pattern: env $TAG_ENV=$TAG docker compose up -- drives only the target
  service, no sed.
- Added 'docker rm -f $CONTAINER' + '-p gitea-dev' + '--force-recreate' before the
  compose up, fixing the 'Container name /mokogitea already in use' conflict.

Aligns deploy-mokogitea.yml with the fixed deploy-dev/deploy-rc pattern. Host compose
was separately restored to env-var form (the bad run had clobbered dev+rc tags).
Long-term: cut over Template-Go#5 deploy-prod.yml. Refs #733, #752.

Claude-Session: https://claude.ai/code/session_01Wsno14cxE49MstXFs9G5KT
2026-07-06 10:55:58 -05:00
31 changed files with 2954 additions and 250 deletions
+3 -3
View File
@@ -4,7 +4,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release # INGROUP: MokoCLI.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/auto-bump.yml # PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00 # VERSION: 09.02.00
@@ -44,7 +44,7 @@ jobs:
token: ${{ secrets.MOKOGITEA_TOKEN }} token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1 fetch-depth: 1
- name: Setup mokocli tools - name: Setup MokoCLI tools
run: | run: |
if ! command -v composer &> /dev/null; then 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 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
@@ -53,7 +53,7 @@ jobs:
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV" echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
else else
git clone --depth 1 --branch main --quiet \ git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/MokoCLI.git" \ "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \
/tmp/mokocli /tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV" echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
+58 -27
View File
@@ -4,17 +4,17 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release # INGROUP: MokoCLI.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/auto-release.yml # PATH: /.mokogitea/workflows/auto-release.yml
# VERSION: 05.01.00 # VERSION: 05.01.00
# BRIEF: Universal build & release detects platform from manifest.xml # BRIEF: Universal build & release detects platform from metadata API
# #
# +=======================================================================+ # +=======================================================================+
# | UNIVERSAL BUILD & RELEASE PIPELINE | # | UNIVERSAL BUILD & RELEASE PIPELINE |
# +=======================================================================+ # +=======================================================================+
# | | # | |
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. | # | Reads metadata API (joomla|dolibarr|generic) to branch logic. |
# | | # | |
# | Platform-specific: | # | Platform-specific: |
# | joomla: XML manifest, type-prefixed packages | # | joomla: XML manifest, type-prefixed packages |
@@ -81,7 +81,7 @@ jobs:
fetch-depth: 1 fetch-depth: 1
submodules: recursive submodules: recursive
- name: Setup mokocli tools - name: Setup MokoCLI tools
env: env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
@@ -95,7 +95,7 @@ jobs:
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 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 fi
rm -rf /tmp/mokocli rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet composer install --no-dev --no-interaction --quiet
@@ -115,20 +115,17 @@ jobs:
SRC_SHA=$(printf '%s' "$SRC_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['commit']['id'])" 2>/dev/null || true) SRC_SHA=$(printf '%s' "$SRC_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['commit']['id'])" 2>/dev/null || true)
[ -n "$SRC_SHA" ] || { echo "::error::Could not resolve HEAD of ${FROM}"; exit 1; } [ -n "$SRC_SHA" ] || { echo "::error::Could not resolve HEAD of ${FROM}"; exit 1; }
# Point rc at the source commit. If rc already exists (a protected branch that # Point rc at the source commit via git push. Gitea's git/refs PATCH API
# cannot be deleted), force-update its ref in place instead of delete+recreate: # returns HTTP 405 on ANY protected branch (force or not, even for a user in
# deleting a protected branch fails, which then makes the recreate return HTTP 409. # the force-push allowlist), so it cannot move a protected rc. git push honors
if curl -sf -o /dev/null -H "$AUTH" "${API_BASE}/branches/rc"; then # the push + force-push allowlists and creates rc if it is absent.
echo "rc exists - force-updating to ${FROM} (${SRC_SHA})" PUSH_URL="https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@${MOKOGITEA_URL#https://}/${GITEA_ORG}/${GITEA_REPO}.git"
curl -sf -X PATCH -H "$AUTH" -H "Content-Type: application/json" \ git config --global user.name "mokogitea-actions[bot]"
"${API_BASE}/git/refs/heads/rc" -d "{\"sha\":\"${SRC_SHA}\",\"force\":true}" \ git config --global user.email "actions@mokoconsulting.tech"
|| { echo "::error::Failed to force-update rc (CI token needs force-push on the protected rc branch)"; exit 1; } git fetch --no-tags "$PUSH_URL" "${FROM}"
else git push --force "$PUSH_URL" "FETCH_HEAD:refs/heads/rc" \
echo "Creating rc from ${FROM}" || { echo "::error::Failed to point rc at ${FROM} (${SRC_SHA}) via git push"; exit 1; }
curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \ echo "rc set to ${FROM} (${SRC_SHA})"
"${API_BASE}/branches" -d "{\"new_branch_name\":\"rc\",\"old_branch_name\":\"${FROM}\"}" \
|| { echo "::error::Failed to create rc from ${FROM}"; exit 1; }
fi
# Repoint the PR at rc, then delete the old source branch (non-fatal). # Repoint the PR at rc, then delete the old source branch (non-fatal).
if [ -n "$PR" ]; then if [ -n "$PR" ]; then
@@ -231,7 +228,7 @@ jobs:
fi fi
echo "No conflict markers found" echo "No conflict markers found"
- name: Setup mokocli tools - name: Setup MokoCLI tools
env: env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
@@ -246,7 +243,7 @@ jobs:
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 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 fi
rm -rf /tmp/mokocli rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet composer install --no-dev --no-interaction --quiet
@@ -377,13 +374,47 @@ jobs:
if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then
DATE=$(date +%Y-%m-%d) DATE=$(date +%Y-%m-%d)
python3 -c " python3 -c "
import sys import sys, re
version, date = sys.argv[1], sys.argv[2] version, date = sys.argv[1], sys.argv[2]
content = open('CHANGELOG.md').read() lines = open('CHANGELOG.md').read().split('\n')
old = '## [Unreleased]' h2 = re.compile(r'^##\s+\[([^\]]+)\]')
new = f'## [Unreleased]\n\n## [{version}] --- {date}' header, sections, cur = [], [], None
content = content if ('## [' + version + ']') in content else content.replace(old, new, 1) for ln in lines:
open('CHANGELOG.md', 'w').write(content) m = h2.match(ln)
if m:
if cur: sections.append(cur)
cur = {'label': m.group(1).strip(), 'head': ln, 'body': []}
elif cur is None:
header.append(ln)
else:
cur['body'].append(ln)
if cur: sections.append(cur)
def nonempty(b): return any(x.strip() for x in b)
def trim(b):
b = b[:]
while b and not b[0].strip(): b.pop(0)
while b and not b[-1].strip(): b.pop()
return b
unreleased, order, bykey = [], [], {}
for s in sections:
key = s['label'].lower()
if key == 'unreleased':
if nonempty(s['body']): unreleased += s['body']
continue
if not nonempty(s['body']): continue # drop blank release sections
if key in bykey: bykey[key]['body'] += [''] + s['body'] # merge duplicate heading (never drop content)
else: bykey[key] = s; order.append(key)
rest, seen = [bykey[k] for k in order], set(order)
out = []
htxt = '\n'.join(header).rstrip()
if htxt: out += [htxt, '']
out += ['## [Unreleased]', '']
promote = bool(unreleased) and version.lower() not in seen
if unreleased and not promote: out += trim(unreleased) + ['']
if promote: out += ['## [%s] --- %s' % (version, date), ''] + trim(unreleased) + ['']
for s in rest: out += [s['head'], ''] + trim(s['body']) + ['']
res = re.sub(r'\n{3,}', '\n\n', '\n'.join(out)).rstrip('\n') + '\n'
open('CHANGELOG.md', 'w').write(res)
" "$VERSION" "$DATE" " "$VERSION" "$DATE"
git add CHANGELOG.md git add CHANGELOG.md
git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Universal # INGROUP: MokoCLI.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/branch-cleanup.yml # PATH: /.mokogitea/workflows/branch-cleanup.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
+107 -23
View File
@@ -4,11 +4,11 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Cascade # INGROUP: MokoCLI.Cascade
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/cascade-dev.yml # PATH: /.mokogitea/workflows/cascade-dev.yml
# VERSION: 02.00.00 # VERSION: 02.01.00
# BRIEF: Cascade main -> dev via PR; auto-merge only if conflict-free, else notify # BRIEF: Cascade main -> dev; auto-merge clean, auto-resolve VERSION-stamp-only conflicts, else notify
name: "Cascade Main -> Dev" name: "Cascade Main -> Dev"
@@ -16,6 +16,10 @@ on:
push: push:
branches: branches:
- main - main
# Daily safety net: catches drift even when main only received [skip ci] pushes
# (which never fire the push trigger above). Off-round minute to avoid a fleet-wide spike.
schedule:
- cron: '23 7 * * *'
workflow_dispatch: workflow_dispatch:
permissions: permissions:
@@ -33,7 +37,13 @@ jobs:
name: Cascade main -> dev name: Cascade main -> dev
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Open main -> dev PR (auto-merge if clean, else notify) - name: Checkout (full history for merge/resolve)
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Cascade main -> dev (auto-resolve version stamps, else notify)
env: env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }} REPO: ${{ github.repository }}
@@ -41,7 +51,7 @@ jobs:
set -uo pipefail set -uo pipefail
API="${MOKOGITEA_URL}/api/v1/repos/${REPO}" API="${MOKOGITEA_URL}/api/v1/repos/${REPO}"
AUTH="Authorization: token ${TOKEN}" AUTH="Authorization: token ${TOKEN}"
jqnum() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; } jqget() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; }
# 0. dev must exist # 0. dev must exist
if ! curl -sf -H "$AUTH" "${API}/branches/dev" >/dev/null 2>&1; then if ! curl -sf -H "$AUTH" "${API}/branches/dev" >/dev/null 2>&1; then
@@ -61,8 +71,8 @@ jobs:
| python3 -c "import sys,json; d=json.load(sys.stdin); print(next((str(p['number']) for p in d if p.get('head',{}).get('ref')=='main'), ''))" 2>/dev/null || echo "") | python3 -c "import sys,json; d=json.load(sys.stdin); print(next((str(p['number']) for p in d if p.get('head',{}).get('ref')=='main'), ''))" 2>/dev/null || echo "")
if [ -z "$PR" ]; then if [ -z "$PR" ]; then
RESP=$(curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/pulls" \ RESP=$(curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/pulls" \
-d '{"head":"main","base":"dev","title":"chore(sync): cascade main -> dev","body":"Automated cascade of main into dev. Auto-merges only if conflict-free; otherwise left open for manual resolution."}') -d '{"head":"main","base":"dev","title":"chore(sync): cascade main -> dev","body":"Automated cascade of main into dev. Auto-merges when conflict-free, auto-resolves VERSION-stamp-only conflicts, otherwise left open for manual resolution."}')
PR=$(printf '%s' "$RESP" | jqnum number) PR=$(printf '%s' "$RESP" | jqget number)
if [ -z "$PR" ]; then if [ -z "$PR" ]; then
echo "::warning::Could not open cascade PR: $RESP"; exit 0 echo "::warning::Could not open cascade PR: $RESP"; exit 0
fi fi
@@ -71,15 +81,6 @@ jobs:
echo "Reusing open cascade PR #${PR}" echo "Reusing open cascade PR #${PR}"
fi fi
# 3. wait for MokoGitea to compute mergeability (conflict detection)
MERGEABLE=""
for _ in 1 2 3 4 5 6; do
MERGEABLE=$(curl -sf -H "$AUTH" "${API}/pulls/${PR}" | jqnum mergeable)
case "$MERGEABLE" in True|False) break ;; esac
sleep 3
done
echo "mergeable=${MERGEABLE}"
notify() { notify() {
curl -sS \ curl -sS \
-H "Title: ${REPO}: dev cascade needs manual merge" \ -H "Title: ${REPO}: dev cascade needs manual merge" \
@@ -90,17 +91,100 @@ jobs:
"${NTFY_URL}/${NTFY_TOPIC}" || true "${NTFY_URL}/${NTFY_TOPIC}" || true
} }
# 4. auto-merge only if conflict-free; otherwise notify # 3. wait for MokoGitea to compute mergeability (conflict detection)
MERGEABLE=""
for _ in 1 2 3 4 5 6; do
MERGEABLE=$(curl -sf -H "$AUTH" "${API}/pulls/${PR}" | jqget mergeable)
case "$MERGEABLE" in True|False) break ;; esac
sleep 3
done
echo "mergeable=${MERGEABLE}"
# 4a. conflict-free -> merge via API (existing behaviour)
if [ "$MERGEABLE" = "True" ]; then if [ "$MERGEABLE" = "True" ]; then
CODE=$(curl -s -o /tmp/merge.json -w "%{http_code}" -H "$AUTH" -H "Content-Type: application/json" \ CODE=$(curl -s -o /tmp/merge.json -w "%{http_code}" -H "$AUTH" -H "Content-Type: application/json" \
-X POST "${API}/pulls/${PR}/merge" -d '{"Do":"merge","merge_when_checks_succeed":true}') -X POST "${API}/pulls/${PR}/merge" -d '{"Do":"merge","merge_when_checks_succeed":true}')
if [ "$CODE" -ge 200 ] && [ "$CODE" -lt 300 ]; then if [ "$CODE" -ge 200 ] && [ "$CODE" -lt 300 ]; then
echo "Cascade PR #${PR} merged (or scheduled to merge when checks pass)." echo "Cascade PR #${PR} merged (or scheduled to merge when checks pass)."
else exit 0
echo "::warning::Auto-merge returned HTTP ${CODE}: $(cat /tmp/merge.json)"
notify "could not be auto-merged (HTTP ${CODE})."
fi fi
else echo "::warning::Auto-merge returned HTTP ${CODE}: $(cat /tmp/merge.json)"
echo "::warning::Cascade PR #${PR} has conflicts (mergeable=${MERGEABLE}); sending notification." notify "could not be auto-merged (HTTP ${CODE})."
notify "has conflicts and cannot be merged automatically." exit 0
fi fi
# 4b. conflicts -> try to auto-resolve if they are ONLY VERSION-stamp lines.
echo "PR not cleanly mergeable; checking whether conflicts are VERSION-stamp-only..."
git config user.name "MokoGitea Cascade"
git config user.email "actions@mokoconsulting.tech"
git fetch --quiet origin main dev
git checkout -B dev origin/dev
if git merge --no-ff --no-commit origin/main >/dev/null 2>&1; then
# Became clean at git level (e.g. mergeability was still computing) -> commit + push.
git commit -m "chore(sync): cascade main -> dev [skip ci]" >/dev/null
git push origin dev
echo "Cascade merged cleanly at git level and pushed to dev."
exit 0
fi
CONFLICTS=$(git diff --name-only --diff-filter=U)
echo "Conflicted files:"; echo "${CONFLICTS}"
# A conflict is "stamp-only" when every line inside every conflict block matches
# a version-stamp pattern (VERSION: header, <version> element, or CHANGELOG title).
is_stamp_only() {
awk '
/^<<<<<<< / { inc=1; next }
inc && /^=======$/ { next }
/^>>>>>>> / { inc=0; next }
inc { if ($0 !~ /(VERSION:|<version>|# Changelog)/) { bad=1 } }
END { exit(bad ? 1 : 0) }
' "$1"
}
# Resolve a stamp-only file by keeping dev (ours) for the conflicting lines,
# preserving all auto-merged content around them.
keep_ours() {
awk '
/^<<<<<<< / { inc=1; side="ours"; next }
inc && /^=======$/ { side="theirs"; next }
/^>>>>>>> / { inc=0; next }
{ if (!inc) { print; next } if (side=="ours") print }
' "$1" > "$1.resolved" && mv "$1.resolved" "$1"
}
ALL_STAMP=1
for f in ${CONFLICTS}; do
if ! is_stamp_only "$f"; then
echo "::notice::$f has non-stamp conflicts -> manual resolution required."
ALL_STAMP=0; break
fi
done
if [ "$ALL_STAMP" != "1" ]; then
git merge --abort || true
notify "has non-version-stamp conflicts and cannot be auto-resolved."
exit 0
fi
echo "All conflicts are VERSION-stamp-only; resolving in favour of dev."
for f in ${CONFLICTS}; do
keep_ours "$f"
git add "$f"
done
# Best-effort: normalise stamps to dev's version if mokocli is available.
if [ -f /opt/mokocli/cli/version_check.php ]; then
php /opt/mokocli/cli/version_check.php --fix || true
git add -A
fi
git commit -m "chore(sync): cascade main -> dev (auto-resolved version stamps) [skip ci]" >/dev/null
git push origin dev
echo "Cascade auto-resolved and pushed to dev."
# Close the now-redundant PR (its changes are in dev) with an explanatory comment.
curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/issues/${PR}/comments" \
-d '{"body":"Auto-resolved VERSION-stamp-only conflicts and pushed the merge to dev. Closing."}' >/dev/null || true
curl -s -H "$AUTH" -H "Content-Type: application/json" -X PATCH "${API}/pulls/${PR}" \
-d '{"state":"closed"}' >/dev/null || true
+2 -2
View File
@@ -4,7 +4,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.CI # INGROUP: MokoCLI.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/ci-generic.yml # PATH: /.mokogitea/workflows/ci-generic.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
@@ -131,7 +131,7 @@ jobs:
test: test:
name: Tests name: Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
# Independent job (no `needs: lint`): the Gitea Actions scheduler does not # Independent job (no `needs: lint`): the MokoGitea Actions scheduler does not
# offer the dependent 2nd job of a needs-chain to runners, so it stalls in # offer the dependent 2nd job of a needs-chain to runners, so it stalls in
# "waiting" and is reaped by ABANDONED_JOB_TIMEOUT. Guard template repos # "waiting" and is reaped by ABANDONED_JOB_TIMEOUT. Guard template repos
# directly (same condition lint uses) instead of gating on lint's result. # directly (same condition lint uses) instead of gating on lint's result.
+2 -2
View File
@@ -4,7 +4,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal # INGROUP: MokoCLI.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/ci-issue-reporter.yml # PATH: /.mokogitea/workflows/ci-issue-reporter.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
@@ -52,7 +52,7 @@ jobs:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: | run: |
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}" MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 --filter=blob:none --sparse "${MOKOGITEA_URL}/MokoConsulting/MokoCLI.git" /tmp/mokocli git clone --depth 1 --filter=blob:none --sparse "${MOKOGITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
cd /tmp/mokocli && git sparse-checkout set cli/ci_issue_reporter.sh cd /tmp/mokocli && git sparse-checkout set cli/ci_issue_reporter.sh
- name: Report CI failure - name: Report CI failure
+2 -2
View File
@@ -4,8 +4,8 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Maintenance # INGROUP: MokoCLI.Maintenance
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards # REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/cleanup.yml # PATH: /.mokogitea/workflows/cleanup.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: Scheduled cleanup — delete merged branches and old workflow runs # BRIEF: Scheduled cleanup — delete merged branches and old workflow runs
@@ -39,17 +39,10 @@ jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Verify dev environment is healthy # NOTE: removed a "Verify dev environment is healthy" gate that curled
run: | # git.dev and `exit 1` on failure — gating a PROD deploy on a live DEV
echo "Checking git.dev.mokoconsulting.tech health..." # health check is a cross-tier false-negative (a transient dev blip blocked
if curl -sf --max-time 10 https://git.dev.mokoconsulting.tech/api/healthz; then # prod). Pre-prod validation is the dev -> rc -> main pipeline + RC env.
echo " Dev environment is healthy — proceeding with production deploy"
else
echo "::error::Dev environment is NOT healthy — blocking production deploy"
echo "Deploy to dev first (push to dev branch) and verify it passes before merging to main."
exit 1
fi
- name: Checkout source (for version detection) - name: Checkout source (for version detection)
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@@ -66,17 +59,19 @@ jobs:
ENV="${{ github.event.inputs.environment }}" ENV="${{ github.event.inputs.environment }}"
fi fi
if [ "$ENV" = "production" ]; then if [ "$ENV" = "production" ]; then
echo "compose_dir=/opt/gitea" >> $GITHUB_OUTPUT echo "compose_dir=/opt/gitea-dev" >> $GITHUB_OUTPUT
echo "container=mokogitea" >> $GITHUB_OUTPUT echo "container=mokogitea" >> $GITHUB_OUTPUT
echo "source_dir=/opt/gitea/source" >> $GITHUB_OUTPUT echo "source_dir=/opt/gitea/source" >> $GITHUB_OUTPUT
echo "branch=main" >> $GITHUB_OUTPUT echo "branch=main" >> $GITHUB_OUTPUT
echo "tag=$VERSION" >> $GITHUB_OUTPUT echo "tag=$VERSION" >> $GITHUB_OUTPUT
echo "tag_env=MOKOGITEA_TAG" >> $GITHUB_OUTPUT
else else
echo "compose_dir=/opt/gitea-dev" >> $GITHUB_OUTPUT echo "compose_dir=/opt/gitea-dev" >> $GITHUB_OUTPUT
echo "container=mokogitea-dev" >> $GITHUB_OUTPUT echo "container=mokogitea-dev" >> $GITHUB_OUTPUT
echo "source_dir=/opt/gitea-dev/source" >> $GITHUB_OUTPUT echo "source_dir=/opt/gitea-dev/source" >> $GITHUB_OUTPUT
echo "branch=dev" >> $GITHUB_OUTPUT echo "branch=dev" >> $GITHUB_OUTPUT
echo "tag=$VERSION-dev" >> $GITHUB_OUTPUT echo "tag=$VERSION-dev" >> $GITHUB_OUTPUT
echo "tag_env=MOKOGITEA_DEV_TAG" >> $GITHUB_OUTPUT
fi fi
- name: Write deploy key - name: Write deploy key
@@ -95,6 +90,7 @@ jobs:
SOURCE_DIR: ${{ steps.config.outputs.source_dir }} SOURCE_DIR: ${{ steps.config.outputs.source_dir }}
COMPOSE_DIR: ${{ steps.config.outputs.compose_dir }} COMPOSE_DIR: ${{ steps.config.outputs.compose_dir }}
CONTAINER: ${{ steps.config.outputs.container }} CONTAINER: ${{ steps.config.outputs.container }}
TAG_ENV: ${{ steps.config.outputs.tag_env }}
run: | run: |
HEALTH_FMT='${{ '{{' }}.State.Health.Status${{ '}}' }}' HEALTH_FMT='${{ '{{' }}.State.Health.Status${{ '}}' }}'
IMAGE_FMT='Image: ${{ '{{' }}.Config.Image${{ '}}' }}' IMAGE_FMT='Image: ${{ '{{' }}.Config.Image${{ '}}' }}'
@@ -134,8 +130,12 @@ jobs:
echo 'Restarting container...' echo 'Restarting container...'
cd $COMPOSE_DIR cd $COMPOSE_DIR
sed -i 's|${{ env.IMAGE }}:[^ ]*|${{ env.IMAGE }}:$TAG|' docker-compose.yml # Drive ONLY the target service's tag via its compose env-var (no sed —
docker compose up -d $CONTAINER # a blanket 'sed s|mokogitea:...|' clobbered the dev + rc service tags too).
# Remove any lingering fixed-name container first (avoids the "name already
# in use" conflict), then force-recreate under the shared compose project.
docker rm -f $CONTAINER 2>/dev/null || true
env $TAG_ENV="$TAG" docker compose -p gitea-dev up -d --force-recreate $CONTAINER
echo 'Health check...' echo 'Health check...'
for i in 1 2 3 4 5 6 7 8; do for i in 1 2 3 4 5 6 7 8; do
+2 -2
View File
@@ -4,8 +4,8 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Security # INGROUP: MokoCLI.Security
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API # REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/gitleaks.yml # PATH: /.mokogitea/workflows/gitleaks.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens # BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Automation # INGROUP: MokoCLI.Automation
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: Auto-create feature branch when an issue is opened # BRIEF: Auto-create feature branch when an issue is opened
+6 -6
View File
@@ -4,8 +4,8 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Notifications # INGROUP: MokoCLI.Notifications
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards # REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /.mokogitea/workflows/notify.yml # PATH: /.mokogitea/workflows/notify.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
# BRIEF: Push notifications via ntfy on release success or workflow failure # BRIEF: Push notifications via ntfy on release success or workflow failure
@@ -46,13 +46,13 @@ jobs:
WORKFLOW="${{ github.event.workflow_run.name }}" WORKFLOW="${{ github.event.workflow_run.name }}"
URL="${{ github.event.workflow_run.html_url }}" URL="${{ github.event.workflow_run.html_url }}"
curl -sS \ curl -sS --retry 3 --retry-connrefused --retry-delay 2 --max-time 20 \
-H "Title: ${REPO} released" \ -H "Title: ${REPO} released" \
-H "Tags: white_check_mark,package" \ -H "Tags: white_check_mark,package" \
-H "Priority: default" \ -H "Priority: default" \
-H "Click: ${URL}" \ -H "Click: ${URL}" \
-d "${WORKFLOW} completed successfully." \ -d "${WORKFLOW} completed successfully." \
"${NTFY_URL}/${NTFY_TOPIC}" "${NTFY_URL}/${NTFY_TOPIC}" || echo "::warning::ntfy notification could not be delivered (non-fatal)"
- name: Notify on failure - name: Notify on failure
if: github.event.workflow_run.conclusion == 'failure' if: github.event.workflow_run.conclusion == 'failure'
@@ -61,10 +61,10 @@ jobs:
WORKFLOW="${{ github.event.workflow_run.name }}" WORKFLOW="${{ github.event.workflow_run.name }}"
URL="${{ github.event.workflow_run.html_url }}" URL="${{ github.event.workflow_run.html_url }}"
curl -sS \ curl -sS --retry 3 --retry-connrefused --retry-delay 2 --max-time 20 \
-H "Title: ${REPO} workflow failed" \ -H "Title: ${REPO} workflow failed" \
-H "Tags: x,warning" \ -H "Tags: x,warning" \
-H "Priority: high" \ -H "Priority: high" \
-H "Click: ${URL}" \ -H "Click: ${URL}" \
-d "${WORKFLOW} failed. Check the run for details." \ -d "${WORKFLOW} failed. Check the run for details." \
"${NTFY_URL}/${NTFY_TOPIC}" "${NTFY_URL}/${NTFY_TOPIC}" || echo "::warning::ntfy notification could not be delivered (non-fatal)"
+5 -4
View File
@@ -4,7 +4,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.CI # INGROUP: MokoCLI.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/pr-check.yml # PATH: /.mokogitea/workflows/pr-check.yml
# VERSION: 09.23.00 # VERSION: 09.23.00
@@ -224,7 +224,7 @@ jobs:
- name: Detect platform - name: Detect platform
id: platform id: platform
run: | run: |
# Platform comes from the MokoGitea metadata API (public GET); manifest.xml is no longer used. # Platform comes from the MokoGitea metadata API (public GET).
API="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${GITHUB_REPOSITORY}/metadata" API="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${GITHUB_REPOSITORY}/metadata"
PLATFORM="$(curl -sf "$API" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('platform') or '')" 2>/dev/null || true)" PLATFORM="$(curl -sf "$API" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('platform') or '')" 2>/dev/null || true)"
[ -z "$PLATFORM" ] && PLATFORM="generic" [ -z "$PLATFORM" ] && PLATFORM="generic"
@@ -258,8 +258,9 @@ jobs:
while IFS= read -r -d '' file; do while IFS= read -r -d '' file; do
# Skip vendor, node_modules, and index.html stub files # Skip vendor, node_modules, and index.html stub files
case "$file" in ./vendor/*|./node_modules/*) continue ;; esac case "$file" in ./vendor/*|./node_modules/*) continue ;; esac
# Check first 10 lines for JEXEC or JPATH guard # Scan the whole file for the JEXEC/JPATH guard: it is placed after
if ! head -20 "$file" | grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]"; then # the SPDX/file-header docblock, which commonly runs past 20 lines.
if ! grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]" "$file"; then
echo "::error file=${file}::Missing JEXEC guard: ${file}" echo "::error file=${file}::Missing JEXEC guard: ${file}"
ERRORS=$((ERRORS + 1)) ERRORS=$((ERRORS + 1))
fi fi
+12 -6
View File
@@ -4,10 +4,10 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release # INGROUP: MokoCLI.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/pre-release.yml # PATH: /.mokogitea/workflows/pre-release.yml
# VERSION: 05.02.00 # VERSION: 05.02.01
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches # BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
name: "Universal: Pre-Release" name: "Universal: Pre-Release"
@@ -69,7 +69,7 @@ jobs:
run: | run: |
git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true
- name: Setup mokocli tools - name: Setup MokoCLI tools
env: env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
@@ -84,7 +84,7 @@ jobs:
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 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 fi
rm -rf /tmp/mokocli rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
@@ -162,7 +162,13 @@ jobs:
git add -A git add -A
git diff --cached --quiet || { git diff --cached --quiet || {
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]" git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
git push origin HEAD 2>&1 # Push the bump commit, but do NOT fail the release if the target branch
# is protected and the release identity is not on the push allowlist.
# The build proceeds from the in-tree bumped version regardless; if the
# push is rejected, the next run simply re-bumps from the same base.
if ! git push origin HEAD 2>&1; then
echo "::warning::Version-bump commit could not be pushed (protected branch?). Building from in-tree version ${VERSION} anyway."
fi
} }
# Auto-detect element via manifest_element.php # Auto-detect element via manifest_element.php
@@ -274,4 +280,4 @@ jobs:
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal # INGROUP: MokoCLI.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/rc-revert.yml # PATH: /.mokogitea/workflows/rc-revert.yml
# VERSION: 09.23.00 # VERSION: 09.23.00
+1 -1
View File
@@ -7,7 +7,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow # DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Validation # INGROUP: MokoCLI.Validation
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/repo-health.yml # PATH: /.mokogitea/workflows/repo-health.yml
# VERSION: 09.23.00 # VERSION: 09.23.00
File diff suppressed because it is too large Load Diff
-32
View File
@@ -1,32 +0,0 @@
name: Sync Workflows to Repos
on:
push:
branches:
- main
paths:
- '.mokogitea/workflows/**'
jobs:
sync:
runs-on: ubuntu-latest
if: ${{ startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Checkout mokocli
uses: actions/checkout@v4
with:
repository: MokoConsulting/MokoCLI
token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Setup PHP
uses: https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/raw/branch/main/actions/setup-php@v1
with:
php-version: '8.1'
- name: Install dependencies
run: composer install --no-dev --no-interaction
- name: Sync workflows to generic repos
run: php automation/bulk_sync.php --platform generic --org MokoConsulting --workflows-only --auto-merge --token "${{ secrets.MOKOGITEA_TOKEN }}"
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# FILE INFORMATION # FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow.Template # DEFGROUP: MokoGitea.Workflow.Template
# INGROUP: MokoStandards.CI # INGROUP: MokoCLI.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
# PATH: /.mokogitea/workflows/version-set.yml # PATH: /.mokogitea/workflows/version-set.yml
# VERSION: 01.00.00 # VERSION: 01.00.00
@@ -1,82 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/workflow-sync-trigger.yml
# VERSION: 01.01.00
# BRIEF: Trigger workflow sync to live repos when a PR is merged to main
name: "Universal: Workflow Sync Trigger"
on:
workflow_dispatch:
pull_request:
types: [closed]
branches:
- main
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
sync:
name: Sync workflows to live repos
runs-on: ubuntu-latest
if: >-
startsWith(github.event.repository.name, 'Template-') &&
(github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')))
steps:
- name: Determine platform from repo name
id: platform
run: |
REPO="${{ github.event.repository.name }}"
case "$REPO" in
Template-Joomla) PLATFORM="joomla" ;;
Template-Dolibarr) PLATFORM="dolibarr" ;;
Template-Go) PLATFORM="go" ;;
Template-MCP) PLATFORM="mcp" ;;
Template-Generic) PLATFORM="" ;;
*) PLATFORM="" ;;
esac
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
echo "Platform: ${PLATFORM:-all}"
- name: Clone mokocli
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
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
composer install --no-dev --no-interaction --quiet 2>/dev/null || true
- name: Run workflow sync
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
ARGS="--token ${MOKOGITEA_TOKEN}"
ARGS="${ARGS} --org ${{ vars.GITEA_ORG || github.repository_owner }}"
ARGS="${ARGS} --phase repos"
PLATFORM="${{ steps.platform.outputs.platform }}"
if [ -n "$PLATFORM" ]; then
ARGS="${ARGS} --platform-filter ${PLATFORM}"
fi
php /tmp/mokocli/cli/workflow_sync.php ${ARGS}
+2
View File
@@ -63,6 +63,8 @@
- Cherry-pick upstream v1.26.4: walk git log context error handling — regression fix (#38185) - Cherry-pick upstream v1.26.4: walk git log context error handling — regression fix (#38185)
### Fixed ### Fixed
- Repo metadata `org` is now **derived from the org profile** (the repository owner) instead of being stored/editable, so it can never drift when an organization is renamed. The `org` column is dropped from `repo_manifest` (migration #368) and the field is derived on read via `Repository.DerivedOrgName` (owner display name, falling back to the handle) across the metadata API, the Settings → Metadata page (now read-only), and the Joomla update-server feed. The API `PUT` and MCP `metadata_update` now ignore `org` (read-only, like the already-derived `display_name`) (#771)
- Admin Branding: uploading a custom **Nav Icon** now also sets the **app icon** (`logo.png`, the PWA / web-manifest icon and navbar fallback), so a branded instance shows its own installable app icon instead of the shipped default; resetting the Nav Icon reverts both (#773)
- Fork server binary now compiles: `routers/api/v1/api.go` called `organization.HasOrgOrUserVisible`, which had been renamed to `IsOwnerVisibleToDoer`; the one missed call site broke `go build` of the entire `routers/api/v1` package (CI's Lint & Validate does not run a full build, so it went unnoticed) (#735) - Fork server binary now compiles: `routers/api/v1/api.go` called `organization.HasOrgOrUserVisible`, which had been renamed to `IsOwnerVisibleToDoer`; the one missed call site broke `go build` of the entire `routers/api/v1` package (CI's Lint & Validate does not run a full build, so it went unnoticed) (#735)
- Dev deploy workflow: the build/deploy step referenced runner-side values as `\$TAG` / `\$REGISTRY_TOKEN` inside an unquoted SSH heredoc, deferring expansion to the remote shell where those names are unset — the Docker tag collapsed to an empty `mokogitea:` and every dev deploy failed with `invalid reference format`. Runner values are now injected via an ssh env-prefix and the heredoc is quoted so each `$var` expands in exactly one place (#737) - Dev deploy workflow: the build/deploy step referenced runner-side values as `\$TAG` / `\$REGISTRY_TOKEN` inside an unquoted SSH heredoc, deferring expansion to the remote shell where those names are unset — the Docker tag collapsed to an empty `mokogitea:` and every dev deploy failed with `invalid reference format`. Runner values are now injected via an ssh env-prefix and the heredoc is quoted so each `$var` expands in exactly one place (#737)
- Repaired unit-test compile and `go vet` failures: `CryptoRandomInt/String/Bytes` now return two values (updated `modules/util/util_test.go`), removed a redundant `&&` condition in `issue_comment.go`, and cleaned up isolated integration-test compile errors (#736) - Repaired unit-test compile and `go vet` failures: `CryptoRandomInt/String/Bytes` now return two values (updated `modules/util/util_test.go`), removed a redundant `&&` condition in `issue_comment.go`, and cleaned up isolated integration-test compile errors (#736)
+1
View File
@@ -445,6 +445,7 @@ func prepareMigrationTasks() []*migration {
newMigration(365, "Add org repo defaults table", v1_27.AddOrgRepoDefaultsTable), newMigration(365, "Add org repo defaults table", v1_27.AddOrgRepoDefaultsTable),
newMigration(366, "Add org email domain policy table", v1_27.AddOrgEmailDomainPolicyTable), newMigration(366, "Add org email domain policy table", v1_27.AddOrgEmailDomainPolicyTable),
newMigration(367, "Add user allowlists to org protected branch", v1_27.AddUserAllowlistsToOrgProtectedBranch), newMigration(367, "Add user allowlists to org protected branch", v1_27.AddUserAllowlistsToOrgProtectedBranch),
newMigration(368, "Drop org from repo manifest (derived from org profile)", v1_27.DropOrgFromRepoManifest),
} }
return preparedMigrations return preparedMigrations
} }
+19
View File
@@ -0,0 +1,19 @@
// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
// SPDX-License-Identifier: GPL-3.0-or-later
package v1_27
import (
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/migrations/base"
"xorm.io/xorm"
)
// DropOrgFromRepoManifest removes the org column from repo_manifest. The
// organization is now derived from the org profile (repository owner) on read
// rather than stored, so it never drifts on rename. See issue #771.
func DropOrgFromRepoManifest(x *xorm.Engine) error {
sess := x.NewSession()
defer sess.Close()
return base.DropTableColumns(sess, "repo_manifest", "org")
}
+17
View File
@@ -486,6 +486,23 @@ func (repo *Repository) LoadOwner(ctx context.Context) (err error) {
return err return err
} }
// DerivedOrgName returns the organization name derived from the org profile
// (the repository owner). It prefers the owner's display name (FullName) and
// falls back to the owner handle (Name / OwnerName). The organization is always
// derived from the profile rather than stored, so it never drifts on rename.
func (repo *Repository) DerivedOrgName(ctx context.Context) string {
if err := repo.LoadOwner(ctx); err != nil || repo.Owner == nil {
return repo.OwnerName
}
if repo.Owner.FullName != "" {
return repo.Owner.FullName
}
if repo.Owner.Name != "" {
return repo.Owner.Name
}
return repo.OwnerName
}
// MustOwner always returns a valid *user_model.User object to avoid // MustOwner always returns a valid *user_model.User object to avoid
// conceptually impossible error handling. // conceptually impossible error handling.
// It creates a fake object that contains error details // It creates a fake object that contains error details
+3 -1
View File
@@ -23,8 +23,10 @@ type RepoMetadata struct {
RepoID int64 `xorm:"UNIQUE INDEX NOT NULL 'repo_id'"` RepoID int64 `xorm:"UNIQUE INDEX NOT NULL 'repo_id'"`
// identity section // identity section
// NOTE: organization is intentionally NOT stored here. It is derived from
// the org profile (repository owner) on read via Repository.DerivedOrgName,
// so it can never drift from the owner on rename. See issue #771.
Name string `xorm:"TEXT 'name'"` // project name Name string `xorm:"TEXT 'name'"` // project name
Org string `xorm:"TEXT 'org'"` // organization name
Description string `xorm:"TEXT 'description'"` // project description Description string `xorm:"TEXT 'description'"` // project description
LicenseSPDX string `xorm:"VARCHAR(50) 'license_spdx'"` // SPDX identifier, e.g. "GPL-3.0-or-later" LicenseSPDX string `xorm:"VARCHAR(50) 'license_spdx'"` // SPDX identifier, e.g. "GPL-3.0-or-later"
LicenseName string `xorm:"TEXT 'license_name'"` // human-readable license name LicenseName string `xorm:"TEXT 'license_name'"` // human-readable license name
+6 -6
View File
@@ -14,7 +14,7 @@ import (
// apiMetadata is the JSON representation of a repo manifest. // apiMetadata is the JSON representation of a repo manifest.
type apiMetadata struct { type apiMetadata struct {
Name string `json:"name"` Name string `json:"name"`
Org string `json:"org"` Org string `json:"org"` // read-only, derived from the org profile (repo owner)
Description string `json:"description"` Description string `json:"description"`
LicenseSPDX string `json:"license_spdx"` LicenseSPDX string `json:"license_spdx"`
LicenseName string `json:"license_name"` LicenseName string `json:"license_name"`
@@ -83,14 +83,14 @@ func GetRepoMetadata(ctx *context.APIContext) {
// Return defaults from repo metadata. // Return defaults from repo metadata.
ctx.JSON(http.StatusOK, &apiMetadata{ ctx.JSON(http.StatusOK, &apiMetadata{
Name: ctx.Repo.Repository.Name, Name: ctx.Repo.Repository.Name,
Org: ctx.Repo.Repository.OwnerName, Org: ctx.Repo.Repository.DerivedOrgName(ctx),
Description: ctx.Repo.Repository.Description, Description: ctx.Repo.Repository.Description,
}) })
return return
} }
ctx.JSON(http.StatusOK, &apiMetadata{ ctx.JSON(http.StatusOK, &apiMetadata{
Name: m.Name, Name: m.Name,
Org: m.Org, Org: ctx.Repo.Repository.DerivedOrgName(ctx),
Description: m.Description, Description: m.Description,
LicenseSPDX: m.LicenseSPDX, LicenseSPDX: m.LicenseSPDX,
@@ -157,7 +157,6 @@ func UpdateRepoMetadata(ctx *context.APIContext) {
m = &repo_model.RepoMetadata{ m = &repo_model.RepoMetadata{
RepoID: ctx.Repo.Repository.ID, RepoID: ctx.Repo.Repository.ID,
Name: ctx.Repo.Repository.Name, Name: ctx.Repo.Repository.Name,
Org: ctx.Repo.Repository.OwnerName,
Description: ctx.Repo.Repository.Description, Description: ctx.Repo.Repository.Description,
} }
} }
@@ -171,7 +170,8 @@ func UpdateRepoMetadata(ctx *context.APIContext) {
} }
} }
setStr("name", &m.Name) setStr("name", &m.Name)
setStr("org", &m.Org) // org is intentionally ignored: it is derived from the org profile
// (repository owner) on read, not stored. See issue #771.
setStr("description", &m.Description) setStr("description", &m.Description)
setStr("license_spdx", &m.LicenseSPDX) setStr("license_spdx", &m.LicenseSPDX)
setStr("license_name", &m.LicenseName) setStr("license_name", &m.LicenseName)
@@ -204,7 +204,7 @@ func UpdateRepoMetadata(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, &apiMetadata{ ctx.JSON(http.StatusOK, &apiMetadata{
Name: m.Name, Name: m.Name,
Org: m.Org, Org: ctx.Repo.Repository.DerivedOrgName(ctx),
Description: m.Description, Description: m.Description,
LicenseSPDX: m.LicenseSPDX, LicenseSPDX: m.LicenseSPDX,
+66 -24
View File
@@ -137,27 +137,49 @@ func BrandingUpload(ctx *context.Context) {
return return
} }
destPath := filepath.Join(imgDir, filename) // The nav icon doubles as the app icon (logo.png) — used as the PWA / web
dest, err := os.Create(destPath) // manifest icon and the navbar fallback — so branding the nav icon brands
if err != nil { // the app icon too. Write the uploaded image to both in a single pass. See #773.
ctx.Flash.Error("Failed to save image") targets := []string{filename}
log.Error("Create %s: %v", destPath, err) if imageType == "nav-icon" {
ctx.Redirect(setting.AppSubURL + "/-/admin/branding") targets = append(targets, "logo.png")
return
}
defer dest.Close()
if _, err := io.Copy(dest, file); err != nil {
ctx.Flash.Error("Failed to write image")
log.Error("Copy to %s: %v", destPath, err)
ctx.Redirect(setting.AppSubURL + "/-/admin/branding")
return
} }
// Remove SVG override if present // Write the uploaded image to each target independently (rewinding the
svgPath := filepath.Join(imgDir, filename[:len(filename)-4]+".svg") // stream between targets) so a failure on a later target never leaves an
if fileExists(svgPath) { // earlier one truncated/empty.
os.Remove(svgPath) for i, name := range targets {
if i > 0 {
if _, err := file.Seek(0, io.SeekStart); err != nil {
ctx.Flash.Error("Failed to write image")
log.Error("Seek branding image %s: %v", name, err)
ctx.Redirect(setting.AppSubURL + "/-/admin/branding")
return
}
}
destPath := filepath.Join(imgDir, name)
dest, err := os.Create(destPath)
if err != nil {
ctx.Flash.Error("Failed to save image")
log.Error("Create %s: %v", destPath, err)
ctx.Redirect(setting.AppSubURL + "/-/admin/branding")
return
}
if _, err := io.Copy(dest, file); err != nil {
dest.Close()
ctx.Flash.Error("Failed to write image")
log.Error("Copy to %s: %v", destPath, err)
ctx.Redirect(setting.AppSubURL + "/-/admin/branding")
return
}
dest.Close()
// Remove any SVG override so the uploaded PNG takes effect.
svgPath := filepath.Join(imgDir, name[:len(name)-4]+".svg")
if fileExists(svgPath) {
os.Remove(svgPath)
}
} }
ctx.Flash.Success("Branding image updated: " + imageType) ctx.Flash.Success("Branding image updated: " + imageType)
@@ -183,16 +205,36 @@ func BrandingReset(ctx *context.Context) {
return return
} }
path := filepath.Join(brandingImageDir(), filename) // The nav icon also sets the app icon (logo.png), so resetting it reverts
if fileExists(path) { // both back to the built-in default. See #773.
targets := []string{filename}
if imageType == "nav-icon" {
targets = append(targets, "logo.png")
}
removedAny := false
failed := false
for _, name := range targets {
path := filepath.Join(brandingImageDir(), name)
if !fileExists(path) {
continue
}
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
ctx.Flash.Error("Failed to remove custom image") ctx.Flash.Error("Failed to remove custom image")
log.Error("Remove %s: %v", path, err) log.Error("Remove %s: %v", path, err)
failed = true
} else { } else {
ctx.Flash.Success("Reset to default: " + imageType) removedAny = true
log.Info("Branding reset to default: %s", filename) log.Info("Branding reset to default: %s", name)
} }
} else { }
switch {
case failed:
// error flash already set
case removedAny:
ctx.Flash.Success("Reset to default: " + imageType)
default:
ctx.Flash.Info("Already using default: " + imageType) ctx.Flash.Info("Already using default: " + imageType)
} }
+4 -2
View File
@@ -35,11 +35,13 @@ func Metadata(ctx *context.Context) {
manifest = &repo_model.RepoMetadata{ manifest = &repo_model.RepoMetadata{
RepoID: repoID, RepoID: repoID,
Name: ctx.Repo.Repository.Name, Name: ctx.Repo.Repository.Name,
Org: ctx.Repo.Repository.OwnerName,
Description: ctx.Repo.Repository.Description, Description: ctx.Repo.Repository.Description,
} }
} }
ctx.Data["Manifest"] = manifest ctx.Data["Manifest"] = manifest
// Organization is derived from the org profile (repo owner), not stored.
// It is displayed read-only. See issue #771.
ctx.Data["DerivedOrg"] = ctx.Repo.Repository.DerivedOrgName(ctx)
// Load repo-scoped custom fields. // Load repo-scoped custom fields.
fields, _ := issues_model.GetCustomFieldsByOwner(ctx, ownerID, issues_model.CustomFieldScopeRepo) fields, _ := issues_model.GetCustomFieldsByOwner(ctx, ownerID, issues_model.CustomFieldScopeRepo)
@@ -102,7 +104,7 @@ func saveMetadata(ctx *context.Context) {
manifest := &repo_model.RepoMetadata{ manifest := &repo_model.RepoMetadata{
RepoID: ctx.Repo.Repository.ID, RepoID: ctx.Repo.Repository.ID,
Name: ctx.FormString("name"), Name: ctx.FormString("name"),
Org: ctx.FormString("org"), // org is not stored: it is derived from the org profile on read. See issue #771.
Description: ctx.Repo.Repository.Description, Description: ctx.Repo.Repository.Description,
LicenseSPDX: spdx, LicenseSPDX: spdx,
LicenseName: licenseName, LicenseName: licenseName,
+2 -5
View File
@@ -269,11 +269,8 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require
phpMinimum := meta.PHPMinimum phpMinimum := meta.PHPMinimum
feedDescription := meta.Description feedDescription := meta.Description
// Maintainer and URL always come from the org profile. // Maintainer/organization and URL always come from the org profile.
maintainer := repo.Owner.FullName maintainer := repo.DerivedOrgName(ctx)
if maintainer == "" {
maintainer = repo.Owner.Name
}
maintainerURL := repo.Owner.Website maintainerURL := repo.Owner.Website
if maintainerURL == "" { if maintainerURL == "" {
maintainerURL = fmt.Sprintf("%s/%s", baseURL, repo.Owner.Name) maintainerURL = fmt.Sprintf("%s/%s", baseURL, repo.Owner.Name)
+1 -1
View File
@@ -54,7 +54,7 @@
<tr> <tr>
<td> <td>
<strong>Nav Icon</strong> {{if .HasNavIcon}}<span class="ui mini green label">Custom</span>{{else}}<span class="ui mini grey label">Default</span>{{end}} <strong>Nav Icon</strong> {{if .HasNavIcon}}<span class="ui mini green label">Custom</span>{{else}}<span class="ui mini grey label">Default</span>{{end}}
<div class="tw-text-text-light tw-text-sm tw-mt-1">Top-left corner across all pages. Square, 30x30px.</div> <div class="tw-text-text-light tw-text-sm tw-mt-1">Top-left corner across all pages. Square, 30x30px. Also sets the app icon (PWA / web manifest); use at least 512x512px for a crisp installed icon.</div>
</td> </td>
<td> <td>
<form method="post" action="{{AppSubUrl}}/-/admin/branding/upload" enctype="multipart/form-data"> <form method="post" action="{{AppSubUrl}}/-/admin/branding/upload" enctype="multipart/form-data">
+2 -1
View File
@@ -18,7 +18,8 @@
</div> </div>
<div class="field"> <div class="field">
<label>Organization</label> <label>Organization</label>
<input name="org" value="{{.Manifest.Org}}" placeholder="Organization"> <input value="{{.DerivedOrg}}" placeholder="Organization" readonly>
<p class="help">Derived from the organization profile (repository owner).</p>
</div> </div>
</div> </div>
<div class="three fields"> <div class="three fields">