@mokoconsulting/mcp-windows 3.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/.gitattributes +94 -0
- package/.gitmessage +9 -0
- package/.mokogitea/ISSUE_TEMPLATE/adr.md +110 -0
- package/.mokogitea/ISSUE_TEMPLATE/bug_report.md +48 -0
- package/.mokogitea/ISSUE_TEMPLATE/config.yml +18 -0
- package/.mokogitea/ISSUE_TEMPLATE/documentation.md +52 -0
- package/.mokogitea/ISSUE_TEMPLATE/feature_request.md +51 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_api_integration.md +48 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_connection_issue.md +67 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_tool_request.md +49 -0
- package/.mokogitea/ISSUE_TEMPLATE/question.md +82 -0
- package/.mokogitea/ISSUE_TEMPLATE/rfc.md +126 -0
- package/.mokogitea/ISSUE_TEMPLATE/security.md +51 -0
- package/.mokogitea/ISSUE_TEMPLATE/version.md +24 -0
- package/.mokogitea/branch-protection.yml +251 -0
- package/.mokogitea/workflows/auto-assign.yml +76 -0
- package/.mokogitea/workflows/auto-bump.yml +66 -0
- package/.mokogitea/workflows/auto-dev-issue.yml +207 -0
- package/.mokogitea/workflows/auto-release.yml +421 -0
- package/.mokogitea/workflows/branch-cleanup.yml +48 -0
- package/.mokogitea/workflows/cascade-dev.yml +10 -0
- package/.mokogitea/workflows/changelog-validation.yml +101 -0
- package/.mokogitea/workflows/ci-generic.yml +191 -0
- package/.mokogitea/workflows/cleanup.yml +87 -0
- package/.mokogitea/workflows/codeql-analysis.yml +115 -0
- package/.mokogitea/workflows/copilot-agent.yml +44 -0
- package/.mokogitea/workflows/deploy-manual.yml +126 -0
- package/.mokogitea/workflows/enterprise-firewall-setup.yml +758 -0
- package/.mokogitea/workflows/gitleaks.yml +92 -0
- package/.mokogitea/workflows/issue-branch.yml +73 -0
- package/.mokogitea/workflows/mcp-auto-release.yml +278 -0
- package/.mokogitea/workflows/mcp-build-test.yml +65 -0
- package/.mokogitea/workflows/mcp-sdk-check.yml +109 -0
- package/.mokogitea/workflows/mcp-tool-inventory.yml +61 -0
- package/.mokogitea/workflows/notify.yml +70 -0
- package/.mokogitea/workflows/npm-publish.yml +113 -0
- package/.mokogitea/workflows/pr-check.yml +534 -0
- package/.mokogitea/workflows/pre-release.yml +252 -0
- package/.mokogitea/workflows/rc-revert.yml +66 -0
- package/.mokogitea/workflows/repo-health.yml +712 -0
- package/.mokogitea/workflows/repository-cleanup.yml +525 -0
- package/.mokogitea/workflows/security-audit.yml +82 -0
- package/.mokogitea/workflows/standards-compliance.yml +2614 -0
- package/.mokogitea/workflows/sync-version-on-merge.yml +133 -0
- package/.mokogitea/workflows/update-server.yml +312 -0
- package/.mokogitea/workflows/workflow-sync-trigger.yml +73 -0
- package/CHANGELOG.md +130 -0
- package/CLAUDE.md +49 -0
- package/CONTRIBUTING.md +161 -0
- package/ISSUES.md +601 -0
- package/Makefile +70 -0
- package/README.md +80 -0
- package/automation/ci-issue-reporter.sh +237 -0
- package/config.example.json +18 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +111 -0
- package/dist/shell.d.ts +50 -0
- package/dist/shell.js +209 -0
- package/dist/tools/apps.d.ts +3 -0
- package/dist/tools/apps.js +63 -0
- package/dist/tools/audio.d.ts +3 -0
- package/dist/tools/audio.js +142 -0
- package/dist/tools/audio_apps.d.ts +3 -0
- package/dist/tools/audio_apps.js +86 -0
- package/dist/tools/automation.d.ts +3 -0
- package/dist/tools/automation.js +261 -0
- package/dist/tools/bluetooth.d.ts +3 -0
- package/dist/tools/bluetooth.js +96 -0
- package/dist/tools/clipboard.d.ts +3 -0
- package/dist/tools/clipboard.js +118 -0
- package/dist/tools/config.d.ts +3 -0
- package/dist/tools/config.js +85 -0
- package/dist/tools/dialog.d.ts +3 -0
- package/dist/tools/dialog.js +72 -0
- package/dist/tools/display.d.ts +3 -0
- package/dist/tools/display.js +256 -0
- package/dist/tools/drives.d.ts +3 -0
- package/dist/tools/drives.js +98 -0
- package/dist/tools/environment.d.ts +3 -0
- package/dist/tools/environment.js +129 -0
- package/dist/tools/execute.d.ts +3 -0
- package/dist/tools/execute.js +28 -0
- package/dist/tools/filesystem.d.ts +3 -0
- package/dist/tools/filesystem.js +230 -0
- package/dist/tools/firewall.d.ts +3 -0
- package/dist/tools/firewall.js +108 -0
- package/dist/tools/hosts.d.ts +3 -0
- package/dist/tools/hosts.js +119 -0
- package/dist/tools/maintenance.d.ts +3 -0
- package/dist/tools/maintenance.js +236 -0
- package/dist/tools/netstat.d.ts +3 -0
- package/dist/tools/netstat.js +56 -0
- package/dist/tools/network.d.ts +3 -0
- package/dist/tools/network.js +70 -0
- package/dist/tools/notification.d.ts +3 -0
- package/dist/tools/notification.js +41 -0
- package/dist/tools/power.d.ts +3 -0
- package/dist/tools/power.js +104 -0
- package/dist/tools/printer.d.ts +3 -0
- package/dist/tools/printer.js +97 -0
- package/dist/tools/process.d.ts +3 -0
- package/dist/tools/process.js +54 -0
- package/dist/tools/process_kill.d.ts +3 -0
- package/dist/tools/process_kill.js +48 -0
- package/dist/tools/recycle_bin.d.ts +3 -0
- package/dist/tools/recycle_bin.js +108 -0
- package/dist/tools/registry.d.ts +3 -0
- package/dist/tools/registry.js +136 -0
- package/dist/tools/scheduler.d.ts +3 -0
- package/dist/tools/scheduler.js +116 -0
- package/dist/tools/service.d.ts +3 -0
- package/dist/tools/service.js +79 -0
- package/dist/tools/startup.d.ts +3 -0
- package/dist/tools/startup.js +159 -0
- package/dist/tools/storage.d.ts +3 -0
- package/dist/tools/storage.js +129 -0
- package/dist/tools/system.d.ts +3 -0
- package/dist/tools/system.js +84 -0
- package/dist/tools/system_mgmt.d.ts +3 -0
- package/dist/tools/system_mgmt.js +174 -0
- package/dist/tools/terminal.d.ts +3 -0
- package/dist/tools/terminal.js +80 -0
- package/dist/tools/theme.d.ts +3 -0
- package/dist/tools/theme.js +165 -0
- package/dist/tools/usb.d.ts +3 -0
- package/dist/tools/usb.js +52 -0
- package/dist/tools/virtual_desktop.d.ts +3 -0
- package/dist/tools/virtual_desktop.js +112 -0
- package/dist/tools/wifi.d.ts +3 -0
- package/dist/tools/wifi.js +136 -0
- package/dist/tools/window.d.ts +3 -0
- package/dist/tools/window.js +189 -0
- package/dist/tools/winget.d.ts +3 -0
- package/dist/tools/winget.js +79 -0
- package/dist/tools/wsl.d.ts +3 -0
- package/dist/tools/wsl.js +99 -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/scripts/setup.mjs +123 -0
- package/src/index.ts +125 -0
- package/src/shell.ts +253 -0
- package/src/tools/apps.ts +76 -0
- package/src/tools/audio.ts +161 -0
- package/src/tools/audio_apps.ts +98 -0
- package/src/tools/automation.ts +297 -0
- package/src/tools/bluetooth.ts +114 -0
- package/src/tools/clipboard.ts +138 -0
- package/src/tools/config.ts +105 -0
- package/src/tools/dialog.ts +87 -0
- package/src/tools/display.ts +285 -0
- package/src/tools/drives.ts +124 -0
- package/src/tools/environment.ts +146 -0
- package/src/tools/execute.ts +35 -0
- package/src/tools/filesystem.ts +273 -0
- package/src/tools/firewall.ts +125 -0
- package/src/tools/hosts.ts +135 -0
- package/src/tools/maintenance.ts +299 -0
- package/src/tools/netstat.ts +72 -0
- package/src/tools/network.ts +84 -0
- package/src/tools/notification.ts +50 -0
- package/src/tools/power.ts +123 -0
- package/src/tools/printer.ts +114 -0
- package/src/tools/process.ts +80 -0
- package/src/tools/process_kill.ts +57 -0
- package/src/tools/recycle_bin.ts +126 -0
- package/src/tools/registry.ts +165 -0
- package/src/tools/scheduler.ts +140 -0
- package/src/tools/service.ts +102 -0
- package/src/tools/startup.ts +180 -0
- package/src/tools/storage.ts +141 -0
- package/src/tools/system.ts +99 -0
- package/src/tools/system_mgmt.ts +190 -0
- package/src/tools/terminal.ts +117 -0
- package/src/tools/theme.ts +205 -0
- package/src/tools/usb.ts +65 -0
- package/src/tools/virtual_desktop.ts +122 -0
- package/src/tools/wifi.ts +157 -0
- package/src/tools/window.ts +211 -0
- package/src/tools/winget.ts +100 -0
- package/src/tools/wsl.ts +112 -0
- package/tsconfig.json +19 -0
|
@@ -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 .mokogitea/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
|
|
@@ -0,0 +1,421 @@
|
|
|
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: Gitea.Workflow
|
|
7
|
+
# INGROUP: mokocli.Release
|
|
8
|
+
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
|
|
9
|
+
# PATH: /templates/workflows/universal/auto-release.yml.template
|
|
10
|
+
# VERSION: 05.00.00
|
|
11
|
+
# BRIEF: Universal build & release � detects platform from manifest.xml
|
|
12
|
+
#
|
|
13
|
+
# +========================================================================+
|
|
14
|
+
# | UNIVERSAL BUILD & RELEASE PIPELINE |
|
|
15
|
+
# +========================================================================+
|
|
16
|
+
# | |
|
|
17
|
+
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
|
|
18
|
+
# | |
|
|
19
|
+
# | Platform-specific: |
|
|
20
|
+
# | joomla: XML manifest, type-prefixed packages |
|
|
21
|
+
# | dolibarr: mod*.class.php, update.txt, dev version reset |
|
|
22
|
+
# | generic: README-only, no update stream |
|
|
23
|
+
# | |
|
|
24
|
+
# +========================================================================+
|
|
25
|
+
|
|
26
|
+
name: "Universal: Build & Release"
|
|
27
|
+
|
|
28
|
+
on:
|
|
29
|
+
pull_request:
|
|
30
|
+
types: [opened, closed]
|
|
31
|
+
branches:
|
|
32
|
+
- main
|
|
33
|
+
workflow_dispatch:
|
|
34
|
+
inputs:
|
|
35
|
+
action:
|
|
36
|
+
description: 'Action to perform'
|
|
37
|
+
required: false
|
|
38
|
+
type: choice
|
|
39
|
+
default: release
|
|
40
|
+
options:
|
|
41
|
+
- release
|
|
42
|
+
- promote-rc
|
|
43
|
+
|
|
44
|
+
env:
|
|
45
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
46
|
+
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
|
47
|
+
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
|
|
48
|
+
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
|
|
49
|
+
|
|
50
|
+
permissions:
|
|
51
|
+
contents: write
|
|
52
|
+
|
|
53
|
+
jobs:
|
|
54
|
+
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────
|
|
55
|
+
promote-rc:
|
|
56
|
+
name: Promote to RC
|
|
57
|
+
runs-on: release
|
|
58
|
+
if: >-
|
|
59
|
+
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
|
|
60
|
+
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
|
|
61
|
+
|
|
62
|
+
steps:
|
|
63
|
+
- name: Checkout repository
|
|
64
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
65
|
+
with:
|
|
66
|
+
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
|
67
|
+
fetch-depth: 1
|
|
68
|
+
|
|
69
|
+
- name: Setup mokocli tools
|
|
70
|
+
env:
|
|
71
|
+
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
|
72
|
+
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
|
73
|
+
run: |
|
|
74
|
+
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
|
75
|
+
echo Using pre-installed /opt/mokocli
|
|
76
|
+
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
|
77
|
+
else
|
|
78
|
+
echo Falling back to fresh clone
|
|
79
|
+
if ! command -v composer > /dev/null 2>&1; then
|
|
80
|
+
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
|
|
81
|
+
fi
|
|
82
|
+
rm -rf /tmp/mokocli
|
|
83
|
+
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
|
84
|
+
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
|
85
|
+
cd /tmp/mokocli
|
|
86
|
+
composer install --no-dev --no-interaction --quiet
|
|
87
|
+
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
- name: Rename branch to rc
|
|
91
|
+
run: |
|
|
92
|
+
php ${MOKO_CLI}/branch_rename.php \
|
|
93
|
+
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
|
|
94
|
+
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
|
95
|
+
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
|
|
96
|
+
--pr "${{ github.event.pull_request.number }}"
|
|
97
|
+
|
|
98
|
+
- name: Checkout rc and configure git
|
|
99
|
+
run: |
|
|
100
|
+
git fetch origin rc
|
|
101
|
+
git checkout rc
|
|
102
|
+
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
|
103
|
+
git config --local user.name "gitea-actions[bot]"
|
|
104
|
+
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
|
105
|
+
|
|
106
|
+
- name: Publish RC release
|
|
107
|
+
run: |
|
|
108
|
+
php ${MOKO_CLI}/release_publish.php \
|
|
109
|
+
--path . --stability rc --bump minor --branch rc \
|
|
110
|
+
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
|
111
|
+
|
|
112
|
+
- name: Update RC release notes from CHANGELOG.md
|
|
113
|
+
run: |
|
|
114
|
+
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
|
115
|
+
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
|
116
|
+
|
|
117
|
+
# Extract [Unreleased] section from changelog
|
|
118
|
+
NOTES=""
|
|
119
|
+
if [ -f "CHANGELOG.md" ]; then
|
|
120
|
+
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
|
|
121
|
+
fi
|
|
122
|
+
[ -z "$NOTES" ] && NOTES="Release candidate"
|
|
123
|
+
|
|
124
|
+
# Find the RC release and update its body
|
|
125
|
+
RELEASE_ID=$(curl -sf -H "Authorization: token ${TOKEN}" \
|
|
126
|
+
"${API_BASE}/releases/tags/release-candidate" \
|
|
127
|
+
| python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
|
128
|
+
|
|
129
|
+
if [ -n "$RELEASE_ID" ]; then
|
|
130
|
+
python3 -c "
|
|
131
|
+
import json, urllib.request
|
|
132
|
+
body = open('/dev/stdin').read()
|
|
133
|
+
payload = json.dumps({'body': body}).encode()
|
|
134
|
+
req = urllib.request.Request(
|
|
135
|
+
'${API_BASE}/releases/${RELEASE_ID}',
|
|
136
|
+
data=payload, method='PATCH',
|
|
137
|
+
headers={
|
|
138
|
+
'Authorization': 'token ${TOKEN}',
|
|
139
|
+
'Content-Type': 'application/json'
|
|
140
|
+
})
|
|
141
|
+
urllib.request.urlopen(req)
|
|
142
|
+
" <<< "$NOTES"
|
|
143
|
+
echo "RC release notes updated from CHANGELOG.md"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
- name: Summary
|
|
147
|
+
if: always()
|
|
148
|
+
run: |
|
|
149
|
+
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
|
|
150
|
+
echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
|
|
151
|
+
|
|
152
|
+
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
|
|
153
|
+
release:
|
|
154
|
+
name: Build & Release Pipeline
|
|
155
|
+
runs-on: release
|
|
156
|
+
if: >-
|
|
157
|
+
github.event.pull_request.merged == true ||
|
|
158
|
+
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
|
|
159
|
+
|
|
160
|
+
steps:
|
|
161
|
+
- name: Checkout repository
|
|
162
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
163
|
+
with:
|
|
164
|
+
token: ${{ secrets.MOKOGITEA_TOKEN }}
|
|
165
|
+
fetch-depth: 0
|
|
166
|
+
|
|
167
|
+
- name: Configure git for bot pushes
|
|
168
|
+
run: |
|
|
169
|
+
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
|
170
|
+
git config --local user.name "gitea-actions[bot]"
|
|
171
|
+
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
|
172
|
+
|
|
173
|
+
- name: Check for merge conflict markers
|
|
174
|
+
run: |
|
|
175
|
+
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
|
|
176
|
+
if [ -n "$CONFLICTS" ]; then
|
|
177
|
+
echo "::error::Merge conflict markers found — aborting release"
|
|
178
|
+
echo "## Release Blocked: Conflict Markers" >> $GITHUB_STEP_SUMMARY
|
|
179
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
180
|
+
echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
|
|
181
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
echo "No conflict markers found"
|
|
185
|
+
|
|
186
|
+
- name: Setup mokocli tools
|
|
187
|
+
env:
|
|
188
|
+
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
|
189
|
+
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
|
190
|
+
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
|
|
191
|
+
run: |
|
|
192
|
+
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
|
193
|
+
echo Using pre-installed /opt/mokocli
|
|
194
|
+
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
|
195
|
+
else
|
|
196
|
+
echo Falling back to fresh clone
|
|
197
|
+
if ! command -v composer > /dev/null 2>&1; then
|
|
198
|
+
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
|
|
199
|
+
fi
|
|
200
|
+
rm -rf /tmp/mokocli
|
|
201
|
+
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
|
202
|
+
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
|
203
|
+
cd /tmp/mokocli
|
|
204
|
+
composer install --no-dev --no-interaction --quiet
|
|
205
|
+
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
- name: "Detect platform"
|
|
209
|
+
id: platform
|
|
210
|
+
run: |
|
|
211
|
+
php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
|
|
212
|
+
php ${MOKO_CLI}/manifest_read.php --path . --github-output 2>/dev/null || true
|
|
213
|
+
|
|
214
|
+
- name: "Determine version bump level"
|
|
215
|
+
id: bump
|
|
216
|
+
run: |
|
|
217
|
+
# Fix/patch branches: version was already bumped by pre-release, just strip suffix
|
|
218
|
+
# Feature/dev branches: bump minor for the new stable release
|
|
219
|
+
HEAD_REF="${{ github.event.pull_request.head.ref || 'dev' }}"
|
|
220
|
+
case "$HEAD_REF" in
|
|
221
|
+
fix/*|patch/*|hotfix/*|bugfix/*) BUMP="none" ;;
|
|
222
|
+
*) BUMP="minor" ;;
|
|
223
|
+
esac
|
|
224
|
+
echo "level=${BUMP}" >> "$GITHUB_OUTPUT"
|
|
225
|
+
echo "Bump level: ${BUMP} (from branch: ${HEAD_REF})"
|
|
226
|
+
|
|
227
|
+
- name: "Publish stable release"
|
|
228
|
+
run: |
|
|
229
|
+
BUMP_FLAG=""
|
|
230
|
+
if [ "${{ steps.bump.outputs.level }}" != "none" ]; then
|
|
231
|
+
BUMP_FLAG="--bump ${{ steps.bump.outputs.level }}"
|
|
232
|
+
fi
|
|
233
|
+
php ${MOKO_CLI}/release_publish.php \
|
|
234
|
+
--path . --stability stable ${BUMP_FLAG} --branch main \
|
|
235
|
+
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
|
236
|
+
|
|
237
|
+
- name: "Read published version"
|
|
238
|
+
id: version
|
|
239
|
+
run: |
|
|
240
|
+
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "")
|
|
241
|
+
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
|
|
242
|
+
[ -z "$VERSION" ] && VERSION="00.00.00" && echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
243
|
+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
244
|
+
echo "tag=stable" >> "$GITHUB_OUTPUT"
|
|
245
|
+
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
|
|
246
|
+
echo "branch=main" >> "$GITHUB_OUTPUT"
|
|
247
|
+
echo "Published version: ${VERSION}"
|
|
248
|
+
|
|
249
|
+
- name: Update release notes and promote changelog
|
|
250
|
+
run: |
|
|
251
|
+
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
|
252
|
+
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
|
253
|
+
|
|
254
|
+
# Get the stable release info (version and ID)
|
|
255
|
+
RELEASE_JSON=$(curl -sf -H "Authorization: token ${TOKEN}" \
|
|
256
|
+
"${API_BASE}/releases/tags/stable" 2>/dev/null || echo '{}')
|
|
257
|
+
RELEASE_ID=$(python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" <<< "$RELEASE_JSON" 2>/dev/null || true)
|
|
258
|
+
# Extract version from release name (e.g. "06.17.00" or "v06.17.00")
|
|
259
|
+
VERSION=$(python3 -c "
|
|
260
|
+
import json, sys, re
|
|
261
|
+
r = json.load(sys.stdin)
|
|
262
|
+
name = r.get('name', '')
|
|
263
|
+
m = re.search(r'(\d+\.\d+\.\d+)', name)
|
|
264
|
+
print(m.group(1) if m else '')
|
|
265
|
+
" <<< "$RELEASE_JSON" 2>/dev/null || true)
|
|
266
|
+
|
|
267
|
+
# Extract [Unreleased] section from changelog
|
|
268
|
+
NOTES=""
|
|
269
|
+
if [ -f "CHANGELOG.md" ]; then
|
|
270
|
+
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
|
|
271
|
+
fi
|
|
272
|
+
[ -z "$NOTES" ] && NOTES="Stable release"
|
|
273
|
+
|
|
274
|
+
# Update release body via API
|
|
275
|
+
if [ -n "$RELEASE_ID" ]; then
|
|
276
|
+
python3 -c "
|
|
277
|
+
import json, urllib.request
|
|
278
|
+
body = open('/dev/stdin').read()
|
|
279
|
+
payload = json.dumps({'body': body}).encode()
|
|
280
|
+
req = urllib.request.Request(
|
|
281
|
+
'${API_BASE}/releases/${RELEASE_ID}',
|
|
282
|
+
data=payload, method='PATCH',
|
|
283
|
+
headers={
|
|
284
|
+
'Authorization': 'token ${TOKEN}',
|
|
285
|
+
'Content-Type': 'application/json'
|
|
286
|
+
})
|
|
287
|
+
urllib.request.urlopen(req)
|
|
288
|
+
" <<< "$NOTES"
|
|
289
|
+
echo "Release notes updated from CHANGELOG.md"
|
|
290
|
+
fi
|
|
291
|
+
|
|
292
|
+
# Promote [Unreleased] → [version] in CHANGELOG.md and reset
|
|
293
|
+
if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then
|
|
294
|
+
DATE=$(date +%Y-%m-%d)
|
|
295
|
+
python3 -c "
|
|
296
|
+
import sys
|
|
297
|
+
version, date = sys.argv[1], sys.argv[2]
|
|
298
|
+
content = open('CHANGELOG.md').read()
|
|
299
|
+
old = '## [Unreleased]'
|
|
300
|
+
new = f'## [Unreleased]\n\n## [{version}] --- {date}'
|
|
301
|
+
content = content.replace(old, new, 1)
|
|
302
|
+
open('CHANGELOG.md', 'w').write(content)
|
|
303
|
+
" "$VERSION" "$DATE"
|
|
304
|
+
git add CHANGELOG.md
|
|
305
|
+
git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true
|
|
306
|
+
git push origin main || true
|
|
307
|
+
echo "Changelog promoted: [Unreleased] → [${VERSION}]"
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
|
311
|
+
- name: "Step 9: Mirror release to GitHub"
|
|
312
|
+
if: >-
|
|
313
|
+
steps.version.outputs.skip != 'true' &&
|
|
314
|
+
secrets.GH_MIRROR_TOKEN != ''
|
|
315
|
+
continue-on-error: true
|
|
316
|
+
run: |
|
|
317
|
+
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
|
318
|
+
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
|
319
|
+
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
|
320
|
+
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
|
321
|
+
php ${MOKO_CLI}/release_mirror.php \
|
|
322
|
+
--version "$VERSION" --tag "$RELEASE_TAG" \
|
|
323
|
+
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
|
324
|
+
--gh-token "${{ secrets.GH_MIRROR_TOKEN }}" --gh-repo "$GH_REPO" \
|
|
325
|
+
--branch main 2>&1 || true
|
|
326
|
+
echo "GitHub mirror updated" >> $GITHUB_STEP_SUMMARY
|
|
327
|
+
|
|
328
|
+
# -- STEP 10: Sync main branch to GitHub mirror ----------------------------
|
|
329
|
+
- name: "Step 10: Push main to GitHub mirror"
|
|
330
|
+
if: >-
|
|
331
|
+
steps.version.outputs.skip != 'true' &&
|
|
332
|
+
secrets.GH_MIRROR_TOKEN != ''
|
|
333
|
+
continue-on-error: true
|
|
334
|
+
run: |
|
|
335
|
+
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
|
336
|
+
GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
|
|
337
|
+
GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
|
|
338
|
+
git remote add github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
|
|
339
|
+
git remote set-url github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
|
|
340
|
+
git fetch origin main --depth=1
|
|
341
|
+
git push github origin/main:refs/heads/main --force 2>/dev/null \
|
|
342
|
+
&& echo "main branch pushed to GitHub mirror" \
|
|
343
|
+
|| echo "WARNING: GitHub mirror push failed"
|
|
344
|
+
|
|
345
|
+
- name: "Step 11: Delete rc branch and recreate dev from main"
|
|
346
|
+
if: steps.version.outputs.skip != 'true'
|
|
347
|
+
continue-on-error: true
|
|
348
|
+
run: |
|
|
349
|
+
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
|
350
|
+
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
|
351
|
+
|
|
352
|
+
# Delete rc branch (ephemeral — created by promote-rc)
|
|
353
|
+
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
|
354
|
+
"${API_BASE}/branches/rc" 2>/dev/null \
|
|
355
|
+
&& echo "Deleted rc branch" || echo "rc branch not found"
|
|
356
|
+
|
|
357
|
+
# Delete dev branch
|
|
358
|
+
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
|
359
|
+
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
|
|
360
|
+
|
|
361
|
+
# Recreate dev from main (now includes version bump + changelog promotion)
|
|
362
|
+
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
|
|
363
|
+
-H "Content-Type: application/json" \
|
|
364
|
+
"${API_BASE}/branches" \
|
|
365
|
+
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
|
|
366
|
+
|
|
367
|
+
echo "Pre-release branches cleaned, dev reset from main" >> $GITHUB_STEP_SUMMARY
|
|
368
|
+
|
|
369
|
+
- name: "Step 12: Create version branch from main"
|
|
370
|
+
if: steps.version.outputs.skip != 'true'
|
|
371
|
+
continue-on-error: true
|
|
372
|
+
run: |
|
|
373
|
+
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
|
374
|
+
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
|
375
|
+
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
|
376
|
+
BRANCH_NAME="version/${VERSION}"
|
|
377
|
+
MAIN_SHA=$(git rev-parse HEAD)
|
|
378
|
+
|
|
379
|
+
# Delete old version branch if it exists (same version re-release)
|
|
380
|
+
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" "${API_BASE}/branches/${BRANCH_NAME}" 2>/dev/null && echo "Deleted old ${BRANCH_NAME}"
|
|
381
|
+
|
|
382
|
+
# Create version/XX.YY.ZZ from main
|
|
383
|
+
curl -sf -X POST -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API_BASE}/branches" -d "{\"new_branch_name\":\"${BRANCH_NAME}\",\"old_branch_name\":\"main\"}" 2>/dev/null && echo "Created ${BRANCH_NAME} from main (${MAIN_SHA})" || echo "WARNING: ${BRANCH_NAME} creation failed"
|
|
384
|
+
|
|
385
|
+
echo "Version branch created: ${BRANCH_NAME} (${MAIN_SHA})" >> $GITHUB_STEP_SUMMARY
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
# -- Dolibarr post-release: Reset dev version -----------------------------
|
|
390
|
+
- name: "Post-release: Reset dev version"
|
|
391
|
+
if: steps.version.outputs.skip != 'true'
|
|
392
|
+
continue-on-error: true
|
|
393
|
+
run: |
|
|
394
|
+
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
|
395
|
+
php ${MOKO_CLI}/version_reset_dev.php \
|
|
396
|
+
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
|
|
397
|
+
--branch dev --path . 2>&1 || true
|
|
398
|
+
|
|
399
|
+
# -- Summary --------------------------------------------------------------
|
|
400
|
+
- name: Pipeline Summary
|
|
401
|
+
if: always()
|
|
402
|
+
run: |
|
|
403
|
+
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
|
404
|
+
PLATFORM="${{ steps.platform.outputs.platform }}"
|
|
405
|
+
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
|
|
406
|
+
echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
|
|
407
|
+
echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
|
|
408
|
+
elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
|
|
409
|
+
echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
|
410
|
+
else
|
|
411
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
412
|
+
echo "## Build & Release Complete (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
|
|
413
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
414
|
+
echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
|
|
415
|
+
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
|
|
416
|
+
echo "| Platform | \`${PLATFORM}\` |" >> $GITHUB_STEP_SUMMARY
|
|
417
|
+
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
|
|
418
|
+
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
419
|
+
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
420
|
+
echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
|
|
421
|
+
fi
|
|
@@ -0,0 +1,48 @@
|
|
|
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: Gitea.Workflow
|
|
7
|
+
# INGROUP: MokoStandards.Universal
|
|
8
|
+
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
|
|
9
|
+
# PATH: /.mokogitea/workflows/branch-cleanup.yml
|
|
10
|
+
# VERSION: 01.00.00
|
|
11
|
+
# BRIEF: Delete feature branches after PR merge
|
|
12
|
+
|
|
13
|
+
name: "Branch Cleanup"
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
pull_request:
|
|
17
|
+
types: [closed]
|
|
18
|
+
|
|
19
|
+
env:
|
|
20
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
cleanup:
|
|
24
|
+
name: Delete merged branch
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
if: >-
|
|
27
|
+
github.event.pull_request.merged == true &&
|
|
28
|
+
github.event.pull_request.head.ref != 'dev' &&
|
|
29
|
+
github.event.pull_request.head.ref != 'main'
|
|
30
|
+
|
|
31
|
+
steps:
|
|
32
|
+
- name: Delete source branch
|
|
33
|
+
run: |
|
|
34
|
+
BRANCH="${{ github.event.pull_request.head.ref }}"
|
|
35
|
+
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
|
|
36
|
+
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
|
|
37
|
+
|
|
38
|
+
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
|
|
39
|
+
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
|
|
40
|
+
"${API}/${ENCODED}" 2>/dev/null || true)
|
|
41
|
+
|
|
42
|
+
if [ "$STATUS" = "204" ]; then
|
|
43
|
+
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
|
|
44
|
+
elif [ "$STATUS" = "404" ]; then
|
|
45
|
+
echo "Branch already deleted: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
|
|
46
|
+
else
|
|
47
|
+
echo "::warning::Failed to delete branch ${BRANCH} (HTTP ${STATUS})"
|
|
48
|
+
fi
|