Skip to content

Commit c18328a

Browse files
authored
fix: install jcodemunch-mcp from github (#24)
2 parents 0e9d44a + 984bbb1 commit c18328a

2 files changed

Lines changed: 236 additions & 6 deletions

File tree

.github/workflows/advance-tags.yml

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Advances selected release tags to merged PR commit so existing tag-push build
2+
name: Advance Major Release Tags After Merge
3+
4+
on:
5+
pull_request:
6+
types:
7+
- closed
8+
9+
workflow_dispatch:
10+
inputs:
11+
tag_update_mode:
12+
description: Which release tags to advance
13+
required: false
14+
type: choice
15+
default: latest-per-major
16+
options:
17+
- latest-per-major
18+
- all-release-tags
19+
20+
permissions:
21+
pull-requests: read
22+
contents: write
23+
24+
jobs:
25+
advance-tags:
26+
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Detect changed files
30+
id: changed-files
31+
if: github.event_name == 'pull_request'
32+
uses: tj-actions/changed-files@v47
33+
with:
34+
files: |
35+
Dockerfile
36+
skills.yaml
37+
scripts/**
38+
39+
- name: Generate GitHub App token
40+
id: app_token
41+
if: github.event_name == 'workflow_dispatch' || steps.changed-files.outputs.any_changed == 'true'
42+
uses: actions/create-github-app-token@v3
43+
with:
44+
client-id: ${{ secrets.WORKFLOW_APP_ID }}
45+
private-key: ${{ secrets.WORKFLOW_APP_PRIVATE_KEY }}
46+
47+
- name: Write skip report when path filter does not match
48+
if: github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed != 'true'
49+
uses: actions/github-script@v9
50+
with:
51+
script: |
52+
await core.summary
53+
.addHeading('Release Tag Advancement Report')
54+
.addTable([
55+
[{ data: 'Field', header: true }, { data: 'Value', header: true }],
56+
['Event', context.eventName],
57+
['Mode', 'path-filtered'],
58+
['Matched files', '0'],
59+
['Action', 'Skipped'],
60+
])
61+
.addRaw('\nClosed PR did not change any configured release-trigger files. No tags were advanced.\n')
62+
.write();
63+
64+
- name: Advance release tags
65+
if: github.event_name == 'workflow_dispatch' || steps.changed-files.outputs.any_changed == 'true'
66+
uses: actions/github-script@v9
67+
env:
68+
TARGET_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.merge_commit_sha || github.sha }}
69+
TAG_UPDATE_MODE: ${{ inputs.tag_update_mode || vars.TAG_UPDATE_MODE || 'latest-per-major' }}
70+
with:
71+
github-token: ${{ steps.app_token.outputs.token }}
72+
script: |
73+
const targetSha = process.env.TARGET_SHA;
74+
const tagUpdateMode = process.env.TAG_UPDATE_MODE;
75+
const semverTagPattern = /^v(\d+)\.(\d+)\.(\d+)$/;
76+
const shortSha = targetSha.slice(0, 7);
77+
78+
const compareVersions = (left, right) => {
79+
if (left.major !== right.major) return left.major - right.major;
80+
if (left.minor !== right.minor) return left.minor - right.minor;
81+
return left.patch - right.patch;
82+
};
83+
84+
const tags = await github.paginate(github.rest.repos.listTags, {
85+
owner: context.repo.owner,
86+
repo: context.repo.repo,
87+
per_page: 100,
88+
});
89+
90+
const releaseTags = tags
91+
.map((tag) => {
92+
const match = tag.name.match(semverTagPattern);
93+
if (!match) return null;
94+
return {
95+
name: tag.name,
96+
sha: tag.commit.sha,
97+
major: Number(match[1]),
98+
minor: Number(match[2]),
99+
patch: Number(match[3]),
100+
};
101+
})
102+
.filter(Boolean)
103+
.sort((left, right) => compareVersions(left, right));
104+
105+
if (releaseTags.length === 0) {
106+
core.info('No semantic release tags found. Nothing to update.');
107+
await core.summary
108+
.addHeading('Release Tag Advancement Report')
109+
.addTable([
110+
[{ data: 'Field', header: true }, { data: 'Value', header: true }],
111+
['Event', context.eventName],
112+
['Mode', tagUpdateMode],
113+
['Target commit', `\`${targetSha}\``],
114+
['Semantic release tags found', '0'],
115+
['Updated tags', '0'],
116+
])
117+
.addRaw('\nNo semantic release tags found. Nothing changed.\n')
118+
.write();
119+
return;
120+
}
121+
122+
let tagsToUpdate;
123+
if (tagUpdateMode === 'all-release-tags') {
124+
tagsToUpdate = releaseTags;
125+
} else if (tagUpdateMode === 'latest-per-major') {
126+
const latestByMajor = new Map();
127+
for (const tag of releaseTags) {
128+
latestByMajor.set(tag.major, tag);
129+
}
130+
tagsToUpdate = [...latestByMajor.keys()]
131+
.sort((a, b) => a - b)
132+
.map((major) => latestByMajor.get(major));
133+
} else {
134+
core.setFailed(`Unsupported TAG_UPDATE_MODE: ${tagUpdateMode}`);
135+
return;
136+
}
137+
138+
core.info(`Tag update mode: ${tagUpdateMode}`);
139+
140+
const updatedTags = [];
141+
const skippedTags = [];
142+
const failedTags = [];
143+
144+
let updated = 0;
145+
for (const tag of tagsToUpdate) {
146+
147+
if (tag.sha === targetSha) {
148+
core.info(`${tag.name} already points at ${targetSha}`);
149+
skippedTags.push(tag);
150+
continue;
151+
}
152+
153+
core.info(`Moving ${tag.name} from ${tag.sha} to ${targetSha}`);
154+
try {
155+
await github.rest.git.updateRef({
156+
owner: context.repo.owner,
157+
repo: context.repo.repo,
158+
ref: `tags/${tag.name}`,
159+
sha: targetSha,
160+
force: true,
161+
});
162+
updated += 1;
163+
updatedTags.push(tag);
164+
} catch (error) {
165+
const message = error instanceof Error ? error.message : String(error);
166+
core.error(`Failed to move ${tag.name}: ${message}`);
167+
failedTags.push({
168+
...tag,
169+
error: message,
170+
});
171+
}
172+
}
173+
174+
if (updated === 0) {
175+
core.info('No tags changed.');
176+
}
177+
178+
const renderTagRows = (items, emptyText) => {
179+
if (items.length === 0) {
180+
return `${emptyText}\n`;
181+
}
182+
183+
const rows = items.map((tag) => {
184+
const fromSha = tag.sha ? `\`${tag.sha.slice(0, 7)}\`` : '-';
185+
return `| \`${tag.name}\` | ${fromSha} | \`${shortSha}\` |`;
186+
});
187+
188+
return [
189+
'| Tag | Previous | Current |',
190+
'| --- | --- | --- |',
191+
...rows,
192+
].join('\n');
193+
};
194+
195+
const renderFailedRows = () => {
196+
if (failedTags.length === 0) {
197+
return 'No tag updates failed.\n';
198+
}
199+
200+
const rows = failedTags.map((tag) => (
201+
`| \`${tag.name}\` | \`${tag.sha.slice(0, 7)}\` | \`${shortSha}\` | ${tag.error.replace(/\n/g, ' ')} |`
202+
));
203+
204+
return [
205+
'| Tag | Previous | Current | Error |',
206+
'| --- | --- | --- | --- |',
207+
...rows,
208+
].join('\n');
209+
};
210+
211+
await core.summary
212+
.addHeading('Release Tag Advancement Report')
213+
.addTable([
214+
[{ data: 'Field', header: true }, { data: 'Value', header: true }],
215+
['Event', context.eventName],
216+
['Mode', tagUpdateMode],
217+
['Target commit', `\`${targetSha}\``],
218+
['Semantic release tags found', String(releaseTags.length)],
219+
['Selected tags', String(tagsToUpdate.length)],
220+
['Updated tags', String(updatedTags.length)],
221+
['Already current', String(skippedTags.length)],
222+
])
223+
.addHeading('Updated Tags', 2)
224+
.addRaw(`\n${renderTagRows(updatedTags, 'No tags were updated.')}\n`)
225+
.addHeading('Already Current', 2)
226+
.addRaw(`\n${renderTagRows(skippedTags, 'No tags already pointed at target commit.')}\n`)
227+
.addHeading('Failed Updates', 2)
228+
.addRaw(`\n${renderFailedRows()}\n`)
229+
.write();
230+
231+
if (failedTags.length > 0) {
232+
core.setFailed(`Failed to advance ${failedTags.length} release tag(s). See workflow summary for details.`);
233+
}

Dockerfile

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,6 @@ resolve_github_latest_version() {
117117
echo "${version}"
118118
}
119119

120-
resolve_caveman_version() {
121-
resolve_github_latest_version "JuliusBrussee/caveman" "${CAVEMAN_VERSION}"
122-
}
123-
124120
mkdir -p "${BUN_INSTALL}" "${OPENCODE_CONFIG_DIR}" "${OPENCODE_PLUGINS_DIR}" "${PROVIDER_DIR}"
125121
chmod 0777 "${OPENCODE_CONFIG_DIR}"
126122

@@ -174,7 +170,8 @@ curl -fsSL "${uv_url}" | tar -C /usr/local/bin -xvzf - --strip-components=1 --wi
174170

175171
##
176172
# jcodemunch-mcp
177-
uv pip install --system jcodemunch-mcp || exit 1
173+
jcodemunch_mcp_resolved_version=$(resolve_github_latest_version "jgravelle/jcodemunch-mcp" "${JCODEMUNCH_MCP_VERSION:-latest}") || exit 1
174+
uv pip install --system "git+https://github.com/jgravelle/jcodemunch-mcp.git@${jcodemunch_mcp_resolved_version}" || exit 1
178175

179176
##
180177
# rtk
@@ -193,7 +190,7 @@ bun install -g --trust skills@latest
193190
###
194191
# caveman
195192
#
196-
caveman_resolved_version=$(resolve_caveman_version) || exit 1
193+
caveman_resolved_version=$(resolve_github_latest_version "JuliusBrussee/caveman" "${CAVEMAN_VERSION}") || exit 1
197194
echo "CAVEMAN_RESOLVED_REF=${caveman_resolved_version}"
198195
echo "${caveman_resolved_version}" > /tmp/caveman_version
199196

0 commit comments

Comments
 (0)