* ci(workflows): use host-uk/build@dev for releases
- Replace manual Go bootstrap with host-uk/build@dev action
- Add matrix builds for linux/amd64, linux/arm64, darwin/universal, windows/amd64
- Update README URLs from Snider/Core to host-uk/core
- Simplify artifact handling with merge-multiple
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs(mkdocs): update repo references to host-uk/core
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore(coderabbit): disable auto-review, manual trigger only
Trigger with @coderabbitai review to control costs.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(ci): implement semver release channels
- Rename dev-release.yml → alpha-release.yml
- Alpha builds: v0.0.4-alpha.{run_number} (prerelease)
- Add pr-build.yml for draft releases
- PR builds: v0.0.4-pr.{num}.bid.{id} (draft, not published)
- Add attestation permissions for SLSA compliance
- No more deleting/recreating dev tag
Versioning strategy:
- Draft: +pr.{NUM}.bid.{ID} (testable, not published)
- Alpha: -alpha.{N} (canary channel)
- Beta: -beta (quality scored)
- RC: -rc.{N} (release candidate)
- Stable: no suffix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(ci): use build@v3 and dot notation for versions
- Switch from host-uk/build@dev to host-uk/build@v3
- Use dots instead of + for build metadata (GitHub tag compatible)
- v0.0.4.pr.{num}.bid.{id} format for PR drafts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci(workflows): update all actions to latest versions
- actions/setup-go: v5 → v6 (Go 1.25+ support)
- actions/upload-artifact: v4 → v6 (immutable artifacts)
- actions/download-artifact: v4 → v7 (attestations support)
- actions/github-script: v7 → v8 (Node 20)
- actions/checkout: standardized on v6
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci: temporarily use self-hosted runners
Testing build on local runners while GitHub hosted runners are backed up.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci: fix webkit dep for Ubuntu 20.04 runners
Fall back to libwebkit2gtk-4.0-dev on older Ubuntu.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: skip unwritable dir test when running as root
Docker self-hosted runners run as root, which can write anywhere.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci: revert to ubuntu-latest runners
Self-hosted runners need environment parity work (ARM64, root user, SDK tools).
Keep self-hosted for future local-llm integration tasks.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
113 lines
4.8 KiB
YAML
113 lines
4.8 KiB
YAML
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues
|
|
name: "Auto Label: Issue Created/Edited"
|
|
|
|
on:
|
|
issues:
|
|
types: [opened, edited]
|
|
|
|
permissions:
|
|
issues: write
|
|
|
|
jobs:
|
|
label:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Auto-label based on content
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const issue = context.payload.issue;
|
|
const title = issue.title.toLowerCase();
|
|
const body = (issue.body || '').toLowerCase();
|
|
const content = title + ' ' + body;
|
|
|
|
const labelsToAdd = [];
|
|
|
|
// Type labels based on title prefix
|
|
if (title.includes('[bug]')) {
|
|
labelsToAdd.push('bug');
|
|
} else if (title.includes('[feature]') || title.includes('feat(') || title.includes('feat:')) {
|
|
labelsToAdd.push('enhancement');
|
|
} else if (title.includes('[docs]') || title.includes('docs(') || title.includes('docs:')) {
|
|
labelsToAdd.push('documentation');
|
|
}
|
|
|
|
// Project labels based on content
|
|
if (content.includes('core dev') || content.includes('core work') || content.includes('core commit') || content.includes('core push')) {
|
|
labelsToAdd.push('project:core-cli');
|
|
}
|
|
if (content.includes('core php') || content.includes('composer') || content.includes('pest') || content.includes('phpstan')) {
|
|
labelsToAdd.push('project:core-php');
|
|
}
|
|
|
|
// Language labels
|
|
if (content.includes('.go') || content.includes('golang') || content.includes('go mod')) {
|
|
labelsToAdd.push('go');
|
|
}
|
|
|
|
// Priority detection
|
|
if (content.includes('critical') || content.includes('urgent') || content.includes('breaking')) {
|
|
labelsToAdd.push('priority:high');
|
|
}
|
|
|
|
// Agent labels
|
|
if (content.includes('agent') || content.includes('ai ') || content.includes('claude') || content.includes('agentic')) {
|
|
labelsToAdd.push('agentic');
|
|
}
|
|
|
|
// Complexity - from template dropdown or heuristics
|
|
if (body.includes('small - quick fix')) {
|
|
labelsToAdd.push('complexity:small');
|
|
labelsToAdd.push('good first issue');
|
|
} else if (body.includes('medium - multiple files')) {
|
|
labelsToAdd.push('complexity:medium');
|
|
} else if (body.includes('large - significant')) {
|
|
labelsToAdd.push('complexity:large');
|
|
} else if (!body.includes('unknown - not sure')) {
|
|
// Heuristic complexity detection
|
|
const checklistCount = (body.match(/- \[ \]/g) || []).length;
|
|
const codeBlocks = (body.match(/```/g) || []).length / 2;
|
|
const sections = (body.match(/^##/gm) || []).length;
|
|
const fileRefs = (body.match(/\.(go|php|js|ts|yml|yaml|json|md)\b/g) || []).length;
|
|
|
|
const complexKeywords = ['refactor', 'rewrite', 'migration', 'breaking change', 'across repos', 'architecture'];
|
|
const simpleKeywords = ['simple', 'quick fix', 'typo', 'minor', 'trivial'];
|
|
|
|
const hasComplexKeyword = complexKeywords.some(k => content.includes(k));
|
|
const hasSimpleKeyword = simpleKeywords.some(k => content.includes(k));
|
|
|
|
let score = checklistCount * 2 + codeBlocks + sections + fileRefs;
|
|
score += hasComplexKeyword ? 5 : 0;
|
|
score -= hasSimpleKeyword ? 3 : 0;
|
|
|
|
if (hasSimpleKeyword || score <= 2) {
|
|
labelsToAdd.push('complexity:small');
|
|
labelsToAdd.push('good first issue');
|
|
} else if (score <= 6) {
|
|
labelsToAdd.push('complexity:medium');
|
|
} else {
|
|
labelsToAdd.push('complexity:large');
|
|
}
|
|
}
|
|
|
|
// Apply labels if any detected
|
|
if (labelsToAdd.length > 0) {
|
|
// Filter to only existing labels
|
|
const existingLabels = await github.rest.issues.listLabelsForRepo({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
per_page: 100
|
|
});
|
|
const validLabels = existingLabels.data.map(l => l.name);
|
|
const filteredLabels = labelsToAdd.filter(l => validLabels.includes(l));
|
|
|
|
if (filteredLabels.length > 0) {
|
|
await github.rest.issues.addLabels({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issue.number,
|
|
labels: filteredLabels
|
|
});
|
|
console.log(`Added labels: ${filteredLabels.join(', ')}`);
|
|
}
|
|
}
|