@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.
Files changed (73) hide show
  1. package/.editorconfig +19 -0
  2. package/.gitattributes +94 -0
  3. package/.gitmessage +9 -0
  4. package/.mokogit/ISSUE_TEMPLATE/adr.md +110 -0
  5. package/.mokogit/ISSUE_TEMPLATE/bug_report.md +48 -0
  6. package/.mokogit/ISSUE_TEMPLATE/config.yml +18 -0
  7. package/.mokogit/ISSUE_TEMPLATE/documentation.md +52 -0
  8. package/.mokogit/ISSUE_TEMPLATE/feature_request.md +51 -0
  9. package/.mokogit/ISSUE_TEMPLATE/mcp_api_integration.md +48 -0
  10. package/.mokogit/ISSUE_TEMPLATE/mcp_connection_issue.md +69 -0
  11. package/.mokogit/ISSUE_TEMPLATE/mcp_tool_request.md +50 -0
  12. package/.mokogit/ISSUE_TEMPLATE/question.md +82 -0
  13. package/.mokogit/ISSUE_TEMPLATE/rfc.md +126 -0
  14. package/.mokogit/ISSUE_TEMPLATE/security.md +51 -0
  15. package/.mokogit/ISSUE_TEMPLATE/version.md +24 -0
  16. package/.mokogit/actions/resolve-source-dir/action.yml +108 -0
  17. package/.mokogit/workflows/auto-assign.yml +76 -0
  18. package/.mokogit/workflows/auto-bump.yml +78 -0
  19. package/.mokogit/workflows/auto-dev-issue.yml +207 -0
  20. package/.mokogit/workflows/auto-release.yml +596 -0
  21. package/.mokogit/workflows/branch-cleanup.yml +60 -0
  22. package/.mokogit/workflows/cascade-dev.yml +198 -0
  23. package/.mokogit/workflows/changelog-validation.yml +101 -0
  24. package/.mokogit/workflows/ci-generic.yml +203 -0
  25. package/.mokogit/workflows/ci-issue-reporter.yml +75 -0
  26. package/.mokogit/workflows/cleanup.yml +87 -0
  27. package/.mokogit/workflows/gitleaks.yml +94 -0
  28. package/.mokogit/workflows/issue-branch.yml +81 -0
  29. package/.mokogit/workflows/notify.yml +73 -0
  30. package/.mokogit/workflows/npm-build-test.yml +83 -0
  31. package/.mokogit/workflows/npm-publish.yml +126 -0
  32. package/.mokogit/workflows/npm-sdk-check.yml +110 -0
  33. package/.mokogit/workflows/npm-tool-inventory.yml +80 -0
  34. package/.mokogit/workflows/pr-branch-check.yml +90 -0
  35. package/.mokogit/workflows/pr-check.yml +565 -0
  36. package/.mokogit/workflows/pre-release.yml +413 -0
  37. package/.mokogit/workflows/push-notify.yml +43 -0
  38. package/.mokogit/workflows/rc-revert.yml +72 -0
  39. package/.mokogit/workflows/repo-health.yml +700 -0
  40. package/.mokogit/workflows/repository-cleanup.yml +525 -0
  41. package/.mokogit/workflows/standards-compliance.yml +2507 -0
  42. package/.mokogit/workflows/sync-version-on-merge.yml +130 -0
  43. package/.mokogit/workflows/version-set.yml +131 -0
  44. package/CHANGELOG.md +18 -0
  45. package/CLAUDE.md +52 -0
  46. package/CODE_OF_CONDUCT.md +70 -0
  47. package/CONTRIBUTING.md +161 -0
  48. package/LICENSE +696 -0
  49. package/Makefile +70 -0
  50. package/README.md +83 -0
  51. package/SECURITY.md +34 -0
  52. package/config.example.json +21 -0
  53. package/dist/client.d.ts +22 -0
  54. package/dist/client.js +124 -0
  55. package/dist/config.d.ts +4 -0
  56. package/dist/config.js +53 -0
  57. package/dist/index.d.ts +3 -0
  58. package/dist/index.js +181 -0
  59. package/dist/signing.d.ts +14 -0
  60. package/dist/signing.js +62 -0
  61. package/dist/types.d.ts +44 -0
  62. package/dist/types.js +16 -0
  63. package/docs/API.md +63 -0
  64. package/docs/ARCHITECTURE.md +73 -0
  65. package/docs/INSTALLATION.md +102 -0
  66. package/docs/index.md +12 -0
  67. package/package.json +35 -0
  68. package/src/client.ts +142 -0
  69. package/src/config.ts +63 -0
  70. package/src/index.ts +336 -0
  71. package/src/signing.ts +67 -0
  72. package/src/types.ts +63 -0
  73. 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