mirror of https://github.com/garrytan/gstack.git
fix: CI report needs checkout + routing needs user-level skill install
Two fixes: 1. Report job: add actions/checkout so `gh pr comment` has git context. Also add pull-requests:write permission for comment posting. 2. Routing tests: install skills to BOTH project-level (.claude/skills/) AND user-level (~/.claude/skills/) since Claude Code discovers from both locations. In CI containers, $HOME differs from workdir. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4d91456b3c
commit
e6c6422cec
|
|
@ -130,7 +130,14 @@ jobs:
|
||||||
needs: evals
|
needs: evals
|
||||||
if: always() && github.event_name == 'pull_request'
|
if: always() && github.event_name == 'pull_request'
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
- name: Download all eval artifacts
|
- name: Download all eval artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,11 @@ if (evalsEnabled && !process.env.EVALS_ALL) {
|
||||||
|
|
||||||
// --- Helper functions ---
|
// --- Helper functions ---
|
||||||
|
|
||||||
/** Copy all SKILL.md files into tmpDir/.claude/skills/gstack/ for auto-discovery,
|
/** Copy all SKILL.md files for auto-discovery.
|
||||||
* plus CLAUDE.md so Claude has project context for routing decisions. */
|
* Install to BOTH project-level (.claude/skills/) AND user-level (~/.claude/skills/)
|
||||||
|
* because Claude Code discovers skills from both locations. In CI containers,
|
||||||
|
* $HOME may differ from the working directory, so we need both paths to ensure
|
||||||
|
* the Skill tool appears in Claude's available tools list. */
|
||||||
function installSkills(tmpDir: string) {
|
function installSkills(tmpDir: string) {
|
||||||
const skillDirs = [
|
const skillDirs = [
|
||||||
'', // root gstack SKILL.md
|
'', // root gstack SKILL.md
|
||||||
|
|
@ -55,24 +58,27 @@ function installSkills(tmpDir: string) {
|
||||||
'gstack-upgrade', 'humanizer',
|
'gstack-upgrade', 'humanizer',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Install to both project-level and user-level skill directories
|
||||||
|
const homeDir = process.env.HOME || os.homedir();
|
||||||
|
const installTargets = [
|
||||||
|
path.join(tmpDir, '.claude', 'skills'), // project-level
|
||||||
|
path.join(homeDir, '.claude', 'skills'), // user-level (~/.claude/skills/)
|
||||||
|
];
|
||||||
|
|
||||||
for (const skill of skillDirs) {
|
for (const skill of skillDirs) {
|
||||||
const srcPath = path.join(ROOT, skill, 'SKILL.md');
|
const srcPath = path.join(ROOT, skill, 'SKILL.md');
|
||||||
if (!fs.existsSync(srcPath)) continue;
|
if (!fs.existsSync(srcPath)) continue;
|
||||||
|
|
||||||
// Install skills at TOP level of .claude/skills/ so Claude Code discovers
|
const skillName = skill || 'gstack';
|
||||||
// each as a separate invocable skill. Nesting under .claude/skills/gstack/
|
|
||||||
// only works for personal skills (~/.claude/skills/) — project-level skills
|
for (const targetBase of installTargets) {
|
||||||
// need to be top-level for discovery.
|
const destDir = path.join(targetBase, skillName);
|
||||||
const destDir = skill
|
fs.mkdirSync(destDir, { recursive: true });
|
||||||
? path.join(tmpDir, '.claude', 'skills', skill)
|
fs.copyFileSync(srcPath, path.join(destDir, 'SKILL.md'));
|
||||||
: path.join(tmpDir, '.claude', 'skills', 'gstack');
|
}
|
||||||
fs.mkdirSync(destDir, { recursive: true });
|
|
||||||
fs.copyFileSync(srcPath, path.join(destDir, 'SKILL.md'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy CLAUDE.md so Claude has project context for skill routing.
|
// Copy CLAUDE.md so Claude has project context for skill routing.
|
||||||
// Without this, Claude in containerized environments lacks the context
|
|
||||||
// that guides it to invoke specific skills vs answering directly.
|
|
||||||
const claudeMdSrc = path.join(ROOT, 'CLAUDE.md');
|
const claudeMdSrc = path.join(ROOT, 'CLAUDE.md');
|
||||||
if (fs.existsSync(claudeMdSrc)) {
|
if (fs.existsSync(claudeMdSrc)) {
|
||||||
fs.copyFileSync(claudeMdSrc, path.join(tmpDir, 'CLAUDE.md'));
|
fs.copyFileSync(claudeMdSrc, path.join(tmpDir, 'CLAUDE.md'));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue