@mokoconsulting/mcp-mokosuite 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +19 -0
- package/.gitattributes +94 -0
- package/.gitmessage +9 -0
- package/.mokogit/ISSUE_TEMPLATE/adr.md +110 -0
- package/.mokogit/ISSUE_TEMPLATE/bug_report.md +48 -0
- package/.mokogit/ISSUE_TEMPLATE/config.yml +18 -0
- package/.mokogit/ISSUE_TEMPLATE/documentation.md +52 -0
- package/.mokogit/ISSUE_TEMPLATE/feature_request.md +51 -0
- package/.mokogit/ISSUE_TEMPLATE/mcp_api_integration.md +48 -0
- package/.mokogit/ISSUE_TEMPLATE/mcp_connection_issue.md +69 -0
- package/.mokogit/ISSUE_TEMPLATE/mcp_tool_request.md +50 -0
- package/.mokogit/ISSUE_TEMPLATE/question.md +82 -0
- package/.mokogit/ISSUE_TEMPLATE/rfc.md +126 -0
- package/.mokogit/ISSUE_TEMPLATE/security.md +51 -0
- package/.mokogit/ISSUE_TEMPLATE/version.md +24 -0
- package/.mokogit/actions/resolve-source-dir/action.yml +108 -0
- package/.mokogit/workflows/auto-assign.yml +76 -0
- package/.mokogit/workflows/auto-bump.yml +78 -0
- package/.mokogit/workflows/auto-dev-issue.yml +207 -0
- package/.mokogit/workflows/auto-release.yml +596 -0
- package/.mokogit/workflows/branch-cleanup.yml +60 -0
- package/.mokogit/workflows/cascade-dev.yml +198 -0
- package/.mokogit/workflows/changelog-validation.yml +101 -0
- package/.mokogit/workflows/ci-generic.yml +203 -0
- package/.mokogit/workflows/ci-issue-reporter.yml +75 -0
- package/.mokogit/workflows/cleanup.yml +87 -0
- package/.mokogit/workflows/gitleaks.yml +94 -0
- package/.mokogit/workflows/issue-branch.yml +81 -0
- package/.mokogit/workflows/notify.yml +73 -0
- package/.mokogit/workflows/npm-build-test.yml +83 -0
- package/.mokogit/workflows/npm-publish.yml +126 -0
- package/.mokogit/workflows/npm-sdk-check.yml +110 -0
- package/.mokogit/workflows/npm-tool-inventory.yml +80 -0
- package/.mokogit/workflows/pr-branch-check.yml +90 -0
- package/.mokogit/workflows/pr-check.yml +565 -0
- package/.mokogit/workflows/pre-release.yml +413 -0
- package/.mokogit/workflows/push-notify.yml +43 -0
- package/.mokogit/workflows/rc-revert.yml +72 -0
- package/.mokogit/workflows/repo-health.yml +700 -0
- package/.mokogit/workflows/repository-cleanup.yml +525 -0
- package/.mokogit/workflows/standards-compliance.yml +2507 -0
- package/.mokogit/workflows/sync-version-on-merge.yml +130 -0
- package/.mokogit/workflows/version-set.yml +131 -0
- package/CHANGELOG.md +18 -0
- package/CLAUDE.md +52 -0
- package/CODE_OF_CONDUCT.md +70 -0
- package/CONTRIBUTING.md +161 -0
- package/LICENSE +696 -0
- package/Makefile +70 -0
- package/README.md +83 -0
- package/SECURITY.md +34 -0
- package/config.example.json +21 -0
- package/dist/client.d.ts +22 -0
- package/dist/client.js +124 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.js +53 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +181 -0
- package/dist/signing.d.ts +14 -0
- package/dist/signing.js +62 -0
- package/dist/types.d.ts +44 -0
- package/dist/types.js +16 -0
- package/docs/API.md +63 -0
- package/docs/ARCHITECTURE.md +73 -0
- package/docs/INSTALLATION.md +102 -0
- package/docs/index.md +12 -0
- package/package.json +35 -0
- package/src/client.ts +142 -0
- package/src/config.ts +63 -0
- package/src/index.ts +336 -0
- package/src/signing.ts +67 -0
- package/src/types.ts +63 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Request for Comments (RFC)
|
|
3
|
+
about: Propose a significant change for community discussion
|
|
4
|
+
title: '[RFC] '
|
|
5
|
+
labels: 'rfc, discussion'
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## RFC Summary
|
|
12
|
+
One-paragraph summary of the proposal.
|
|
13
|
+
|
|
14
|
+
## Motivation
|
|
15
|
+
Why are we doing this? What use cases does it support? What is the expected outcome?
|
|
16
|
+
|
|
17
|
+
## Detailed Design
|
|
18
|
+
### Overview
|
|
19
|
+
Provide a detailed explanation of the proposed change.
|
|
20
|
+
|
|
21
|
+
### API Changes (if applicable)
|
|
22
|
+
```php
|
|
23
|
+
// Before
|
|
24
|
+
function oldApi($param1) { }
|
|
25
|
+
|
|
26
|
+
// After
|
|
27
|
+
function newApi($param1, $param2) { }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### User Experience Changes
|
|
31
|
+
Describe how users will interact with this change.
|
|
32
|
+
|
|
33
|
+
### Implementation Approach
|
|
34
|
+
High-level implementation strategy.
|
|
35
|
+
|
|
36
|
+
## Drawbacks
|
|
37
|
+
Why should we *not* do this?
|
|
38
|
+
|
|
39
|
+
## Alternatives
|
|
40
|
+
What other designs have been considered? What is the impact of not doing this?
|
|
41
|
+
|
|
42
|
+
### Alternative 1
|
|
43
|
+
- Description
|
|
44
|
+
- Trade-offs
|
|
45
|
+
|
|
46
|
+
### Alternative 2
|
|
47
|
+
- Description
|
|
48
|
+
- Trade-offs
|
|
49
|
+
|
|
50
|
+
## Adoption Strategy
|
|
51
|
+
How will existing users adopt this? Is this a breaking change?
|
|
52
|
+
|
|
53
|
+
### Migration Guide
|
|
54
|
+
```bash
|
|
55
|
+
# Steps to migrate
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Deprecation Timeline
|
|
59
|
+
- **Announcement**:
|
|
60
|
+
- **Deprecation**:
|
|
61
|
+
- **Removal**:
|
|
62
|
+
|
|
63
|
+
## Unresolved Questions
|
|
64
|
+
- Question 1
|
|
65
|
+
- Question 2
|
|
66
|
+
|
|
67
|
+
## Future Possibilities
|
|
68
|
+
What future work does this enable?
|
|
69
|
+
|
|
70
|
+
## Impact Assessment
|
|
71
|
+
### Performance
|
|
72
|
+
Expected performance impact.
|
|
73
|
+
|
|
74
|
+
### Security
|
|
75
|
+
Security considerations and implications.
|
|
76
|
+
|
|
77
|
+
### Compatibility
|
|
78
|
+
- **Backward Compatible**: [Yes / No]
|
|
79
|
+
- **Breaking Changes**: [List]
|
|
80
|
+
|
|
81
|
+
### Maintenance
|
|
82
|
+
Long-term maintenance considerations.
|
|
83
|
+
|
|
84
|
+
## Community Input
|
|
85
|
+
### Stakeholders
|
|
86
|
+
- [ ] Core team
|
|
87
|
+
- [ ] Module developers
|
|
88
|
+
- [ ] End users
|
|
89
|
+
- [ ] Enterprise customers
|
|
90
|
+
|
|
91
|
+
### Feedback Period
|
|
92
|
+
**Duration**: [e.g., 2 weeks]
|
|
93
|
+
**Deadline**: [date]
|
|
94
|
+
|
|
95
|
+
## Implementation Timeline
|
|
96
|
+
### Phase 1: Design
|
|
97
|
+
- [ ] RFC discussion
|
|
98
|
+
- [ ] Design finalization
|
|
99
|
+
- [ ] Approval
|
|
100
|
+
|
|
101
|
+
### Phase 2: Implementation
|
|
102
|
+
- [ ] Core implementation
|
|
103
|
+
- [ ] Tests
|
|
104
|
+
- [ ] Documentation
|
|
105
|
+
|
|
106
|
+
### Phase 3: Release
|
|
107
|
+
- [ ] Beta release
|
|
108
|
+
- [ ] Feedback collection
|
|
109
|
+
- [ ] Stable release
|
|
110
|
+
|
|
111
|
+
## Success Metrics
|
|
112
|
+
How will we measure success?
|
|
113
|
+
- Metric 1
|
|
114
|
+
- Metric 2
|
|
115
|
+
|
|
116
|
+
## References
|
|
117
|
+
- Related RFCs:
|
|
118
|
+
- External documentation:
|
|
119
|
+
- Prior art:
|
|
120
|
+
|
|
121
|
+
## Open Questions for Community
|
|
122
|
+
1. Question 1?
|
|
123
|
+
2. Question 2?
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
**Note**: This RFC is open for community discussion. Please provide feedback in the comments below.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Security Vulnerability Report
|
|
3
|
+
about: Report a security vulnerability (use only for non-critical issues)
|
|
4
|
+
title: '[SECURITY] '
|
|
5
|
+
labels: 'security'
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## ⚠️ IMPORTANT: Private Disclosure Required
|
|
12
|
+
|
|
13
|
+
**For critical security vulnerabilities, DO NOT use this template.**
|
|
14
|
+
Follow the process in [SECURITY.md](../SECURITY.md) for responsible disclosure.
|
|
15
|
+
|
|
16
|
+
Use this template only for:
|
|
17
|
+
- Security improvements
|
|
18
|
+
- Non-critical security suggestions
|
|
19
|
+
- Security documentation updates
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Security Issue
|
|
24
|
+
|
|
25
|
+
**Severity**:
|
|
26
|
+
<!-- Low, Medium, or informational only -->
|
|
27
|
+
|
|
28
|
+
## Description
|
|
29
|
+
<!-- Describe the security concern or improvement suggestion -->
|
|
30
|
+
|
|
31
|
+
## Affected Components
|
|
32
|
+
<!-- List the affected files, features, or components -->
|
|
33
|
+
|
|
34
|
+
## Suggested Mitigation
|
|
35
|
+
<!-- Describe how this could be addressed -->
|
|
36
|
+
|
|
37
|
+
## Standards Reference
|
|
38
|
+
Does this relate to security standards in [MokoCLI](https://git.mokoconsulting.tech/MokoConsulting/mokocli)?
|
|
39
|
+
- [ ] SPDX license identifiers
|
|
40
|
+
- [ ] Secret management
|
|
41
|
+
- [ ] Dependency security
|
|
42
|
+
- [ ] Access control
|
|
43
|
+
- [ ] Other: [specify]
|
|
44
|
+
|
|
45
|
+
## Additional Context
|
|
46
|
+
<!-- Add any other context about the security concern -->
|
|
47
|
+
|
|
48
|
+
## Checklist
|
|
49
|
+
- [ ] This is NOT a critical vulnerability requiring private disclosure
|
|
50
|
+
- [ ] I have reviewed the SECURITY.md policy
|
|
51
|
+
- [ ] I have provided sufficient detail for evaluation
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Version Bump
|
|
3
|
+
about: Request or track a version change
|
|
4
|
+
title: '[VERSION] '
|
|
5
|
+
labels: 'version, type: version'
|
|
6
|
+
assignees: 'jmiller'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Version Change
|
|
10
|
+
|
|
11
|
+
**Current version**: <!-- e.g., 01.02.03 -->
|
|
12
|
+
**Requested version**: <!-- e.g., 01.03.00 -->
|
|
13
|
+
**Change type**: <!-- patch / minor / major -->
|
|
14
|
+
|
|
15
|
+
## Reason
|
|
16
|
+
|
|
17
|
+
<!-- Why is this version bump needed? -->
|
|
18
|
+
|
|
19
|
+
## Checklist
|
|
20
|
+
|
|
21
|
+
- [ ] README.md `VERSION:` field updated
|
|
22
|
+
- [ ] CHANGELOG.md entry added
|
|
23
|
+
- [ ] Manifest/descriptor version updated (Joomla: `<version>`, NPM/MCP: `package.json`, client: theme manifest)
|
|
24
|
+
- [ ] All file headers will be auto-propagated by `sync-version-on-merge` workflow
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
name: "Resolve source dir"
|
|
5
|
+
description: >-
|
|
6
|
+
Resolve the repository source directory from the MokoGIT metadata API
|
|
7
|
+
(entry_point) and cross-check the Makefile SRC_DIR, erroring on conflict.
|
|
8
|
+
Falls back to source/ when neither is available.
|
|
9
|
+
|
|
10
|
+
inputs:
|
|
11
|
+
mokogit_token:
|
|
12
|
+
description: "MokoGIT API token used for the metadata lookup (secrets are not accessible inside composite actions, so pass it in)."
|
|
13
|
+
required: false
|
|
14
|
+
default: ""
|
|
15
|
+
strict:
|
|
16
|
+
description: >-
|
|
17
|
+
When 'true', an unreachable/invalid metadata API is a hard error
|
|
18
|
+
(refuse to guess). When 'false', warn and treat entry_point as absent.
|
|
19
|
+
A genuine metadata-vs-Makefile conflict always errors regardless.
|
|
20
|
+
required: false
|
|
21
|
+
default: "true"
|
|
22
|
+
|
|
23
|
+
outputs:
|
|
24
|
+
source_dir:
|
|
25
|
+
description: "Resolved source directory with trailing slash (e.g. source/)"
|
|
26
|
+
value: ${{ steps.resolve.outputs.source_dir }}
|
|
27
|
+
source_glob:
|
|
28
|
+
description: "Recursive glob for the source directory (e.g. source/**)"
|
|
29
|
+
value: ${{ steps.resolve.outputs.source_glob }}
|
|
30
|
+
|
|
31
|
+
runs:
|
|
32
|
+
using: "composite"
|
|
33
|
+
steps:
|
|
34
|
+
- id: resolve
|
|
35
|
+
shell: bash
|
|
36
|
+
run: |
|
|
37
|
+
set -euo pipefail
|
|
38
|
+
|
|
39
|
+
STRICT='${{ inputs.strict }}'
|
|
40
|
+
|
|
41
|
+
normalize() {
|
|
42
|
+
# Trim whitespace, strip surrounding quotes, ensure single trailing slash.
|
|
43
|
+
# A resolved value of "." / "./" (repo root) is treated as invalid → empty.
|
|
44
|
+
local v="$1"
|
|
45
|
+
v="$(printf '%s' "$v" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
|
46
|
+
v="${v%\"}"; v="${v#\"}"
|
|
47
|
+
v="${v%\'}"; v="${v#\'}"
|
|
48
|
+
v="$(printf '%s' "$v" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
|
49
|
+
[ -z "$v" ] && { printf ''; return; }
|
|
50
|
+
v="${v%/}/"
|
|
51
|
+
if [ "$v" = "./" ] || [ "$v" = "." ]; then
|
|
52
|
+
printf ''
|
|
53
|
+
return
|
|
54
|
+
fi
|
|
55
|
+
printf '%s' "$v"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# --- Metadata entry_point --------------------------------------------
|
|
59
|
+
ENTRY_POINT=""
|
|
60
|
+
META_DIR=""
|
|
61
|
+
if [ -n "${MOKOGIT_URL:-}" ] && [ -n "${GIT_ORG:-}" ] && [ -n "${GIT_REPO:-}" ]; then
|
|
62
|
+
URL="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}/metadata"
|
|
63
|
+
CURL_RC=0
|
|
64
|
+
META=$(curl -sf -H "Authorization: token ${{ inputs.mokogit_token }}" "$URL") || CURL_RC=$?
|
|
65
|
+
if [ "$CURL_RC" -ne 0 ]; then
|
|
66
|
+
if [ "$STRICT" = "true" ]; then
|
|
67
|
+
echo "::error::metadata API unreachable (curl $CURL_RC); refusing to guess source dir"
|
|
68
|
+
exit 1
|
|
69
|
+
else
|
|
70
|
+
echo "::warning::metadata unreachable; treating entry_point as absent"
|
|
71
|
+
META_DIR=""
|
|
72
|
+
fi
|
|
73
|
+
else
|
|
74
|
+
ENTRY_POINT=$(printf '%s' "$META" | python3 -c "import json,sys;print(json.load(sys.stdin).get('entry_point','') or '')") || { echo "::error::metadata not valid JSON"; exit 1; }
|
|
75
|
+
META_DIR="$(normalize "$ENTRY_POINT")"
|
|
76
|
+
fi
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# --- Makefile SRC_DIR -------------------------------------------------
|
|
80
|
+
MAKE_DIR=""
|
|
81
|
+
if [ -f Makefile ]; then
|
|
82
|
+
RAW=$(awk -F':= *' '/^SRC_DIR[[:space:]]*:=/{print $2}' Makefile | head -n1)
|
|
83
|
+
if [ -z "$RAW" ]; then
|
|
84
|
+
RAW=$(awk -F'\\?= *' '/^SRC_DIR[[:space:]]*\?=/{print $2}' Makefile | head -n1)
|
|
85
|
+
fi
|
|
86
|
+
MAKE_DIR="$(normalize "$RAW")"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# --- Reconcile --------------------------------------------------------
|
|
90
|
+
# A genuine conflict ALWAYS errors, regardless of strict.
|
|
91
|
+
SOURCE_DIR=""
|
|
92
|
+
if [ -n "$META_DIR" ] && [ -n "$MAKE_DIR" ]; then
|
|
93
|
+
if [ "$META_DIR" != "$MAKE_DIR" ]; then
|
|
94
|
+
echo "::error::source dir conflict: metadata entry_point='${META_DIR}' vs Makefile SRC_DIR='${MAKE_DIR}'"
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
SOURCE_DIR="$META_DIR"
|
|
98
|
+
elif [ -n "$META_DIR" ]; then
|
|
99
|
+
SOURCE_DIR="$META_DIR"
|
|
100
|
+
elif [ -n "$MAKE_DIR" ]; then
|
|
101
|
+
SOURCE_DIR="$MAKE_DIR"
|
|
102
|
+
else
|
|
103
|
+
SOURCE_DIR="source/"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
echo "Resolved source_dir: ${SOURCE_DIR}"
|
|
107
|
+
echo "source_dir=${SOURCE_DIR}" >> "$GITHUB_OUTPUT"
|
|
108
|
+
echo "source_glob=${SOURCE_DIR}**" >> "$GITHUB_OUTPUT"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
+
#
|
|
4
|
+
# FILE INFORMATION
|
|
5
|
+
# DEFGROUP: GitHub.Workflow
|
|
6
|
+
# INGROUP: MokoStandards.Workflows.Shared
|
|
7
|
+
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
|
8
|
+
# PATH: /.mokogit/workflows/auto-assign.yml
|
|
9
|
+
# VERSION: 04.06.00
|
|
10
|
+
# BRIEF: Auto-assign jmiller to unassigned issues and PRs every 15 minutes
|
|
11
|
+
|
|
12
|
+
name: "Universal: Auto-Assign"
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
issues:
|
|
16
|
+
types: [opened]
|
|
17
|
+
pull_request_target:
|
|
18
|
+
types: [opened]
|
|
19
|
+
schedule:
|
|
20
|
+
- cron: '0 */12 * * *'
|
|
21
|
+
workflow_dispatch:
|
|
22
|
+
|
|
23
|
+
permissions:
|
|
24
|
+
issues: write
|
|
25
|
+
pull-requests: write
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
auto-assign:
|
|
29
|
+
name: Assign unassigned issues and PRs
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
- name: Assign unassigned issues
|
|
34
|
+
env:
|
|
35
|
+
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
|
36
|
+
run: |
|
|
37
|
+
REPO="${{ github.repository }}"
|
|
38
|
+
ASSIGNEE="jmiller"
|
|
39
|
+
|
|
40
|
+
echo "## 🏷️ Auto-Assign Report" >> $GITHUB_STEP_SUMMARY
|
|
41
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
42
|
+
|
|
43
|
+
ASSIGNED_ISSUES=0
|
|
44
|
+
ASSIGNED_PRS=0
|
|
45
|
+
|
|
46
|
+
# Assign unassigned open issues
|
|
47
|
+
ISSUES=$(gh api "repos/$REPO/issues?state=open&per_page=100&assignee=none" --jq '.[].number' 2>/dev/null || true)
|
|
48
|
+
for NUM in $ISSUES; do
|
|
49
|
+
# Skip PRs (the issues endpoint returns PRs too)
|
|
50
|
+
IS_PR=$(gh api "repos/$REPO/issues/$NUM" --jq '.pull_request // empty' 2>/dev/null || true)
|
|
51
|
+
if [ -z "$IS_PR" ]; then
|
|
52
|
+
gh api "repos/$REPO/issues/$NUM/assignees" -X POST -f "assignees[]=$ASSIGNEE" --silent 2>/dev/null && {
|
|
53
|
+
ASSIGNED_ISSUES=$((ASSIGNED_ISSUES + 1))
|
|
54
|
+
echo " Assigned issue #$NUM"
|
|
55
|
+
} || true
|
|
56
|
+
fi
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
# Assign unassigned open PRs
|
|
60
|
+
PRS=$(gh api "repos/$REPO/pulls?state=open&per_page=100" --jq '.[] | select(.assignees | length == 0) | .number' 2>/dev/null || true)
|
|
61
|
+
for NUM in $PRS; do
|
|
62
|
+
gh api "repos/$REPO/issues/$NUM/assignees" -X POST -f "assignees[]=$ASSIGNEE" --silent 2>/dev/null && {
|
|
63
|
+
ASSIGNED_PRS=$((ASSIGNED_PRS + 1))
|
|
64
|
+
echo " Assigned PR #$NUM"
|
|
65
|
+
} || true
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
echo "| Type | Assigned |" >> $GITHUB_STEP_SUMMARY
|
|
69
|
+
echo "|------|----------|" >> $GITHUB_STEP_SUMMARY
|
|
70
|
+
echo "| Issues | $ASSIGNED_ISSUES |" >> $GITHUB_STEP_SUMMARY
|
|
71
|
+
echo "| Pull Requests | $ASSIGNED_PRS |" >> $GITHUB_STEP_SUMMARY
|
|
72
|
+
|
|
73
|
+
if [ "$ASSIGNED_ISSUES" -eq 0 ] && [ "$ASSIGNED_PRS" -eq 0 ]; then
|
|
74
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
75
|
+
echo "✅ All issues and PRs already have assignees" >> $GITHUB_STEP_SUMMARY
|
|
76
|
+
fi
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
#
|
|
5
|
+
# FILE INFORMATION
|
|
6
|
+
# DEFGROUP: MokoGIT.Workflow
|
|
7
|
+
# INGROUP: MokoCLI.Release
|
|
8
|
+
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
|
9
|
+
# PATH: /.mokogit/workflows/auto-bump.yml
|
|
10
|
+
# VERSION: 10.00.00
|
|
11
|
+
# BRIEF: Auto patch-bump version on push to feature/patch branches (dev/rc use rolling build-metadata versioning — #404)
|
|
12
|
+
|
|
13
|
+
name: "Universal: Auto Version Bump"
|
|
14
|
+
|
|
15
|
+
# #404 — dev and rc are DELIBERATELY removed from this trigger. Committing an
|
|
16
|
+
# auto-bump back to dev/rc on every push was the root cause of manifest <version>
|
|
17
|
+
# merge conflicts (branch vs dev diverge on every merge) and per-push CI churn.
|
|
18
|
+
# Those branches now advance their version as BUILD METADATA at pre-release time
|
|
19
|
+
# (pre-release.yml -> version_build_metadata.php), stamped only into the built
|
|
20
|
+
# artifact and never committed. feature/** and patch/** still bump normally so a
|
|
21
|
+
# branch carries its own advancing version into review.
|
|
22
|
+
on:
|
|
23
|
+
push:
|
|
24
|
+
branches:
|
|
25
|
+
- 'feature/**'
|
|
26
|
+
- 'patch/**'
|
|
27
|
+
# Don't bump the version for a pure workflow/CI-config sync — only real
|
|
28
|
+
# source changes should move the version.
|
|
29
|
+
paths-ignore:
|
|
30
|
+
- '.mokogit/**'
|
|
31
|
+
- '.gitea/**'
|
|
32
|
+
- '.github/**'
|
|
33
|
+
|
|
34
|
+
env:
|
|
35
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
36
|
+
MOKOGIT_URL: ${{ vars.MOKOGIT_URL || 'https://git.mokoconsulting.tech' }}
|
|
37
|
+
|
|
38
|
+
permissions:
|
|
39
|
+
contents: write
|
|
40
|
+
|
|
41
|
+
jobs:
|
|
42
|
+
bump:
|
|
43
|
+
name: Version Bump
|
|
44
|
+
runs-on: release
|
|
45
|
+
if: >-
|
|
46
|
+
!contains(github.event.head_commit.message, '[skip ci]') &&
|
|
47
|
+
!contains(github.event.head_commit.message, '[skip bump]') &&
|
|
48
|
+
!startsWith(github.event.head_commit.message, 'Merge pull request') &&
|
|
49
|
+
!startsWith(github.event.repository.name, 'Template-')
|
|
50
|
+
|
|
51
|
+
steps:
|
|
52
|
+
- name: Checkout
|
|
53
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
54
|
+
with:
|
|
55
|
+
token: ${{ github.token }}
|
|
56
|
+
fetch-depth: 1
|
|
57
|
+
|
|
58
|
+
- name: Setup MokoCLI tools
|
|
59
|
+
run: |
|
|
60
|
+
if ! command -v composer &> /dev/null; then
|
|
61
|
+
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
|
|
62
|
+
fi
|
|
63
|
+
if [ -d "/opt/mokocli/cli" ]; then
|
|
64
|
+
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
|
|
65
|
+
else
|
|
66
|
+
git clone --depth 1 --branch main --quiet \
|
|
67
|
+
"https://x-access-token:${{ secrets.MOKOGIT_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \
|
|
68
|
+
/tmp/mokocli
|
|
69
|
+
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
|
|
70
|
+
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
- name: Bump version
|
|
74
|
+
run: |
|
|
75
|
+
php ${MOKO_CLI}/version_auto_bump.php \
|
|
76
|
+
--path . --branch "${GITHUB_REF_NAME}" \
|
|
77
|
+
--token "${{ github.token }}" \
|
|
78
|
+
--repo-url "https://x-access-token:${{ github.token }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
#
|
|
3
|
+
# This file is part of a Moko Consulting project.
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
6
|
+
#
|
|
7
|
+
# FILE INFORMATION
|
|
8
|
+
# DEFGROUP: GitHub.Workflow
|
|
9
|
+
# INGROUP: MokoStandards.Automation
|
|
10
|
+
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
|
11
|
+
# PATH: /templates/workflows/shared/auto-dev-issue.yml.template
|
|
12
|
+
# VERSION: 04.06.00
|
|
13
|
+
# BRIEF: Auto-create tracking issue with sub-issues for dev/rc branch workflow
|
|
14
|
+
# NOTE: Synced via bulk-repo-sync to .mokogit/workflows/auto-dev-issue.yml in all governed repos.
|
|
15
|
+
|
|
16
|
+
name: "Universal: Dev/RC Branch Issue"
|
|
17
|
+
|
|
18
|
+
on:
|
|
19
|
+
# Auto-create on RC branch creation
|
|
20
|
+
create:
|
|
21
|
+
# Manual trigger for dev branches
|
|
22
|
+
workflow_dispatch:
|
|
23
|
+
inputs:
|
|
24
|
+
branch:
|
|
25
|
+
description: 'Branch name (e.g., dev/my-feature or dev/04.06)'
|
|
26
|
+
required: true
|
|
27
|
+
type: string
|
|
28
|
+
|
|
29
|
+
env:
|
|
30
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
31
|
+
|
|
32
|
+
permissions:
|
|
33
|
+
contents: read
|
|
34
|
+
issues: write
|
|
35
|
+
|
|
36
|
+
jobs:
|
|
37
|
+
create-issue:
|
|
38
|
+
name: Create version tracking issue
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
if: >-
|
|
41
|
+
(github.event_name == 'workflow_dispatch') ||
|
|
42
|
+
(github.event.ref_type == 'branch' &&
|
|
43
|
+
(startsWith(github.event.ref, 'rc/') ||
|
|
44
|
+
startsWith(github.event.ref, 'alpha/') ||
|
|
45
|
+
startsWith(github.event.ref, 'beta/')))
|
|
46
|
+
|
|
47
|
+
steps:
|
|
48
|
+
- name: Create tracking issue and sub-issues
|
|
49
|
+
env:
|
|
50
|
+
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
|
|
51
|
+
run: |
|
|
52
|
+
# For manual dispatch, use input; for auto, use event ref
|
|
53
|
+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
54
|
+
BRANCH="${{ inputs.branch }}"
|
|
55
|
+
else
|
|
56
|
+
BRANCH="${{ github.event.ref }}"
|
|
57
|
+
fi
|
|
58
|
+
REPO="${{ github.repository }}"
|
|
59
|
+
ACTOR="${{ github.actor }}"
|
|
60
|
+
NOW=$(date -u '+%Y-%m-%d %H:%M UTC')
|
|
61
|
+
|
|
62
|
+
# Determine branch type and version
|
|
63
|
+
if [[ "$BRANCH" == rc/* ]]; then
|
|
64
|
+
VERSION="${BRANCH#rc/}"
|
|
65
|
+
BRANCH_TYPE="Release Candidate"
|
|
66
|
+
LABEL_TYPE="type: release"
|
|
67
|
+
TITLE_PREFIX="rc"
|
|
68
|
+
elif [[ "$BRANCH" == beta/* ]]; then
|
|
69
|
+
VERSION="${BRANCH#beta/}"
|
|
70
|
+
BRANCH_TYPE="Beta"
|
|
71
|
+
LABEL_TYPE="type: release"
|
|
72
|
+
TITLE_PREFIX="beta"
|
|
73
|
+
elif [[ "$BRANCH" == alpha/* ]]; then
|
|
74
|
+
VERSION="${BRANCH#alpha/}"
|
|
75
|
+
BRANCH_TYPE="Alpha"
|
|
76
|
+
LABEL_TYPE="type: release"
|
|
77
|
+
TITLE_PREFIX="alpha"
|
|
78
|
+
else
|
|
79
|
+
VERSION="${BRANCH#dev/}"
|
|
80
|
+
BRANCH_TYPE="Development"
|
|
81
|
+
LABEL_TYPE="type: feature"
|
|
82
|
+
TITLE_PREFIX="feat"
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
TITLE="${TITLE_PREFIX}(${VERSION}): ${BRANCH_TYPE} tracking for ${BRANCH}"
|
|
86
|
+
|
|
87
|
+
# Check for existing issue with same title prefix
|
|
88
|
+
EXISTING=$(gh api "repos/${REPO}/issues?state=open&per_page=10" \
|
|
89
|
+
--jq ".[] | select(.title | startswith(\"${TITLE_PREFIX}(${VERSION})\")) | .number" 2>/dev/null | head -1)
|
|
90
|
+
|
|
91
|
+
if [ -n "$EXISTING" ]; then
|
|
92
|
+
echo "ℹ️ Issue #${EXISTING} already exists for ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
|
93
|
+
exit 0
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# ── Define sub-issues for the workflow ─────────────────────────
|
|
97
|
+
if [[ "$BRANCH" == rc/* ]]; then
|
|
98
|
+
SUB_ISSUES=(
|
|
99
|
+
"RC Testing|Verify all features work on rc branch|type: test,release-candidate"
|
|
100
|
+
"Regression Testing|Run full regression suite before merge|type: test,release-candidate"
|
|
101
|
+
"Version Bump|Bump version in README.md and all headers|type: version,release-candidate"
|
|
102
|
+
"Changelog Update|Update CHANGELOG.md with release notes|documentation,release-candidate"
|
|
103
|
+
"Merge to Version Branch|Create PR to version/XX|type: release,needs-review"
|
|
104
|
+
)
|
|
105
|
+
elif [[ "$BRANCH" == alpha/* ]] || [[ "$BRANCH" == beta/* ]]; then
|
|
106
|
+
SUB_ISSUES=(
|
|
107
|
+
"Testing|Verify features on ${BRANCH_TYPE} branch|type: test,status: in-progress"
|
|
108
|
+
"Bug Fixes|Fix issues found during ${BRANCH_TYPE} testing|type: bug,status: pending"
|
|
109
|
+
"Promote to Next Stage|Create PR to promote to next release stage|type: release,needs-review"
|
|
110
|
+
)
|
|
111
|
+
else
|
|
112
|
+
SUB_ISSUES=(
|
|
113
|
+
"Development|Implement feature/fix on dev branch|type: feature,status: in-progress"
|
|
114
|
+
"Unit Testing|Write and pass unit tests|type: test,status: pending"
|
|
115
|
+
"Code Review|Request and complete code review|needs-review,status: pending"
|
|
116
|
+
"Version Bump|Bump version in README.md and all headers|type: version,status: pending"
|
|
117
|
+
"Changelog Update|Update CHANGELOG.md with release notes|documentation,status: pending"
|
|
118
|
+
"Create RC Branch|Promote dev to rc branch for final testing|type: release,status: pending"
|
|
119
|
+
"Merge to Main|Create PR from rc/dev to main|type: release,needs-review,status: pending"
|
|
120
|
+
)
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# ── Create sub-issues first ───────────────────────────────────────
|
|
124
|
+
SUB_LIST=""
|
|
125
|
+
SUB_NUMBERS=""
|
|
126
|
+
for SUB in "${SUB_ISSUES[@]}"; do
|
|
127
|
+
IFS='|' read -r SUB_TITLE SUB_DESC SUB_LABELS <<< "$SUB"
|
|
128
|
+
SUB_FULL_TITLE="${TITLE_PREFIX}(${VERSION}): ${SUB_TITLE}"
|
|
129
|
+
|
|
130
|
+
SUB_BODY=$(printf '### %s\n\n%s\n\n| Field | Value |\n|-------|-------|\n| **Parent Branch** | `%s` |\n| **Version** | `%s` |\n\n---\n*Sub-issue of the %s tracking issue for `%s`.*' \
|
|
131
|
+
"$SUB_TITLE" "$SUB_DESC" "$BRANCH" "$VERSION" "$BRANCH_TYPE" "$BRANCH")
|
|
132
|
+
|
|
133
|
+
SUB_URL=$(gh issue create \
|
|
134
|
+
--repo "$REPO" \
|
|
135
|
+
--title "$SUB_FULL_TITLE" \
|
|
136
|
+
--body "$SUB_BODY" \
|
|
137
|
+
--label "${SUB_LABELS}" \
|
|
138
|
+
--assignee "jmiller" 2>&1)
|
|
139
|
+
|
|
140
|
+
SUB_NUM=$(echo "$SUB_URL" | grep -oE '[0-9]+$')
|
|
141
|
+
if [ -n "$SUB_NUM" ]; then
|
|
142
|
+
SUB_LIST="${SUB_LIST}\n- [ ] ${SUB_TITLE} (#${SUB_NUM})"
|
|
143
|
+
SUB_NUMBERS="${SUB_NUMBERS} #${SUB_NUM}"
|
|
144
|
+
fi
|
|
145
|
+
sleep 0.3
|
|
146
|
+
done
|
|
147
|
+
|
|
148
|
+
# ── Create parent tracking issue ──────────────────────────────────
|
|
149
|
+
PARENT_BODY=$(printf '## %s Branch Created\n\n| Field | Value |\n|-------|-------|\n| **Branch** | `%s` |\n| **Version** | `%s` |\n| **Type** | %s |\n| **Created by** | @%s |\n| **Created at** | %s |\n| **Repository** | `%s` |\n\n## Workflow Sub-Issues\n\n%b\n\n---\n*Auto-created by [auto-dev-issue.yml](.github/workflows/auto-dev-issue.yml) on branch creation.*' \
|
|
150
|
+
"$BRANCH_TYPE" "$BRANCH" "$VERSION" "$BRANCH_TYPE" "$ACTOR" "$NOW" "$REPO" "$SUB_LIST")
|
|
151
|
+
|
|
152
|
+
PARENT_URL=$(gh issue create \
|
|
153
|
+
--repo "$REPO" \
|
|
154
|
+
--title "$TITLE" \
|
|
155
|
+
--body "$PARENT_BODY" \
|
|
156
|
+
--label "${LABEL_TYPE},version" \
|
|
157
|
+
--assignee "jmiller" 2>&1)
|
|
158
|
+
|
|
159
|
+
PARENT_NUM=$(echo "$PARENT_URL" | grep -oE '[0-9]+$')
|
|
160
|
+
|
|
161
|
+
# ── Link sub-issues back to parent ────────────────────────────────
|
|
162
|
+
if [ -n "$PARENT_NUM" ]; then
|
|
163
|
+
for SUB in "${SUB_ISSUES[@]}"; do
|
|
164
|
+
IFS='|' read -r SUB_TITLE _ _ <<< "$SUB"
|
|
165
|
+
SUB_FULL_TITLE="${TITLE_PREFIX}(${VERSION}): ${SUB_TITLE}"
|
|
166
|
+
SUB_NUM=$(gh api "repos/${REPO}/issues?state=open&per_page=20" \
|
|
167
|
+
--jq ".[] | select(.title == \"${SUB_FULL_TITLE}\") | .number" 2>/dev/null | head -1)
|
|
168
|
+
if [ -n "$SUB_NUM" ]; then
|
|
169
|
+
gh api "repos/${REPO}/issues/${SUB_NUM}" -X PATCH \
|
|
170
|
+
-f body="$(gh api "repos/${REPO}/issues/${SUB_NUM}" --jq '.body' 2>/dev/null)
|
|
171
|
+
|
|
172
|
+
> **Parent Issue:** #${PARENT_NUM}" --silent 2>/dev/null || true
|
|
173
|
+
fi
|
|
174
|
+
sleep 0.2
|
|
175
|
+
done
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
# ── Create or update prerelease for alpha/beta/rc ────────────────
|
|
179
|
+
if [[ "$BRANCH" == rc/* ]] || [[ "$BRANCH" == alpha/* ]] || [[ "$BRANCH" == beta/* ]]; then
|
|
180
|
+
case "$BRANCH_TYPE" in
|
|
181
|
+
Alpha) RELEASE_TAG="alpha" ;;
|
|
182
|
+
Beta) RELEASE_TAG="beta" ;;
|
|
183
|
+
"Release Candidate") RELEASE_TAG="release-candidate" ;;
|
|
184
|
+
esac
|
|
185
|
+
|
|
186
|
+
EXISTING=$(gh release view "$RELEASE_TAG" --json tagName -q .tagName 2>/dev/null || true)
|
|
187
|
+
if [ -z "$EXISTING" ]; then
|
|
188
|
+
gh release create "$RELEASE_TAG" \
|
|
189
|
+
--title "${RELEASE_TAG} (${VERSION})" \
|
|
190
|
+
--notes "## ${BRANCH_TYPE} ${VERSION}\n\nBranch: \`${BRANCH}\`\nTracking issue: ${PARENT_URL}" \
|
|
191
|
+
--prerelease \
|
|
192
|
+
--target main 2>/dev/null || true
|
|
193
|
+
echo "${BRANCH_TYPE} release created: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
|
|
194
|
+
else
|
|
195
|
+
gh release edit "$RELEASE_TAG" \
|
|
196
|
+
--title "${RELEASE_TAG} (${VERSION})" --prerelease 2>/dev/null || true
|
|
197
|
+
echo "${BRANCH_TYPE} release updated: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
|
|
198
|
+
fi
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
# ── Summary ───────────────────────────────────────────────────────
|
|
202
|
+
echo "## Dev Workflow Issues Created" >> $GITHUB_STEP_SUMMARY
|
|
203
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
204
|
+
echo "| Item | Issue |" >> $GITHUB_STEP_SUMMARY
|
|
205
|
+
echo "|------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
206
|
+
echo "| **Parent** | ${PARENT_URL} |" >> $GITHUB_STEP_SUMMARY
|
|
207
|
+
echo "| **Sub-issues** |${SUB_NUMBERS} |" >> $GITHUB_STEP_SUMMARY
|