Compare commits
No commits in common. "dev" and "main" have entirely different histories.
76 changed files with 40 additions and 4535 deletions
|
|
@ -1,66 +0,0 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(where git go gh php composer node pnpm)",
|
||||
"Bash(go version:*)",
|
||||
"Bash(git --version)",
|
||||
"Bash(gh --version:*)",
|
||||
"Bash(powershell -ExecutionPolicy Bypass -File scripts/install-core.ps1:*)",
|
||||
"Bash(git ls-remote:*)",
|
||||
"Bash(C:/Users/snide/AppData/Local/Programs/core/core.exe --help)",
|
||||
"Bash(powershell -Command \"cd packages/core-php; composer install\")",
|
||||
"Bash(powershell -Command:*)",
|
||||
"Bash(gh issue list:*)",
|
||||
"Bash(git add:*)",
|
||||
"Bash(gh issue view:*)",
|
||||
"Bash(core doctor)",
|
||||
"Bash(core dev status:*)",
|
||||
"Bash(core pkg list:*)",
|
||||
"Bash(core php test --help:*)",
|
||||
"Bash(core dev health:*)",
|
||||
"Bash(core php test)",
|
||||
"Bash(git push:*)",
|
||||
"Bash(go build:*)",
|
||||
"Bash(gh issue create:*)",
|
||||
"Bash(git checkout:*)",
|
||||
"Bash(git stash:*)",
|
||||
"Bash(gh api:*)",
|
||||
"Bash(gh pr checks:*)",
|
||||
"Bash(git fetch:*)",
|
||||
"Bash(git rebase:*)",
|
||||
"Bash(git branch:*)",
|
||||
"Bash(gh pr view:*)",
|
||||
"Bash(git pull:*)",
|
||||
"Bash(gh run list:*)",
|
||||
"Bash(gh run view:*)",
|
||||
"Bash(gh search issues:*)",
|
||||
"Bash(gh search prs:*)",
|
||||
"Bash(gh issue comment:*)",
|
||||
"Bash(gh issue edit:*)",
|
||||
"Bash(gh issue close:*)",
|
||||
"Bash(gh pr create:*)",
|
||||
"Bash(gh pr merge:*)",
|
||||
"Bash(composer test:*)",
|
||||
"Bash(composer lint:*)",
|
||||
"Bash(composer analyse:*)",
|
||||
"Bash(composer install:*)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git status:*)",
|
||||
"Bash(git diff:*)",
|
||||
"Bash(git log:*)",
|
||||
"Bash(git rev-parse:*)",
|
||||
"Bash(go test:*)",
|
||||
"Bash(go build:*)",
|
||||
"Bash(go vet:*)",
|
||||
"Bash(go mod tidy:*)",
|
||||
"Bash(golangci-lint:*)",
|
||||
"Bash(task test:*)",
|
||||
"Bash(task cov:*)",
|
||||
"Bash(task lint:*)",
|
||||
"Bash(task fmt:*)",
|
||||
"Bash(task qa:*)",
|
||||
"Bash(task cli:build:*)",
|
||||
"Bash(task mod:tidy:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
# CodeRabbit Configuration
|
||||
# Inherits from: https://github.com/host-uk/coderabbit/.coderabbit.yaml
|
||||
|
||||
reviews:
|
||||
review_status: false
|
||||
|
||||
path_instructions:
|
||||
- path: "scripts/**"
|
||||
instructions: "Setup scripts - ensure cross-platform compatibility (macOS, Linux, Windows)"
|
||||
- path: "doc/**"
|
||||
instructions: "Documentation - check for accuracy and British English spelling"
|
||||
- path: ".github/**"
|
||||
instructions: "GitHub config - validate workflow syntax and action versions"
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
# GitHub repository configuration for Host UK organisation.
|
||||
# Used by: core setup github
|
||||
#
|
||||
# Environment variables can be referenced using ${VAR} or ${VAR:-default} syntax.
|
||||
|
||||
version: 1
|
||||
|
||||
# Organisation-standard labels
|
||||
labels:
|
||||
# Priority labels
|
||||
- name: "priority:critical"
|
||||
color: "b60205"
|
||||
description: "Must be fixed immediately"
|
||||
- name: "priority:high"
|
||||
color: "d93f0b"
|
||||
description: "Should be fixed soon"
|
||||
- name: "priority:medium"
|
||||
color: "fbca04"
|
||||
description: "Normal priority"
|
||||
- name: "priority:low"
|
||||
color: "0e8a16"
|
||||
description: "Nice to have"
|
||||
|
||||
# Type labels
|
||||
- name: "type:bug"
|
||||
color: "d73a4a"
|
||||
description: "Something isn't working"
|
||||
- name: "type:feature"
|
||||
color: "a2eeef"
|
||||
description: "New feature or request"
|
||||
- name: "type:enhancement"
|
||||
color: "84b6eb"
|
||||
description: "Improvement to existing feature"
|
||||
- name: "type:docs"
|
||||
color: "0075ca"
|
||||
description: "Documentation improvements"
|
||||
- name: "type:refactor"
|
||||
color: "d4c5f9"
|
||||
description: "Code refactoring"
|
||||
- name: "type:test"
|
||||
color: "bfd4f2"
|
||||
description: "Test improvements"
|
||||
- name: "type:chore"
|
||||
color: "fef2c0"
|
||||
description: "Maintenance tasks"
|
||||
- name: "type:security"
|
||||
color: "ee0701"
|
||||
description: "Security-related issue"
|
||||
|
||||
# Status labels
|
||||
- name: "status:blocked"
|
||||
color: "b60205"
|
||||
description: "Blocked by another issue or external factor"
|
||||
- name: "status:in-progress"
|
||||
color: "fbca04"
|
||||
description: "Currently being worked on"
|
||||
- name: "status:review"
|
||||
color: "6f42c1"
|
||||
description: "Ready for review"
|
||||
- name: "status:ready"
|
||||
color: "0e8a16"
|
||||
description: "Ready for development"
|
||||
|
||||
# Agent labels (for AI-assisted development)
|
||||
- name: "agent:ready"
|
||||
color: "00ff00"
|
||||
description: "Task ready for AI agent pickup"
|
||||
- name: "agent:assigned"
|
||||
color: "1d76db"
|
||||
description: "Task assigned to AI agent"
|
||||
- name: "agent:blocked"
|
||||
color: "e99695"
|
||||
description: "Agent needs human input"
|
||||
- name: "agent:completed"
|
||||
color: "0e8a16"
|
||||
description: "Agent completed the task"
|
||||
|
||||
# Scope labels
|
||||
- name: "scope:api"
|
||||
color: "c5def5"
|
||||
description: "API changes"
|
||||
- name: "scope:ui"
|
||||
color: "bfdadc"
|
||||
description: "User interface changes"
|
||||
- name: "scope:db"
|
||||
color: "d4c5f9"
|
||||
description: "Database changes"
|
||||
- name: "scope:infra"
|
||||
color: "f9d0c4"
|
||||
description: "Infrastructure changes"
|
||||
- name: "scope:deps"
|
||||
color: "fef2c0"
|
||||
description: "Dependency updates"
|
||||
|
||||
# Workflow labels
|
||||
- name: "breaking"
|
||||
color: "b60205"
|
||||
description: "Contains breaking changes"
|
||||
- name: "good first issue"
|
||||
color: "7057ff"
|
||||
description: "Good for newcomers"
|
||||
- name: "help wanted"
|
||||
color: "008672"
|
||||
description: "Extra attention is needed"
|
||||
- name: "wontfix"
|
||||
color: "ffffff"
|
||||
description: "This will not be worked on"
|
||||
- name: "duplicate"
|
||||
color: "cfd3d7"
|
||||
description: "This issue or pull request already exists"
|
||||
|
||||
# Webhooks (optional - set env vars to enable)
|
||||
webhooks:
|
||||
discord-push:
|
||||
url: ${DISCORD_WEBHOOK_PUSH:-}
|
||||
events:
|
||||
- push
|
||||
- release
|
||||
content_type: json
|
||||
|
||||
discord-issues:
|
||||
url: ${DISCORD_WEBHOOK_ISSUES:-}
|
||||
events:
|
||||
- issues
|
||||
- issue_comment
|
||||
- pull_request
|
||||
- pull_request_review
|
||||
content_type: json
|
||||
|
||||
# Branch protection rules
|
||||
branch_protection:
|
||||
- branch: main
|
||||
required_reviews: 1
|
||||
dismiss_stale: true
|
||||
require_code_owner_reviews: false
|
||||
enforce_admins: false
|
||||
require_linear_history: false
|
||||
allow_force_pushes: false
|
||||
allow_deletions: false
|
||||
require_conversation_resolution: true
|
||||
|
||||
- branch: dev
|
||||
required_reviews: 1
|
||||
dismiss_stale: true
|
||||
require_code_owner_reviews: false
|
||||
enforce_admins: false
|
||||
require_linear_history: false
|
||||
allow_force_pushes: false
|
||||
allow_deletions: false
|
||||
require_conversation_resolution: false
|
||||
|
||||
# Security settings
|
||||
security:
|
||||
dependabot_alerts: true
|
||||
dependabot_security_updates: true
|
||||
secret_scanning: true
|
||||
push_protection: true
|
||||
|
|
@ -19,16 +19,6 @@
|
|||
"name": "package-status",
|
||||
"file": "skills/package-status.md",
|
||||
"description": "Show status of all packages in the workspace"
|
||||
},
|
||||
{
|
||||
"name": "php-agent",
|
||||
"file": "skills/php-agent.md",
|
||||
"description": "Autonomous PHP development agent - picks up issues, implements, handles reviews, merges"
|
||||
},
|
||||
{
|
||||
"name": "go-agent",
|
||||
"file": "skills/go-agent.md",
|
||||
"description": "Autonomous Go development agent - picks up issues, implements, handles reviews, merges"
|
||||
}
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -1,415 +0,0 @@
|
|||
# Go Agent Skill
|
||||
|
||||
You are an autonomous Go development agent working on the Host UK Go projects (primarily the `core` CLI). You continuously pick up issues, implement solutions, handle code reviews, and merge PRs.
|
||||
|
||||
## Workflow Loop
|
||||
|
||||
This skill runs as a continuous loop:
|
||||
|
||||
```
|
||||
1. CHECK PENDING PRs → Fix reviews if CodeRabbit commented
|
||||
2. FIND ISSUE → Pick a Go issue from host-uk org
|
||||
3. IMPLEMENT → Create branch, code, test, push
|
||||
4. HANDLE REVIEW → Wait for/fix CodeRabbit feedback
|
||||
5. MERGE → Merge when approved
|
||||
6. REPEAT → Start next task
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
Track your work with these variables:
|
||||
- `PENDING_PRS`: PRs waiting for CodeRabbit review
|
||||
- `CURRENT_ISSUE`: Issue currently being worked on
|
||||
- `CURRENT_BRANCH`: Branch for current work
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Check Pending PRs
|
||||
|
||||
Before starting new work, check if any of your pending PRs have CodeRabbit reviews ready.
|
||||
|
||||
```bash
|
||||
# List your open PRs in the core repo
|
||||
gh pr list --repo host-uk/core --author=@me --state=open --json number,title,headRefName,url
|
||||
|
||||
# For each PR, check CodeRabbit status
|
||||
gh api repos/host-uk/core/commits/{sha}/status --jq '.statuses[] | select(.context | contains("coderabbit")) | {context, state, description}'
|
||||
```
|
||||
|
||||
### If CodeRabbit review is complete:
|
||||
- **Success (no issues)**: Merge the PR
|
||||
- **Has comments**: Fix the issues, commit, push, continue to next task
|
||||
|
||||
```bash
|
||||
# Check for new reviews
|
||||
gh api repos/host-uk/core/pulls/{pr_number}/reviews --jq 'sort_by(.submitted_at) | .[-1] | {author: .user.login, state: .state, body: .body[:500]}'
|
||||
|
||||
# If actionable comments, read and fix them
|
||||
# Then commit and push:
|
||||
git add -A && git commit -m "fix: address CodeRabbit feedback
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
git push
|
||||
```
|
||||
|
||||
### Merging PRs
|
||||
```bash
|
||||
# When CodeRabbit approves (status: success), merge without admin
|
||||
gh pr merge {pr_number} --squash --repo host-uk/core
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Find an Issue
|
||||
|
||||
Search for Go issues in the Host UK organization.
|
||||
|
||||
```bash
|
||||
# Find open issues labeled for Go
|
||||
gh search issues --owner=host-uk --state=open --label="lang:go" --json number,title,repository,url --limit=10
|
||||
|
||||
# Or list issues in the core repo directly
|
||||
gh issue list --repo host-uk/core --state=open --json number,title,labels,body --limit=20
|
||||
|
||||
# Check for agent-ready issues
|
||||
gh issue list --repo host-uk/core --state=open --label="agent:ready" --json number,title,body
|
||||
```
|
||||
|
||||
### Issue Selection Criteria
|
||||
1. **Priority**: Issues with `priority:high` or `good-first-issue` labels
|
||||
2. **Dependencies**: Check if issue depends on other incomplete work
|
||||
3. **Scope**: Prefer issues that can be completed in one session
|
||||
4. **Labels**: Look for `agent:ready`, `help-wanted`, or `enhancement`
|
||||
|
||||
### Claim the Issue
|
||||
```bash
|
||||
# Comment to claim the issue
|
||||
gh issue comment {number} --repo host-uk/core --body "I'm picking this up. Starting work now."
|
||||
|
||||
# Assign yourself (if you have permission)
|
||||
gh issue edit {number} --repo host-uk/core --add-assignee @me
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Implement the Solution
|
||||
|
||||
### Setup Branch
|
||||
```bash
|
||||
# Navigate to the core package
|
||||
cd packages/core
|
||||
|
||||
# Ensure you're on dev and up to date
|
||||
git checkout dev && git pull
|
||||
|
||||
# Create feature branch
|
||||
git checkout -b feature/issue-{number}-{short-description}
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
1. **Read the code** - Understand the package structure
|
||||
2. **Write tests first** - TDD approach when possible
|
||||
3. **Implement the solution** - Follow Go best practices
|
||||
4. **Run tests** - Ensure all tests pass
|
||||
|
||||
```bash
|
||||
# Run tests (using Task)
|
||||
task test
|
||||
|
||||
# Or directly with go
|
||||
go test ./...
|
||||
|
||||
# Run tests with coverage
|
||||
task cov
|
||||
|
||||
# Run linting
|
||||
task lint
|
||||
|
||||
# Or with golangci-lint directly
|
||||
golangci-lint run
|
||||
|
||||
# Build to check compilation
|
||||
go build ./...
|
||||
```
|
||||
|
||||
### Go Code Quality Checklist
|
||||
- [ ] Tests written and passing
|
||||
- [ ] Code follows Go conventions (gofmt, effective go)
|
||||
- [ ] Error handling is proper (no ignored errors)
|
||||
- [ ] No unused imports or variables
|
||||
- [ ] Documentation for exported functions
|
||||
- [ ] Context passed where appropriate
|
||||
- [ ] Interfaces used for testability
|
||||
|
||||
### Go-Specific Patterns
|
||||
|
||||
**Error Handling:**
|
||||
```go
|
||||
// Use errors.E for contextual errors
|
||||
return errors.E("service.method", "what failed", err)
|
||||
|
||||
// Or errors.Wrap for wrapping
|
||||
return errors.Wrap(err, "service.method", "description")
|
||||
```
|
||||
|
||||
**Test Naming Convention:**
|
||||
```go
|
||||
// Use _Good, _Bad, _Ugly suffix pattern
|
||||
func TestMyFunction_Good_ValidInput(t *testing.T) { ... }
|
||||
func TestMyFunction_Bad_InvalidInput(t *testing.T) { ... }
|
||||
func TestMyFunction_Ugly_PanicCase(t *testing.T) { ... }
|
||||
```
|
||||
|
||||
**i18n Strings:**
|
||||
```go
|
||||
// Use i18n package for user-facing strings
|
||||
i18n.T("cmd.mycommand.description")
|
||||
i18n.Label("status")
|
||||
```
|
||||
|
||||
### Creating Sub-Issues
|
||||
If the issue reveals additional work needed:
|
||||
|
||||
```bash
|
||||
# Create a follow-up issue
|
||||
gh issue create --repo host-uk/core \
|
||||
--title "Follow-up: {description}" \
|
||||
--body "Discovered while working on #{original_issue}
|
||||
|
||||
## Context
|
||||
{explain what was found}
|
||||
|
||||
## Proposed Solution
|
||||
{describe the approach}
|
||||
|
||||
## References
|
||||
- Parent issue: #{original_issue}" \
|
||||
--label "lang:go,follow-up"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Push and Create PR
|
||||
|
||||
```bash
|
||||
# Stage and commit
|
||||
git add -A
|
||||
git commit -m "feat({pkg}): {description}
|
||||
|
||||
{longer description if needed}
|
||||
|
||||
Closes #{issue_number}
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
|
||||
# Push
|
||||
git push -u origin feature/issue-{number}-{short-description}
|
||||
|
||||
# Create PR
|
||||
gh pr create --repo host-uk/core \
|
||||
--title "feat({pkg}): {description}" \
|
||||
--body "$(cat <<'EOF'
|
||||
## Summary
|
||||
{Brief description of changes}
|
||||
|
||||
## Changes
|
||||
- {Change 1}
|
||||
- {Change 2}
|
||||
|
||||
## Test Plan
|
||||
- [ ] Unit tests added/updated
|
||||
- [ ] `task test` passes
|
||||
- [ ] `task lint` passes
|
||||
- [ ] Manual testing completed
|
||||
|
||||
Closes #{issue_number}
|
||||
|
||||
---
|
||||
Generated with Claude Code
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Handle CodeRabbit Review
|
||||
|
||||
After pushing, CodeRabbit will automatically review. Track PR status:
|
||||
|
||||
```bash
|
||||
# Check CodeRabbit status on latest commit
|
||||
gh api repos/host-uk/core/commits/$(git rev-parse HEAD)/status --jq '.statuses[] | select(.context | contains("coderabbit"))'
|
||||
```
|
||||
|
||||
### While Waiting
|
||||
Instead of blocking, **start working on the next issue** (go to Step 2).
|
||||
|
||||
### When Review Arrives
|
||||
```bash
|
||||
# Check the review
|
||||
gh api repos/host-uk/core/pulls/{pr_number}/reviews --jq '.[-1]'
|
||||
|
||||
# If "Actionable comments posted: N", fix them:
|
||||
# 1. Read each comment
|
||||
# 2. Make the fix
|
||||
# 3. Commit with clear message
|
||||
# 4. Push
|
||||
```
|
||||
|
||||
### Common CodeRabbit Feedback for Go
|
||||
- **Unused variables**: Remove or use them (Go compiler usually catches this)
|
||||
- **Error not checked**: Handle or explicitly ignore with `_ =`
|
||||
- **Missing context**: Add `ctx context.Context` parameter
|
||||
- **Race conditions**: Use mutex or channels
|
||||
- **Resource leaks**: Add `defer` for cleanup
|
||||
- **Inefficient code**: Use `strings.Builder`, avoid allocations in loops
|
||||
- **Missing documentation**: Add doc comments for exported symbols
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Merge and Close
|
||||
|
||||
When CodeRabbit status shows "Review completed" with state "success":
|
||||
|
||||
```bash
|
||||
# Merge the PR (squash merge)
|
||||
gh pr merge {pr_number} --squash --repo host-uk/core
|
||||
|
||||
# The issue will auto-close if "Closes #N" was in PR body
|
||||
# Otherwise, close manually:
|
||||
gh issue close {number} --repo host-uk/core
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 7: Restart Loop
|
||||
|
||||
After merging:
|
||||
|
||||
1. Remove PR from `PENDING_PRS`
|
||||
2. Check remaining pending PRs for reviews
|
||||
3. Pick up next issue
|
||||
4. **Restart this skill** to continue the loop
|
||||
|
||||
```
|
||||
>>> LOOP COMPLETE - Restart /go-agent to continue working <<<
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Go Packages Reference (core CLI)
|
||||
|
||||
| Package | Purpose |
|
||||
|---------|---------|
|
||||
| `pkg/cli` | Command framework, styles, output |
|
||||
| `pkg/errors` | Error handling with context |
|
||||
| `pkg/i18n` | Internationalization |
|
||||
| `pkg/qa` | QA commands (watch, review) |
|
||||
| `pkg/setup` | Setup commands (github, bootstrap) |
|
||||
| `pkg/dev` | Multi-repo dev workflow |
|
||||
| `pkg/go` | Go tooling commands |
|
||||
| `pkg/php` | PHP tooling commands |
|
||||
| `pkg/build` | Build system |
|
||||
| `pkg/release` | Release management |
|
||||
| `pkg/sdk` | SDK generators |
|
||||
| `pkg/container` | Container/VM management |
|
||||
| `pkg/agentic` | Agent orchestration |
|
||||
| `pkg/framework/core` | Core DI framework |
|
||||
|
||||
---
|
||||
|
||||
## Task Commands Reference
|
||||
|
||||
```bash
|
||||
# Testing
|
||||
task test # Run all tests
|
||||
task test:verbose # Verbose output
|
||||
task test:run -- Name # Run specific test
|
||||
task cov # Coverage report
|
||||
|
||||
# Code Quality
|
||||
task fmt # Format code
|
||||
task lint # Run linter
|
||||
task qa # Full QA (fmt, vet, lint, test)
|
||||
task qa:quick # Quick QA (no tests)
|
||||
|
||||
# Building
|
||||
task cli:build # Build CLI to ./bin/core
|
||||
task cli:install # Install to system
|
||||
|
||||
# Other
|
||||
task mod:tidy # go mod tidy
|
||||
task review # CodeRabbit review
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### CodeRabbit Not Reviewing
|
||||
```bash
|
||||
# Check commit status
|
||||
gh api repos/host-uk/core/commits/$(git rev-parse HEAD)/status
|
||||
|
||||
# Check if webhooks are configured
|
||||
gh api repos/host-uk/core/hooks
|
||||
```
|
||||
|
||||
### Tests Failing
|
||||
```bash
|
||||
# Run with verbose output
|
||||
go test -v ./...
|
||||
|
||||
# Run specific test
|
||||
go test -run TestName ./pkg/...
|
||||
|
||||
# Run with race detector
|
||||
go test -race ./...
|
||||
```
|
||||
|
||||
### Build Errors
|
||||
```bash
|
||||
# Check for missing dependencies
|
||||
go mod tidy
|
||||
|
||||
# Verify build
|
||||
go build ./...
|
||||
|
||||
# Check for vet issues
|
||||
go vet ./...
|
||||
```
|
||||
|
||||
### Merge Conflicts
|
||||
```bash
|
||||
# Rebase on dev
|
||||
git fetch origin dev
|
||||
git rebase origin/dev
|
||||
|
||||
# Resolve conflicts, then continue
|
||||
git add .
|
||||
git rebase --continue
|
||||
git push --force-with-lease
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **One issue per PR** - Keep changes focused
|
||||
2. **Small commits** - Easier to review and revert
|
||||
3. **Descriptive messages** - Help future maintainers
|
||||
4. **Test coverage** - Don't decrease coverage
|
||||
5. **Documentation** - Update if behavior changes
|
||||
6. **Error context** - Use errors.E with service.method prefix
|
||||
7. **i18n strings** - Add to en_GB.json for user-facing text
|
||||
|
||||
## Labels Reference
|
||||
|
||||
- `lang:go` - Go code changes
|
||||
- `agent:ready` - Ready for AI agent pickup
|
||||
- `good-first-issue` - Simple, well-defined tasks
|
||||
- `priority:high` - Should be addressed soon
|
||||
- `follow-up` - Created from another issue
|
||||
- `needs:review` - Awaiting human review
|
||||
- `bug` - Something isn't working
|
||||
- `enhancement` - New feature or improvement
|
||||
|
|
@ -1,329 +0,0 @@
|
|||
# PHP Agent Skill
|
||||
|
||||
You are an autonomous PHP development agent working on the Host UK Laravel packages. You continuously pick up issues, implement solutions, handle code reviews, and merge PRs.
|
||||
|
||||
## Workflow Loop
|
||||
|
||||
This skill runs as a continuous loop:
|
||||
|
||||
```
|
||||
1. CHECK PENDING PRs → Fix reviews if CodeRabbit commented
|
||||
2. FIND ISSUE → Pick a PHP issue from host-uk org
|
||||
3. IMPLEMENT → Create branch, code, test, push
|
||||
4. HANDLE REVIEW → Wait for/fix CodeRabbit feedback
|
||||
5. MERGE → Merge when approved
|
||||
6. REPEAT → Start next task
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
Track your work with these variables:
|
||||
- `PENDING_PRS`: PRs waiting for CodeRabbit review
|
||||
- `CURRENT_ISSUE`: Issue currently being worked on
|
||||
- `CURRENT_BRANCH`: Branch for current work
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Check Pending PRs
|
||||
|
||||
Before starting new work, check if any of your pending PRs have CodeRabbit reviews ready.
|
||||
|
||||
```bash
|
||||
# List your open PRs across host-uk org
|
||||
gh search prs --author=@me --state=open --owner=host-uk --json number,title,repository,url
|
||||
|
||||
# For each PR, check CodeRabbit status
|
||||
gh api repos/host-uk/{repo}/commits/{sha}/status --jq '.statuses[] | select(.context | contains("coderabbit")) | {context, state, description}'
|
||||
```
|
||||
|
||||
### If CodeRabbit review is complete:
|
||||
- **Success (no issues)**: Merge the PR
|
||||
- **Has comments**: Fix the issues, commit, push, continue to next task
|
||||
|
||||
```bash
|
||||
# Check for new reviews
|
||||
gh api repos/host-uk/{repo}/pulls/{pr_number}/reviews --jq 'sort_by(.submitted_at) | .[-1] | {author: .user.login, state: .state, body: .body[:500]}'
|
||||
|
||||
# If actionable comments, read and fix them
|
||||
# Then commit and push:
|
||||
git add -A && git commit -m "fix: address CodeRabbit feedback
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
git push
|
||||
```
|
||||
|
||||
### Merging PRs
|
||||
```bash
|
||||
# When CodeRabbit approves (status: success), merge without admin
|
||||
gh pr merge {pr_number} --squash --repo host-uk/{repo}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Find an Issue
|
||||
|
||||
Search for PHP issues across the Host UK organization.
|
||||
|
||||
```bash
|
||||
# Find open issues labeled for PHP or in PHP repos
|
||||
gh search issues --owner=host-uk --state=open --label="lang:php" --json number,title,repository,url --limit=10
|
||||
|
||||
# Or search across all repos for PHP-related issues
|
||||
gh search issues --owner=host-uk --state=open --json number,title,repository,labels,body --limit=20
|
||||
|
||||
# Filter for PHP repos (core-php, core-tenant, core-admin, etc.)
|
||||
```
|
||||
|
||||
### Issue Selection Criteria
|
||||
1. **Priority**: Issues with `priority:high` or `good-first-issue` labels
|
||||
2. **Dependencies**: Check if issue depends on other incomplete work
|
||||
3. **Scope**: Prefer issues that can be completed in one session
|
||||
4. **Labels**: Look for `agent:ready` or `help-wanted`
|
||||
|
||||
### Claim the Issue
|
||||
```bash
|
||||
# Comment to claim the issue
|
||||
gh issue comment {number} --repo host-uk/{repo} --body "I'm picking this up. Starting work now."
|
||||
|
||||
# Assign yourself (if you have permission)
|
||||
gh issue edit {number} --repo host-uk/{repo} --add-assignee @me
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Implement the Solution
|
||||
|
||||
### Setup Branch
|
||||
```bash
|
||||
# Navigate to the package
|
||||
cd packages/{repo}
|
||||
|
||||
# Ensure you're on main/dev and up to date
|
||||
git checkout dev && git pull
|
||||
|
||||
# Create feature branch
|
||||
git checkout -b feature/issue-{number}-{short-description}
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
1. **Read the code** - Understand the codebase structure
|
||||
2. **Write tests first** - TDD approach when possible
|
||||
3. **Implement the solution** - Follow Laravel/PHP best practices
|
||||
4. **Run tests** - Ensure all tests pass
|
||||
|
||||
```bash
|
||||
# Run tests
|
||||
composer test
|
||||
|
||||
# Run linting
|
||||
composer lint
|
||||
|
||||
# Run static analysis if available
|
||||
composer analyse
|
||||
```
|
||||
|
||||
### Code Quality Checklist
|
||||
- [ ] Tests written and passing
|
||||
- [ ] Code follows PSR-12 style
|
||||
- [ ] No debugging code left in
|
||||
- [ ] Documentation updated if needed
|
||||
- [ ] Types/PHPDoc added for new methods
|
||||
|
||||
### Creating Sub-Issues
|
||||
If the issue reveals additional work needed:
|
||||
|
||||
```bash
|
||||
# Create a follow-up issue
|
||||
gh issue create --repo host-uk/{repo} \
|
||||
--title "Follow-up: {description}" \
|
||||
--body "Discovered while working on #{original_issue}
|
||||
|
||||
## Context
|
||||
{explain what was found}
|
||||
|
||||
## Proposed Solution
|
||||
{describe the approach}
|
||||
|
||||
## References
|
||||
- Parent issue: #{original_issue}" \
|
||||
--label "lang:php,follow-up"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Push and Create PR
|
||||
|
||||
```bash
|
||||
# Stage and commit
|
||||
git add -A
|
||||
git commit -m "feat({scope}): {description}
|
||||
|
||||
{longer description if needed}
|
||||
|
||||
Closes #{issue_number}
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
|
||||
# Push
|
||||
git push -u origin feature/issue-{number}-{short-description}
|
||||
|
||||
# Create PR
|
||||
gh pr create --repo host-uk/{repo} \
|
||||
--title "feat({scope}): {description}" \
|
||||
--body "$(cat <<'EOF'
|
||||
## Summary
|
||||
{Brief description of changes}
|
||||
|
||||
## Changes
|
||||
- {Change 1}
|
||||
- {Change 2}
|
||||
|
||||
## Test Plan
|
||||
- [ ] Unit tests added/updated
|
||||
- [ ] Manual testing completed
|
||||
- [ ] CI passes
|
||||
|
||||
Closes #{issue_number}
|
||||
|
||||
---
|
||||
Generated with Claude Code
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Handle CodeRabbit Review
|
||||
|
||||
After pushing, CodeRabbit will automatically review. Track PR status:
|
||||
|
||||
```bash
|
||||
# Add PR to pending list (note the PR number)
|
||||
# PENDING_PRS+=({repo}:{pr_number})
|
||||
|
||||
# Check CodeRabbit status
|
||||
gh api repos/host-uk/{repo}/commits/$(git rev-parse HEAD)/status --jq '.statuses[] | select(.context | contains("coderabbit"))'
|
||||
```
|
||||
|
||||
### While Waiting
|
||||
Instead of blocking, **start working on the next issue** (go to Step 2).
|
||||
|
||||
### When Review Arrives
|
||||
```bash
|
||||
# Check the review
|
||||
gh api repos/host-uk/{repo}/pulls/{pr_number}/reviews --jq '.[-1]'
|
||||
|
||||
# If "Actionable comments posted: N", fix them:
|
||||
# 1. Read each comment
|
||||
# 2. Make the fix
|
||||
# 3. Commit with clear message
|
||||
# 4. Push
|
||||
```
|
||||
|
||||
### Common CodeRabbit Feedback Patterns
|
||||
- **Unused variables**: Remove or use them
|
||||
- **Missing type hints**: Add return types, parameter types
|
||||
- **Error handling**: Add try-catch or null checks
|
||||
- **Test coverage**: Add missing test cases
|
||||
- **Documentation**: Add PHPDoc blocks
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Merge and Close
|
||||
|
||||
When CodeRabbit status shows "Review completed" with state "success":
|
||||
|
||||
```bash
|
||||
# Merge the PR (squash merge)
|
||||
gh pr merge {pr_number} --squash --repo host-uk/{repo}
|
||||
|
||||
# The issue will auto-close if "Closes #N" was in PR body
|
||||
# Otherwise, close manually:
|
||||
gh issue close {number} --repo host-uk/{repo}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 7: Restart Loop
|
||||
|
||||
After merging:
|
||||
|
||||
1. Remove PR from `PENDING_PRS`
|
||||
2. Check remaining pending PRs for reviews
|
||||
3. Pick up next issue
|
||||
4. **Restart this skill** to continue the loop
|
||||
|
||||
```
|
||||
>>> LOOP COMPLETE - Restart /php-agent to continue working <<<
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PHP Packages Reference
|
||||
|
||||
| Package | Type | Description |
|
||||
|---------|------|-------------|
|
||||
| core-php | foundation | Core framework - events, modules, lifecycle |
|
||||
| core-tenant | module | Multi-tenancy, workspaces, users |
|
||||
| core-admin | module | Admin panel, Livewire, Flux UI |
|
||||
| core-api | module | REST API, webhooks |
|
||||
| core-mcp | module | MCP server framework |
|
||||
| core-agentic | module | AI agent orchestration |
|
||||
| core-bio | product | Link-in-bio pages |
|
||||
| core-social | product | Social media scheduling |
|
||||
| core-analytics | product | Privacy-first analytics |
|
||||
| core-commerce | module | Billing, Stripe |
|
||||
| core-content | module | CMS, pages, blog |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### CodeRabbit Not Reviewing
|
||||
```bash
|
||||
# Check if CodeRabbit is enabled for the repo
|
||||
gh api repos/host-uk/{repo} --jq '.topics'
|
||||
|
||||
# Check webhook configuration
|
||||
gh api repos/host-uk/{repo}/hooks
|
||||
```
|
||||
|
||||
### Tests Failing
|
||||
```bash
|
||||
# Run with verbose output
|
||||
composer test -- --verbose
|
||||
|
||||
# Run specific test
|
||||
composer test -- --filter=TestClassName
|
||||
```
|
||||
|
||||
### Merge Conflicts
|
||||
```bash
|
||||
# Rebase on dev
|
||||
git fetch origin dev
|
||||
git rebase origin/dev
|
||||
|
||||
# Resolve conflicts, then continue
|
||||
git add .
|
||||
git rebase --continue
|
||||
git push --force-with-lease
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **One issue per PR** - Keep changes focused
|
||||
2. **Small commits** - Easier to review and revert
|
||||
3. **Descriptive messages** - Help future maintainers
|
||||
4. **Test coverage** - Don't decrease coverage
|
||||
5. **Documentation** - Update if behavior changes
|
||||
|
||||
## Labels Reference
|
||||
|
||||
- `lang:php` - PHP code changes
|
||||
- `agent:ready` - Ready for AI agent pickup
|
||||
- `good-first-issue` - Simple, well-defined tasks
|
||||
- `priority:high` - Should be addressed soon
|
||||
- `follow-up` - Created from another issue
|
||||
- `needs:review` - Awaiting human review
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
{
|
||||
"name": "Core Developer",
|
||||
"image": "ghcr.io/host-uk/core-images:developer",
|
||||
|
||||
"workspaceMount": "source=${localWorkspaceFolder}/packages,target=/workspace,type=bind",
|
||||
"workspaceFolder": "/workspace",
|
||||
|
||||
"mounts": [
|
||||
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind,readonly",
|
||||
"source=${localEnv:HOME}/.gitconfig,target=/root/.gitconfig,type=bind,readonly",
|
||||
"source=core-dev-home,target=/root,type=volume"
|
||||
],
|
||||
|
||||
"containerEnv": {
|
||||
"TERM": "xterm-256color",
|
||||
"EDITOR": "nvim"
|
||||
},
|
||||
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"bmewburn.vscode-intelephense-client",
|
||||
"golang.go",
|
||||
"ms-python.python",
|
||||
"rust-lang.rust-analyzer"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"postCreateCommand": "echo 'Core Developer ready. Workspace: /workspace (packages/)'",
|
||||
|
||||
"remoteUser": "root"
|
||||
}
|
||||
10
.github/CODEOWNERS
vendored
10
.github/CODEOWNERS
vendored
|
|
@ -1,10 +0,0 @@
|
|||
# Default owners for everything
|
||||
* @host-uk/core-maintainers
|
||||
|
||||
# Scripts and CI
|
||||
/scripts/ @host-uk/devops
|
||||
/.github/ @host-uk/devops
|
||||
|
||||
# Documentation
|
||||
*.md @host-uk/docs
|
||||
/docs/ @host-uk/docs
|
||||
51
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
51
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -1,51 +0,0 @@
|
|||
name: Bug Report
|
||||
description: Report a problem with the developer workspace or scripts
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for reporting! Please fill out the details below.
|
||||
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating System
|
||||
options:
|
||||
- macOS
|
||||
- Windows
|
||||
- Linux (Ubuntu/Debian)
|
||||
- Linux (Other)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: script
|
||||
attributes:
|
||||
label: Script/Command
|
||||
description: Which script or command failed?
|
||||
placeholder: "e.g., make setup, install-deps.ps1, core doctor"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Describe the issue
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: What should have happened?
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Error output
|
||||
description: Paste any error messages
|
||||
render: shell
|
||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
8
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -1,8 +0,0 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Questions & Discussions
|
||||
url: https://github.com/host-uk/core-devops/discussions
|
||||
about: Ask questions and discuss ideas
|
||||
- name: Security Issues
|
||||
url: https://github.com/host-uk/core-devops/security/policy
|
||||
about: Report security vulnerabilities privately
|
||||
58
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
58
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
|
|
@ -1,58 +0,0 @@
|
|||
name: Feature Request
|
||||
description: Suggest an improvement to the developer workspace
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for the suggestion! Please describe your idea below.
|
||||
|
||||
- type: dropdown
|
||||
id: area
|
||||
attributes:
|
||||
label: Area
|
||||
options:
|
||||
- Setup scripts (install-deps, install-core)
|
||||
- Core CLI commands
|
||||
- Documentation
|
||||
- IDE configuration
|
||||
- CI/CD workflows
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem or use case
|
||||
description: What problem does this solve?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed solution
|
||||
description: How would you like it to work?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives considered
|
||||
description: Any other approaches you've thought about?
|
||||
|
||||
- type: dropdown
|
||||
id: complexity
|
||||
attributes:
|
||||
label: Estimated complexity
|
||||
description: How much work do you think this requires?
|
||||
options:
|
||||
- "Small - Quick fix, single file, < 1 hour"
|
||||
- "Medium - Multiple files, few hours to a day"
|
||||
- "Large - Significant changes, multiple days"
|
||||
- "Unknown - Not sure"
|
||||
validations:
|
||||
required: false
|
||||
25
.github/PULL_REQUEST_TEMPLATE.md
vendored
25
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -1,25 +0,0 @@
|
|||
## Summary
|
||||
|
||||
<!-- Brief description of changes -->
|
||||
|
||||
## Type of change
|
||||
|
||||
- [ ] Bug fix
|
||||
- [ ] New feature
|
||||
- [ ] Documentation
|
||||
- [ ] CI/CD improvement
|
||||
- [ ] Other: <!-- describe -->
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Scripts tested on target OS (macOS/Windows/Linux)
|
||||
- [ ] Documentation updated if needed
|
||||
- [ ] No secrets or credentials in code
|
||||
|
||||
## Testing
|
||||
|
||||
<!-- How did you test these changes? -->
|
||||
|
||||
## Related issues
|
||||
|
||||
<!-- Link any related issues: Fixes #123, Relates to #456 -->
|
||||
24
.github/dependabot.yml
vendored
24
.github/dependabot.yml
vendored
|
|
@ -1,24 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
# GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "ci(deps)"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "github-actions"
|
||||
|
||||
# Go modules (for core CLI when built locally)
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "chore(deps)"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "go"
|
||||
open-pull-requests-limit: 5
|
||||
23
.github/workflow-templates/security-docker.yml
vendored
23
.github/workflow-templates/security-docker.yml
vendored
|
|
@ -1,23 +0,0 @@
|
|||
name: Dockerfile Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
paths: ['**/Dockerfile*', '**.dockerfile']
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
paths: ['**/Dockerfile*', '**.dockerfile']
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
hadolint:
|
||||
name: Hadolint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run Hadolint
|
||||
uses: hadolint/hadolint-action@v3.1.0
|
||||
with:
|
||||
recursive: true
|
||||
failure-threshold: warning
|
||||
50
.github/workflow-templates/security-php.yml
vendored
50
.github/workflow-templates/security-php.yml
vendored
|
|
@ -1,50 +0,0 @@
|
|||
name: PHP Security
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
schedule:
|
||||
- cron: '0 6 * * 1'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
jobs:
|
||||
phpstan:
|
||||
name: PHPStan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
coverage: none
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-interaction --prefer-dist
|
||||
|
||||
- name: Run PHPStan
|
||||
run: vendor/bin/phpstan analyse --error-format=github || true
|
||||
|
||||
semgrep:
|
||||
name: Semgrep SAST
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: semgrep/semgrep
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run Semgrep
|
||||
run: semgrep scan --config auto --sarif --output results.sarif || true
|
||||
|
||||
- name: Upload SARIF
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
if: always()
|
||||
24
.github/workflow-templates/security-shell.yml
vendored
24
.github/workflow-templates/security-shell.yml
vendored
|
|
@ -1,24 +0,0 @@
|
|||
name: Shell Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
paths: ['**.sh', '**.bash', 'scripts/**']
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
paths: ['**.sh', '**.bash', 'scripts/**']
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
shellcheck:
|
||||
name: ShellCheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run ShellCheck
|
||||
uses: ludeeus/action-shellcheck@master
|
||||
with:
|
||||
severity: warning
|
||||
scandir: '.'
|
||||
format: gcc
|
||||
126
.github/workflows/ai-worker.yml
vendored
126
.github/workflows/ai-worker.yml
vendored
|
|
@ -1,126 +0,0 @@
|
|||
name: AI Worker (Free Tier)
|
||||
|
||||
# Runs on contributor's fork - uses THEIR API allowances
|
||||
# Gemini 2.0 Flash: 1500 req/day free
|
||||
# Jules: Available to all GitHub users
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
# Contributors set their own GEMINI_API_KEY in fork secrets
|
||||
# Free tier: 1500 requests/day, 1M tokens/min
|
||||
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
||||
|
||||
jobs:
|
||||
# Analyze PR with Gemini (contributor's free tier)
|
||||
gemini-review:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get diff
|
||||
id: diff
|
||||
run: |
|
||||
DIFF=$(git diff origin/${{ github.base_ref }}...HEAD | head -c 50000)
|
||||
echo "diff<<EOFMARKER" >> $GITHUB_OUTPUT
|
||||
echo "$DIFF" >> $GITHUB_OUTPUT
|
||||
echo "EOFMARKER" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Gemini Analysis
|
||||
if: env.GEMINI_API_KEY != ''
|
||||
id: gemini
|
||||
run: |
|
||||
# Call Gemini 2.0 Flash (free tier)
|
||||
RESPONSE=$(curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=$GEMINI_API_KEY" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d @- << 'PAYLOAD'
|
||||
{
|
||||
"contents": [{
|
||||
"parts": [{
|
||||
"text": "Review this code diff. Be concise. List: 1) Security issues 2) Bugs 3) Improvements. If none, say 'LGTM'.\n\nDiff:\n${{ steps.diff.outputs.diff }}"
|
||||
}]
|
||||
}],
|
||||
"generationConfig": {
|
||||
"temperature": 0.2,
|
||||
"maxOutputTokens": 1000
|
||||
}
|
||||
}
|
||||
PAYLOAD
|
||||
)
|
||||
|
||||
# Extract text from response
|
||||
REVIEW=$(echo "$RESPONSE" | jq -r '.candidates[0].content.parts[0].text // "Analysis failed"')
|
||||
echo "review<<EOFMARKER" >> $GITHUB_OUTPUT
|
||||
echo "$REVIEW" >> $GITHUB_OUTPUT
|
||||
echo "EOFMARKER" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Post Gemini review
|
||||
if: steps.gemini.outputs.review != ''
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const review = `${{ steps.gemini.outputs.review }}`;
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: `## 🤖 Gemini Analysis (Free Tier)\n\n${review}\n\n---\n_Powered by contributor's Gemini API allowance (1500 req/day free)_`
|
||||
});
|
||||
|
||||
# Trigger Jules to fix issues (contributor's Copilot allowance)
|
||||
trigger-jules:
|
||||
if: github.event_name == 'issues' && github.event.label.name == 'agent:ready'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Jules eligibility
|
||||
id: check
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Check if this repo has Copilot coding agent enabled
|
||||
const issue = context.payload.issue;
|
||||
|
||||
console.log(`Issue #${issue.number}: ${issue.title}`);
|
||||
console.log(`Labels: ${issue.labels.map(l => l.name).join(', ')}`);
|
||||
|
||||
// Jules can be assigned to issues with specific labels
|
||||
const hasAgentic = issue.labels.some(l => l.name === 'agentic');
|
||||
|
||||
return { eligible: hasAgentic, issueNumber: issue.number };
|
||||
|
||||
- name: Assign to Jules
|
||||
if: steps.check.outputs.result != ''
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Trigger Jules by adding the copilot label
|
||||
// Jules will pick up the issue and create a PR
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.issue.number,
|
||||
labels: ['copilot'] // This triggers Jules/Copilot coding agent
|
||||
});
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.issue.number,
|
||||
body: `## 🤖 Jules Activated\n\nThis issue has been assigned to GitHub Copilot coding agent (Jules).\n\nJules will:\n1. Analyze the issue\n2. Create a solution\n3. Open a PR with the fix\n\n_Using contributor's Copilot allowance_ 🆓`
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Could not assign to Jules:', e.message);
|
||||
}
|
||||
110
.github/workflows/auto-label.yml
vendored
110
.github/workflows/auto-label.yml
vendored
|
|
@ -1,110 +0,0 @@
|
|||
name: Auto Label Issues
|
||||
|
||||
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@v7
|
||||
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');
|
||||
}
|
||||
if (content.includes('setup') || content.includes('install') || content.includes('makefile')) {
|
||||
labelsToAdd.push('project:workstation');
|
||||
}
|
||||
|
||||
// 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(', ')}`);
|
||||
}
|
||||
}
|
||||
36
.github/workflows/codeql.yml
vendored
36
.github/workflows/codeql.yml
vendored
|
|
@ -1,36 +0,0 @@
|
|||
name: CodeQL
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
schedule:
|
||||
- cron: "0 6 * * 1"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: javascript
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:javascript"
|
||||
|
||||
57
.github/workflows/contributor-ci.yml
vendored
57
.github/workflows/contributor-ci.yml
vendored
|
|
@ -1,57 +0,0 @@
|
|||
name: Contributor CI
|
||||
|
||||
# Runs on fork's compute allowance (Microsoft/GitHub free tier)
|
||||
# Heavy analysis happens here, not on upstream
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore: [main, dev] # Only feature branches (forks)
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
|
||||
jobs:
|
||||
# This runs on CONTRIBUTOR'S allowance
|
||||
analyze:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run analysis
|
||||
run: |
|
||||
echo "## 🔍 Contributor Analysis" >> $GITHUB_STEP_SUMMARY
|
||||
echo "This CI runs on your fork's GitHub Actions allowance." >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Add your heavy analysis here - it's FREE for contributors
|
||||
# - CodeQL scanning
|
||||
# - Dependency analysis
|
||||
# - AI-powered code review (if using Copilot)
|
||||
# - Full test suite
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
# Linting on contributor's compute
|
||||
echo "Running lint..."
|
||||
|
||||
- name: Security scan
|
||||
run: |
|
||||
# Security scanning on contributor's compute
|
||||
echo "Running security scan..."
|
||||
|
||||
# AI-powered analysis (uses contributor's Copilot/AI allowance)
|
||||
ai-review:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: AI Analysis Placeholder
|
||||
run: |
|
||||
echo "## 🤖 AI Analysis" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "This would run AI analysis using:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Contributor's Copilot allowance" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- GitHub's free AI features" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Any AI APIs the contributor has configured" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Upstream repo pays nothing. 💰" >> $GITHUB_STEP_SUMMARY
|
||||
58
.github/workflows/docs.yml
vendored
58
.github/workflows/docs.yml
vendored
|
|
@ -1,58 +0,0 @@
|
|||
name: Deploy Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
paths:
|
||||
- 'doc/**'
|
||||
- '.vitepress/**'
|
||||
- 'package.json'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: pages
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Build with VitePress
|
||||
run: npm run docs:build
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: .vitepress/dist
|
||||
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
120
.github/workflows/fork-ai-triage.yml
vendored
120
.github/workflows/fork-ai-triage.yml
vendored
|
|
@ -1,120 +0,0 @@
|
|||
name: AI Triage (Fork Compute)
|
||||
|
||||
# Strategy: Heavy AI analysis runs on contributor's fork
|
||||
# They get free GitHub Copilot / Actions minutes
|
||||
# We only do lightweight verification
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
# Runs on contributor's GitHub Actions allowance
|
||||
ai-triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get changed files
|
||||
id: changes
|
||||
run: |
|
||||
FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | head -50)
|
||||
echo "files<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$FILES" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
echo "count=$(echo "$FILES" | wc -l)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Categorize changes
|
||||
id: categorize
|
||||
run: |
|
||||
# Determine what type of changes (runs on fork's compute)
|
||||
PHP_COUNT=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -c '\.php$' || echo 0)
|
||||
GO_COUNT=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -c '\.go$' || echo 0)
|
||||
JS_COUNT=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -cE '\.(js|ts)$' || echo 0)
|
||||
DOC_COUNT=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -cE '\.(md|txt)$' || echo 0)
|
||||
|
||||
echo "php=$PHP_COUNT" >> $GITHUB_OUTPUT
|
||||
echo "go=$GO_COUNT" >> $GITHUB_OUTPUT
|
||||
echo "js=$JS_COUNT" >> $GITHUB_OUTPUT
|
||||
echo "docs=$DOC_COUNT" >> $GITHUB_OUTPUT
|
||||
|
||||
# Suggest labels
|
||||
LABELS=""
|
||||
[ "$PHP_COUNT" -gt 0 ] && LABELS="$LABELS,lang:php"
|
||||
[ "$GO_COUNT" -gt 0 ] && LABELS="$LABELS,lang:go"
|
||||
[ "$JS_COUNT" -gt 0 ] && LABELS="$LABELS,lang:js"
|
||||
[ "$DOC_COUNT" -gt 0 ] && LABELS="$LABELS,type:docs"
|
||||
|
||||
echo "labels=${LABELS#,}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Security quick scan
|
||||
run: |
|
||||
# Quick security checks (contributor's compute)
|
||||
echo "Checking for secrets..."
|
||||
|
||||
# Check for common secret patterns
|
||||
if git diff origin/${{ github.base_ref }}...HEAD | grep -iE '(api_key|secret|password|token)\s*[:=]' | grep -v 'example\|placeholder\|xxx'; then
|
||||
echo "::warning::Possible secrets detected in diff"
|
||||
fi
|
||||
|
||||
# Check for .env files
|
||||
if git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -E '\.env$'; then
|
||||
echo "::error::Environment file changes detected - review carefully"
|
||||
fi
|
||||
|
||||
- name: Generate triage summary
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const changes = `${{ steps.changes.outputs.files }}`.split('\n').filter(f => f);
|
||||
const labels = '${{ steps.categorize.outputs.labels }}'.split(',').filter(l => l);
|
||||
|
||||
const summary = `## 🤖 AI Triage Summary
|
||||
|
||||
**Files changed:** ${changes.length}
|
||||
**Languages detected:** ${labels.filter(l => l.startsWith('lang:')).map(l => l.replace('lang:', '')).join(', ') || 'none'}
|
||||
|
||||
### Suggested labels
|
||||
${labels.map(l => '`' + l + '`').join(' ') || '_No suggestions_'}
|
||||
|
||||
### Changed files
|
||||
<details>
|
||||
<summary>View ${changes.length} files</summary>
|
||||
|
||||
\`\`\`
|
||||
${changes.join('\n')}
|
||||
\`\`\`
|
||||
</details>
|
||||
|
||||
---
|
||||
_This analysis ran on the contributor's GitHub Actions allowance._ 🆓
|
||||
`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: summary
|
||||
});
|
||||
|
||||
- name: Apply suggested labels
|
||||
if: steps.categorize.outputs.labels != ''
|
||||
uses: actions/github-script@v7
|
||||
continue-on-error: true
|
||||
with:
|
||||
script: |
|
||||
const labels = '${{ steps.categorize.outputs.labels }}'.split(',').filter(l => l);
|
||||
if (labels.length > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: labels
|
||||
});
|
||||
}
|
||||
37
.github/workflows/fork-pr-analysis.yml
vendored
37
.github/workflows/fork-pr-analysis.yml
vendored
|
|
@ -1,37 +0,0 @@
|
|||
name: PR Analysis (Fork)
|
||||
|
||||
# This workflow runs on the FORK's resources, not ours
|
||||
# Contributors get free GitHub Actions minutes
|
||||
# Microsoft/GitHub subsidizes the compute
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
# Lightweight check on our side - just verify the fork did the work
|
||||
verify-fork-ci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check fork CI status
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
owner: context.payload.pull_request.head.repo.owner.login,
|
||||
repo: context.payload.pull_request.head.repo.name,
|
||||
ref: context.payload.pull_request.head.sha
|
||||
});
|
||||
|
||||
const passed = checks.check_runs.filter(c => c.conclusion === 'success');
|
||||
const failed = checks.check_runs.filter(c => c.conclusion === 'failure');
|
||||
|
||||
console.log(`Fork CI: ${passed.length} passed, ${failed.length} failed`);
|
||||
|
||||
if (failed.length > 0) {
|
||||
core.setFailed('Fork CI has failures - contributor must fix on their fork');
|
||||
}
|
||||
|
||||
---
|
||||
# This file goes in the TEMPLATE so forks inherit it
|
||||
# The heavy work runs on contributor's GitHub Actions allowance
|
||||
145
.github/workflows/free-tier-ai.yml
vendored
145
.github/workflows/free-tier-ai.yml
vendored
|
|
@ -1,145 +0,0 @@
|
|||
name: Free Tier AI Analysis
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
# Groq - 14,400 requests/day FREE (Llama 3, Mixtral)
|
||||
groq-analysis:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get diff
|
||||
id: diff
|
||||
run: |
|
||||
git diff origin/${{ github.base_ref }}...HEAD > /tmp/diff.txt
|
||||
head -c 30000 /tmp/diff.txt > /tmp/diff_truncated.txt
|
||||
|
||||
- name: Groq Analysis
|
||||
if: env.GROQ_API_KEY != ''
|
||||
env:
|
||||
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
run: |
|
||||
# Groq is FAST and FREE (14,400 req/day)
|
||||
DIFF=$(cat /tmp/diff_truncated.txt | jq -Rs .)
|
||||
|
||||
curl -s https://api.groq.com/openai/v1/chat/completions \
|
||||
-H "Authorization: Bearer $GROQ_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"model\": \"llama-3.3-70b-versatile\",
|
||||
\"messages\": [{
|
||||
\"role\": \"user\",
|
||||
\"content\": \"Review this diff for security issues, bugs, and code smells. Be very concise. Output as: SECURITY: x issues, BUGS: x issues, SMELLS: x issues. Then list critical items only.\n\nDiff:\n${DIFF}\"
|
||||
}],
|
||||
\"temperature\": 0.1,
|
||||
\"max_tokens\": 500
|
||||
}" | jq -r '.choices[0].message.content' > /tmp/groq_review.txt
|
||||
|
||||
cat /tmp/groq_review.txt
|
||||
|
||||
# Mistral - Free tier available
|
||||
mistral-analysis:
|
||||
if: github.event_name == 'pull_request' && vars.MISTRAL_API_KEY != ''
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Mistral Code Review
|
||||
env:
|
||||
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
|
||||
run: |
|
||||
echo "Mistral analysis would run here"
|
||||
# Similar pattern to Groq
|
||||
|
||||
# Cohere - 1000 req/month free (good for classification)
|
||||
cohere-classify:
|
||||
if: github.event_name == 'issues'
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Classify Issue
|
||||
if: env.COHERE_API_KEY != ''
|
||||
env:
|
||||
COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }}
|
||||
run: |
|
||||
# Use Cohere to classify issue type/priority
|
||||
TITLE="${{ github.event.issue.title }}"
|
||||
BODY="${{ github.event.issue.body }}"
|
||||
|
||||
curl -s https://api.cohere.ai/v1/classify \
|
||||
-H "Authorization: Bearer $COHERE_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"inputs\": [\"$TITLE\"],
|
||||
\"examples\": [
|
||||
{\"text\": \"App crashes on login\", \"label\": \"bug\"},
|
||||
{\"text\": \"Add dark mode\", \"label\": \"feature\"},
|
||||
{\"text\": \"SQL injection in auth\", \"label\": \"security\"},
|
||||
{\"text\": \"Slow page load\", \"label\": \"performance\"}
|
||||
]
|
||||
}" | jq '.classifications[0].prediction'
|
||||
|
||||
# Cloudflare Workers AI - 10,000 neurons/day FREE
|
||||
cloudflare-ai:
|
||||
if: github.event_name == 'pull_request' && vars.CF_ACCOUNT_ID != ''
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Cloudflare AI Analysis
|
||||
env:
|
||||
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
|
||||
CF_ACCOUNT_ID: ${{ vars.CF_ACCOUNT_ID }}
|
||||
run: |
|
||||
# Cloudflare Workers AI - runs at the edge
|
||||
echo "Cloudflare AI analysis would run here"
|
||||
# @cf/meta/llama-3-8b-instruct is free
|
||||
|
||||
# Aggregate results and create summary
|
||||
aggregate:
|
||||
needs: [groq-analysis]
|
||||
if: always() && github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create Summary
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const summary = `## 🤖 Free Tier AI Analysis
|
||||
|
||||
Multiple AI services analyzed this PR:
|
||||
|
||||
| Service | Status | Free Tier |
|
||||
|---------|--------|-----------|
|
||||
| Groq (Llama 3) | ${{ needs.groq-analysis.result }} | 14,400 req/day |
|
||||
| Mistral | skipped | 1M tokens/month |
|
||||
| Cohere | skipped | 1000 req/month |
|
||||
| Cloudflare AI | skipped | 10K neurons/day |
|
||||
|
||||
---
|
||||
_Add API keys to your fork secrets to enable more services._
|
||||
_All analysis runs on contributor's free tier allowance._
|
||||
`;
|
||||
|
||||
// Only comment if at least one analysis ran
|
||||
if ('${{ needs.groq-analysis.result }}' !== 'skipped') {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: summary
|
||||
});
|
||||
}
|
||||
163
.github/workflows/free-tier-scanners.yml
vendored
163
.github/workflows/free-tier-scanners.yml
vendored
|
|
@ -1,163 +0,0 @@
|
|||
name: Free Tier Security Scanners
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
schedule:
|
||||
- cron: '0 6 * * 1' # Weekly Monday 6am
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
# Semgrep - FREE, powerful SAST
|
||||
semgrep:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: semgrep/semgrep
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Semgrep Scan
|
||||
run: |
|
||||
semgrep scan --config auto --sarif --output semgrep.sarif || true
|
||||
|
||||
- name: Upload SARIF
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: semgrep.sarif
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
|
||||
# Trivy - FREE container/IaC scanner
|
||||
trivy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Trivy Vulnerability Scan
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
scan-ref: '.'
|
||||
format: 'sarif'
|
||||
output: 'trivy.sarif'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload Trivy SARIF
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: trivy.sarif
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
|
||||
# Gitleaks - FREE secret scanner
|
||||
gitleaks:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Gitleaks Scan
|
||||
uses: gitleaks/gitleaks-action@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
continue-on-error: true
|
||||
|
||||
# OSV-Scanner - FREE vulnerability DB from Google
|
||||
osv-scanner:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: OSV Scanner
|
||||
uses: google/osv-scanner-action@v1
|
||||
with:
|
||||
scan-args: |-
|
||||
--recursive
|
||||
--format=sarif
|
||||
--output=osv.sarif
|
||||
.
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload OSV SARIF
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: osv.sarif
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
|
||||
# Checkov - FREE IaC scanner
|
||||
checkov:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Checkov Scan
|
||||
uses: bridgecrewio/checkov-action@v12
|
||||
with:
|
||||
directory: .
|
||||
framework: all
|
||||
output_format: sarif
|
||||
output_file_path: checkov.sarif
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload Checkov SARIF
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: checkov.sarif
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
|
||||
# Aggregate all findings for core CLI to consume
|
||||
aggregate-findings:
|
||||
needs: [semgrep, trivy, gitleaks, osv-scanner, checkov]
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Summary
|
||||
run: |
|
||||
echo "## 🔍 Security Scan Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Scanner | Status | Free Tier |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|---------|--------|-----------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Semgrep | ${{ needs.semgrep.result }} | Unlimited |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Trivy | ${{ needs.trivy.result }} | Unlimited |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Gitleaks | ${{ needs.gitleaks.result }} | Unlimited |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| OSV-Scanner | ${{ needs.osv-scanner.result }} | Unlimited |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Checkov | ${{ needs.checkov.result }} | Unlimited |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Results uploaded to GitHub Security tab." >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "_All scanners are 100% free. No API keys needed._" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Create findings artifact for core CLI
|
||||
run: |
|
||||
# Create JSON summary for core CLI to consume
|
||||
cat > findings.json << 'FINDINGS'
|
||||
{
|
||||
"timestamp": "${{ github.event.head_commit.timestamp }}",
|
||||
"commit": "${{ github.sha }}",
|
||||
"scanners": {
|
||||
"semgrep": "${{ needs.semgrep.result }}",
|
||||
"trivy": "${{ needs.trivy.result }}",
|
||||
"gitleaks": "${{ needs.gitleaks.result }}",
|
||||
"osv": "${{ needs.osv-scanner.result }}",
|
||||
"checkov": "${{ needs.checkov.result }}"
|
||||
},
|
||||
"security_tab": "https://github.com/${{ github.repository }}/security/code-scanning"
|
||||
}
|
||||
FINDINGS
|
||||
cat findings.json
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: security-findings
|
||||
path: findings.json
|
||||
retention-days: 30
|
||||
64
.github/workflows/jules-dispatch.yml
vendored
64
.github/workflows/jules-dispatch.yml
vendored
|
|
@ -1,64 +0,0 @@
|
|||
name: Jules Task Dispatch
|
||||
|
||||
# Dispatch tasks to Jules (Copilot coding agent)
|
||||
# Jules works on the contributor's fork using their Copilot Pro allowance
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
dispatch-to-jules:
|
||||
# Trigger when someone comments "@jules" or "/jules"
|
||||
if: contains(github.event.comment.body, '@jules') || contains(github.event.comment.body, '/jules')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Parse Jules command
|
||||
id: parse
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = context.payload.comment.body;
|
||||
|
||||
// Extract task from comment
|
||||
// Format: @jules <task description>
|
||||
// or: /jules fix the bug in auth.php
|
||||
const match = comment.match(/(?:@jules|\/jules)\s+(.+)/i);
|
||||
const task = match ? match[1].trim() : null;
|
||||
|
||||
return { task, commenter: context.payload.comment.user.login };
|
||||
|
||||
- name: Create Jules task
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const result = ${{ steps.parse.outputs.result }};
|
||||
|
||||
if (!result.task) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: `@${result.commenter} Please specify a task for Jules:\n\n\`@jules fix the authentication bug\`\n\`@jules add unit tests for User model\`\n\`@jules refactor this to use async/await\``
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Add copilot label to trigger Jules
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['copilot', 'agent:wip']
|
||||
});
|
||||
|
||||
// Create a sub-issue or task for Jules
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: `## 🤖 Jules Task Queued\n\n**Task:** ${result.task}\n**Requested by:** @${result.commenter}\n\nJules (Copilot coding agent) will work on this using the repository owner's Copilot allowance.\n\n---\n_Tip: Fork this repo to use your own Copilot Pro allowance for faster processing._`
|
||||
});
|
||||
140
.github/workflows/template-bootstrap.yml
vendored
140
.github/workflows/template-bootstrap.yml
vendored
|
|
@ -1,140 +0,0 @@
|
|||
name: Bootstrap from Template
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
repo_type:
|
||||
description: 'Repository type'
|
||||
required: true
|
||||
default: 'module'
|
||||
type: choice
|
||||
options:
|
||||
- foundation
|
||||
- module
|
||||
- product
|
||||
- service
|
||||
- infra
|
||||
- template
|
||||
|
||||
jobs:
|
||||
bootstrap:
|
||||
# Only run if this looks like a fresh repo (no releases, few commits)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check if bootstrap needed
|
||||
id: check
|
||||
run: |
|
||||
COMMIT_COUNT=$(git rev-list --count HEAD)
|
||||
if [ "$COMMIT_COUNT" -lt 5 ]; then
|
||||
echo "needs_bootstrap=true" >> $GITHUB_OUTPUT
|
||||
echo "Fresh repo detected ($COMMIT_COUNT commits)"
|
||||
else
|
||||
echo "needs_bootstrap=false" >> $GITHUB_OUTPUT
|
||||
echo "Existing repo ($COMMIT_COUNT commits) - skipping bootstrap"
|
||||
fi
|
||||
|
||||
- name: Create standard labels
|
||||
if: steps.check.outputs.needs_bootstrap == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Agent workflow labels
|
||||
gh label create "agent:ready" --description "Task ready for AI agent" --color "0E8A16" --force || true
|
||||
gh label create "agent:wip" --description "Work in progress by agent" --color "F9D0C4" --force || true
|
||||
gh label create "agent:review" --description "Needs verification" --color "FBCA04" --force || true
|
||||
gh label create "agent:blocked" --description "Needs human input" --color "D93F0B" --force || true
|
||||
gh label create "verified" --description "Work verified" --color "0E8A16" --force || true
|
||||
gh label create "verify-failed" --description "Verification failed" --color "D93F0B" --force || true
|
||||
gh label create "agentic" --description "AI-consumable task" --color "5319E7" --force || true
|
||||
|
||||
# Type labels
|
||||
gh label create "type:feature" --description "New feature" --color "0052CC" --force || true
|
||||
gh label create "type:bug" --description "Bug fix" --color "D93F0B" --force || true
|
||||
gh label create "type:security" --description "Security issue" --color "D93F0B" --force || true
|
||||
gh label create "type:docs" --description "Documentation" --color "0075CA" --force || true
|
||||
|
||||
# Priority labels
|
||||
gh label create "priority:critical" --description "Critical priority" --color "B60205" --force || true
|
||||
gh label create "priority:high" --description "High priority" --color "D93F0B" --force || true
|
||||
gh label create "priority:medium" --description "Medium priority" --color "FBCA04" --force || true
|
||||
gh label create "priority:low" --description "Low priority" --color "0E8A16" --force || true
|
||||
|
||||
echo "✅ Labels created"
|
||||
|
||||
- name: Set dev as default branch
|
||||
if: steps.check.outputs.needs_bootstrap == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Create dev branch if it doesn't exist
|
||||
git checkout -b dev 2>/dev/null || git checkout dev
|
||||
git push origin dev --force-with-lease || true
|
||||
|
||||
# Set as default (requires admin token, may fail with GITHUB_TOKEN)
|
||||
gh repo edit --default-branch dev || echo "⚠️ Could not set default branch (needs admin)"
|
||||
|
||||
- name: Enable security features
|
||||
if: steps.check.outputs.needs_bootstrap == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Enable vulnerability alerts
|
||||
gh api -X PUT repos/${{ github.repository }}/vulnerability-alerts || true
|
||||
|
||||
# Enable automated security fixes
|
||||
gh api -X PUT repos/${{ github.repository }}/automated-security-fixes || true
|
||||
|
||||
echo "✅ Security features enabled"
|
||||
|
||||
- name: Create setup instructions issue
|
||||
if: steps.check.outputs.needs_bootstrap == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh issue create \
|
||||
--title "🚀 Repository Setup Checklist" \
|
||||
--label "agentic,type:docs" \
|
||||
--body "## Post-Template Setup
|
||||
|
||||
This repo was created from the [core-devops template](https://github.com/host-uk/core-devops).
|
||||
|
||||
### Automated ✅
|
||||
- [x] Standard labels created
|
||||
- [x] Security features enabled
|
||||
- [x] CodeRabbit config present
|
||||
|
||||
### Manual Steps
|
||||
- [ ] Update \`repos.yaml\` with your package details
|
||||
- [ ] Update \`CLAUDE.md\` with project-specific guidance
|
||||
- [ ] Update \`README.md\` with project description
|
||||
- [ ] Add to org project if needed
|
||||
- [ ] Set up any required secrets (\`PROJECT_TOKEN\` for auto-project)
|
||||
- [ ] Remove/customize template files
|
||||
|
||||
### Optional
|
||||
- [ ] Enable GitHub Pages for docs
|
||||
- [ ] Add to CodeRabbit (if not auto-enabled)
|
||||
- [ ] Configure branch protection rules
|
||||
|
||||
---
|
||||
_This issue was auto-created by the template bootstrap workflow._"
|
||||
|
||||
echo "✅ Setup issue created"
|
||||
|
||||
- name: Summary
|
||||
if: steps.check.outputs.needs_bootstrap == 'true'
|
||||
run: |
|
||||
echo "## 🎉 Bootstrap Complete" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Your repo has been configured with:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ Standard labels for agent workflow" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ Security features enabled" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ Setup checklist issue created" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "See the created issue for remaining manual steps." >> $GITHUB_STEP_SUMMARY
|
||||
153
.github/workflows/test-setup.yml
vendored
153
.github/workflows/test-setup.yml
vendored
|
|
@ -1,153 +0,0 @@
|
|||
name: Test Setup Scripts
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
paths:
|
||||
- 'scripts/**'
|
||||
- '.github/workflows/test-setup.yml'
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
paths:
|
||||
- 'scripts/**'
|
||||
- '.github/workflows/test-setup.yml'
|
||||
# Weekly test to catch upstream changes (package repos, etc.)
|
||||
schedule:
|
||||
- cron: '0 6 * * 1' # Every Monday at 6am UTC
|
||||
workflow_dispatch: # Manual trigger
|
||||
|
||||
jobs:
|
||||
test-linux:
|
||||
name: Linux (Ubuntu)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run install-deps.sh
|
||||
run: |
|
||||
chmod +x scripts/install-deps.sh
|
||||
./scripts/install-deps.sh
|
||||
|
||||
- name: Verify dependencies installed
|
||||
run: |
|
||||
echo "=== Checking installed tools ==="
|
||||
git --version
|
||||
gh --version
|
||||
go version
|
||||
php --version
|
||||
composer --version
|
||||
node --version
|
||||
pnpm --version
|
||||
echo "=== All dependencies verified ==="
|
||||
|
||||
- name: Run install-core.sh
|
||||
run: |
|
||||
chmod +x scripts/install-core.sh
|
||||
./scripts/install-core.sh
|
||||
env:
|
||||
INSTALL_DIR: ${{ github.workspace }}/bin
|
||||
|
||||
- name: Verify core CLI installed
|
||||
run: |
|
||||
export PATH="${{ github.workspace }}/bin:$PATH"
|
||||
core --version || echo "Core CLI version check"
|
||||
core doctor || echo "Core doctor completed"
|
||||
|
||||
test-macos:
|
||||
name: macOS
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run install-deps.sh
|
||||
run: |
|
||||
chmod +x scripts/install-deps.sh
|
||||
./scripts/install-deps.sh
|
||||
|
||||
- name: Verify dependencies installed
|
||||
run: |
|
||||
echo "=== Checking installed tools ==="
|
||||
git --version
|
||||
gh --version
|
||||
go version
|
||||
php --version
|
||||
composer --version
|
||||
node --version
|
||||
pnpm --version
|
||||
echo "=== All dependencies verified ==="
|
||||
|
||||
- name: Run install-core.sh
|
||||
run: |
|
||||
chmod +x scripts/install-core.sh
|
||||
./scripts/install-core.sh
|
||||
env:
|
||||
INSTALL_DIR: ${{ github.workspace }}/bin
|
||||
|
||||
- name: Verify core CLI installed
|
||||
run: |
|
||||
export PATH="${{ github.workspace }}/bin:$PATH"
|
||||
core --version || echo "Core CLI version check"
|
||||
core doctor || echo "Core doctor completed"
|
||||
|
||||
test-windows:
|
||||
name: Windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run install-deps.ps1
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Run as current user (GitHub runners have admin)
|
||||
# Modify script to skip admin check for CI
|
||||
$script = Get-Content scripts/install-deps.ps1 -Raw
|
||||
$script = $script -replace 'Write-Err "Please run this script as Administrator"', 'Write-Warn "Skipping admin check in CI"'
|
||||
$script | Set-Content scripts/install-deps-ci.ps1
|
||||
.\scripts\install-deps-ci.ps1
|
||||
|
||||
- name: Verify dependencies installed
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "=== Checking installed tools ==="
|
||||
git --version
|
||||
gh --version
|
||||
go version
|
||||
php --version
|
||||
composer --version
|
||||
node --version
|
||||
pnpm --version
|
||||
Write-Host "=== All dependencies verified ==="
|
||||
|
||||
- name: Run install-core.ps1
|
||||
shell: pwsh
|
||||
run: |
|
||||
.\scripts\install-core.ps1
|
||||
env:
|
||||
INSTALL_DIR: ${{ github.workspace }}\bin
|
||||
|
||||
- name: Verify core CLI installed
|
||||
shell: pwsh
|
||||
run: |
|
||||
$env:PATH = "${{ github.workspace }}\bin;$env:PATH"
|
||||
core --version
|
||||
core doctor
|
||||
|
||||
# Summary job that requires all platforms to pass
|
||||
setup-complete:
|
||||
name: All Platforms
|
||||
needs: [test-linux, test-macos, test-windows]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check results
|
||||
run: |
|
||||
if [ "${{ needs.test-linux.result }}" != "success" ] || \
|
||||
[ "${{ needs.test-macos.result }}" != "success" ] || \
|
||||
[ "${{ needs.test-windows.result }}" != "success" ]; then
|
||||
echo "One or more platform tests failed"
|
||||
exit 1
|
||||
fi
|
||||
echo "All platform tests passed!"
|
||||
14
.gitignore
vendored
14
.gitignore
vendored
|
|
@ -5,15 +5,8 @@ packages/*
|
|||
# Core CLI cache (transient data, not config)
|
||||
.core/cache/
|
||||
|
||||
# IDE - share useful configs, ignore user-specific
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/shelf/
|
||||
.idea/httpRequests/
|
||||
.idea/dataSources/
|
||||
.idea/dataSources.local.xml
|
||||
.idea/copilot*.xml
|
||||
.idea/material_theme*.xml
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
|
|
@ -28,6 +21,3 @@ Thumbs.db
|
|||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Template - remove these lines after setup
|
||||
# !TEMPLATE_SETUP.md
|
||||
|
|
|
|||
17
.idea/.gitignore
generated
vendored
17
.idea/.gitignore
generated
vendored
|
|
@ -1,17 +0,0 @@
|
|||
# User-specific files
|
||||
/workspace.xml
|
||||
/tasks.xml
|
||||
/shelf/
|
||||
/httpRequests/
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
/copilot*.xml
|
||||
|
||||
# Sensitive data
|
||||
/webServers.xml
|
||||
/deployment.xml
|
||||
/.env
|
||||
|
||||
# OS/editor artifacts
|
||||
*.iws
|
||||
.DS_Store
|
||||
79
.idea/codeStyles/Project.xml
generated
79
.idea/codeStyles/Project.xml
generated
|
|
@ -1,79 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<!-- PHP PSR-12 Style -->
|
||||
<PHPCodeStyleSettings>
|
||||
<option name="ALIGN_KEY_VALUE_PAIRS" value="false" />
|
||||
<option name="ALIGN_PHPDOC_PARAM_NAMES" value="false" />
|
||||
<option name="ALIGN_PHPDOC_COMMENTS" value="false" />
|
||||
<option name="ALIGN_ASSIGNMENTS" value="false" />
|
||||
<option name="ALIGN_MATCH_ARM_ARROW" value="false" />
|
||||
<option name="BLANK_LINES_BEFORE_RETURN_STATEMENT" value="1" />
|
||||
<option name="KEEP_RPAREN_AND_LBRACE_ON_ONE_LINE" value="true" />
|
||||
<option name="SPACE_AFTER_UNARY_NOT" value="false" />
|
||||
<option name="LOWER_CASE_BOOLEAN_CONST" value="true" />
|
||||
<option name="LOWER_CASE_NULL_CONST" value="true" />
|
||||
<option name="FORCE_SHORT_DECLARATION_ARRAY_STYLE" value="true" />
|
||||
<option name="PHPDOC_BLANK_LINE_BEFORE_TAGS" value="true" />
|
||||
<option name="PHPDOC_BLANK_LINES_AROUND_PARAMETERS" value="false" />
|
||||
<option name="PHPDOC_WRAP_LONG_LINES" value="true" />
|
||||
<option name="MULTILINE_CHAINED_CALLS_SEMICOLON_ON_NEW_LINE" value="true" />
|
||||
<option name="COMMA_AFTER_LAST_ARRAY_ELEMENT" value="true" />
|
||||
<option name="COMMA_AFTER_LAST_PARAMETER" value="true" />
|
||||
<option name="COMMA_AFTER_LAST_MATCH_ARM" value="true" />
|
||||
<option name="BLANK_LINE_BEFORE_RETURN_STATEMENT" value="true" />
|
||||
<option name="NAMESPACE_BRACE_STYLE" value="1" />
|
||||
</PHPCodeStyleSettings>
|
||||
<codeStyleSettings language="PHP">
|
||||
<option name="BLANK_LINES_AFTER_PACKAGE" value="1" />
|
||||
<option name="BLANK_LINES_BEFORE_IMPORTS" value="1" />
|
||||
<option name="BLANK_LINES_AFTER_IMPORTS" value="1" />
|
||||
<option name="BLANK_LINES_AROUND_CLASS" value="1" />
|
||||
<option name="BLANK_LINES_AROUND_METHOD" value="1" />
|
||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||
<option name="CLASS_BRACE_STYLE" value="1" />
|
||||
<option name="METHOD_BRACE_STYLE" value="1" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
<option name="ALIGN_MULTILINE_FOR" value="false" />
|
||||
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="false" />
|
||||
<option name="SPACE_BEFORE_IF_PARENTHESES" value="true" />
|
||||
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="true" />
|
||||
<option name="SPACE_BEFORE_FOR_PARENTHESES" value="true" />
|
||||
<option name="SPACE_BEFORE_CATCH_PARENTHESES" value="true" />
|
||||
<option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="true" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="5" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||
<option name="ARRAY_INITIALIZER_WRAP" value="5" />
|
||||
<option name="IF_BRACE_FORCE" value="3" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||
<option name="FOR_BRACE_FORCE" value="3" />
|
||||
</codeStyleSettings>
|
||||
<!-- JavaScript/TypeScript -->
|
||||
<codeStyleSettings language="JavaScript">
|
||||
<option name="SPACE_BEFORE_METHOD_PARENTHESES" value="true" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="TypeScript">
|
||||
<option name="SPACE_BEFORE_METHOD_PARENTHESES" value="true" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<!-- YAML -->
|
||||
<codeStyleSettings language="yaml">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/codeStyles/codeStyleConfig.xml
generated
8
.idea/codeStyles/codeStyleConfig.xml
generated
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
</project>
|
||||
29
.idea/core-devops.iml
generated
29
.idea/core-devops.iml
generated
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/packages" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-php/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-tenant/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-admin/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-api/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-mcp/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-agentic/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-bio/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-social/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-analytics/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-notify/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-trust/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-support/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-commerce/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-content/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-tools/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-uptelligence/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-developer/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/core-template/vendor" />
|
||||
<excludePattern pattern="node_modules" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
33
.idea/dictionaries/hostuk.xml
generated
33
.idea/dictionaries/hostuk.xml
generated
|
|
@ -1,33 +0,0 @@
|
|||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="hostuk">
|
||||
<words>
|
||||
<w>agentic</w>
|
||||
<w>biohost</w>
|
||||
<w>devops</w>
|
||||
<w>fileable</w>
|
||||
<w>hostuk</w>
|
||||
<w>laravel</w>
|
||||
<w>livewire</w>
|
||||
<w>mcp</w>
|
||||
<w>middlewares</w>
|
||||
<w>multitenancy</w>
|
||||
<w>namespacing</w>
|
||||
<w>notifyhost</w>
|
||||
<w>oauth</w>
|
||||
<w>phpstan</w>
|
||||
<w>pint</w>
|
||||
<w>sanctum</w>
|
||||
<w>serializable</w>
|
||||
<w>socialhost</w>
|
||||
<w>tailwindcss</w>
|
||||
<w>tenancy</w>
|
||||
<w>trusthost</w>
|
||||
<w>uptelligence</w>
|
||||
<w>uuid</w>
|
||||
<w>uuids</w>
|
||||
<w>vite</w>
|
||||
<w>webhook</w>
|
||||
<w>webhooks</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
26
.idea/inspectionProfiles/Host_UK.xml
generated
26
.idea/inspectionProfiles/Host_UK.xml
generated
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Host UK" />
|
||||
<!-- PHP Inspections -->
|
||||
<inspection_tool class="PhpUnused" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpMissingReturnTypeInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpMissingParamTypeInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpUnusedLocalVariableInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpUnusedPrivateMethodInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpUnusedPrivateFieldInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PhpArrayShapeAttributeCanBeAddedInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PhpDocMissingThrowsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<!-- Laravel-specific: don't warn about facades -->
|
||||
<inspection_tool class="PhpUndefinedMethodInspection" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<scope name="Vendor" level="INFORMATION" enabled="false" />
|
||||
</inspection_tool>
|
||||
<!-- Ignore TODO comments in vendor -->
|
||||
<inspection_tool class="TodoComment" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<scope name="Vendor" level="INFORMATION" enabled="false" />
|
||||
</inspection_tool>
|
||||
<!-- TypeScript/JavaScript -->
|
||||
<inspection_tool class="TypeScriptUnresolvedReference" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="JSUnusedLocalSymbols" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
8
.idea/inspectionProfiles/profiles_settings.xml
generated
8
.idea/inspectionProfiles/profiles_settings.xml
generated
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<option name="PROJECT_PROFILE" value="Host UK" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
16
.idea/laravel-idea.xml
generated
16
.idea/laravel-idea.xml
generated
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="LaravelSettings">
|
||||
<option name="routeNamespaceModule" value="" />
|
||||
<option name="routeNamespaceWeb" value="" />
|
||||
<option name="viewPath" value="" />
|
||||
<option name="routeNamespaceApi" value="" />
|
||||
<option name="controllerNamespace" value="" />
|
||||
<option name="basePath" value="$PROJECT_DIR$/packages/core-php" />
|
||||
<option name="apiResourceNamespace" value="" />
|
||||
<option name="resourceNamespace" value="" />
|
||||
<option name="multipleModules" value="true" />
|
||||
<option name="livewireEnabled" value="true" />
|
||||
<option name="bladeDirectiveIgnorePrefix" value="" />
|
||||
</component>
|
||||
</project>
|
||||
9
.idea/misc.xml
generated
9
.idea/misc.xml
generated
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/core-devops.iml" filepath="$PROJECT_DIR$/.idea/core-devops.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
17
.idea/php.xml
generated
17
.idea/php.xml
generated
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.4">
|
||||
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
||||
</component>
|
||||
<component name="PhpIncludePathManager">
|
||||
<include_path>
|
||||
<path value="$PROJECT_DIR$/packages/core-php/vendor" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpStanOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PhpCSFixerOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
15
.idea/runConfigurations/Clone_All_Repos.xml
generated
15
.idea/runConfigurations/Clone_All_Repos.xml
generated
|
|
@ -1,15 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Clone All Repos" type="ShConfigurationType">
|
||||
<option name="SCRIPT_TEXT" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/scripts/clone-repos.ps1" />
|
||||
<option name="SCRIPT_OPTIONS" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="powershell" />
|
||||
<option name="INTERPRETER_OPTIONS" value="-ExecutionPolicy Bypass -File" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Composer Lint (core-php)" type="ComposerRunConfigurationType">
|
||||
<option name="command" value="lint" />
|
||||
<option name="workingDir" value="$PROJECT_DIR$/packages/core-php" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Composer Test (core-php)" type="ComposerRunConfigurationType">
|
||||
<option name="command" value="test" />
|
||||
<option name="workingDir" value="$PROJECT_DIR$/packages/core-php" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
19
.idea/runConfigurations/PHPStan__core_php_.xml
generated
19
.idea/runConfigurations/PHPStan__core_php_.xml
generated
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="PHPStan (core-php)" type="PhpUnitRunConfigurationType" factoryName="PHPUnit">
|
||||
<CommandLine workingDirectory="$PROJECT_DIR$/packages/core-php" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" />
|
||||
<option name="externalSystemIdString" value="com.jetbrains.php.phpunit" />
|
||||
<option name="scriptParameters" value="analyse" />
|
||||
<option name="vmOptions" />
|
||||
</ExternalSystemSettings>
|
||||
<EXTENSION ID="PhpQualityToolRunConfigurationExtensionSettingsManager">
|
||||
<QualityTool>
|
||||
<option name="tool" value="PHPStan" />
|
||||
</QualityTool>
|
||||
</EXTENSION>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
4
.idea/scopes/Packages.xml
generated
4
.idea/scopes/Packages.xml
generated
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="DependencyValidationManager">
|
||||
<scope name="Packages" pattern="file[core-devops]:packages//*" />
|
||||
</component>
|
||||
4
.idea/scopes/Tests.xml
generated
4
.idea/scopes/Tests.xml
generated
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="DependencyValidationManager">
|
||||
<scope name="Tests" pattern="file[core-devops]:packages//tests//*||file[core-devops]:packages//*/Tests//*" />
|
||||
</component>
|
||||
4
.idea/scopes/Vendor.xml
generated
4
.idea/scopes/Vendor.xml
generated
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component name="DependencyValidationManager">
|
||||
<scope name="Vendor" pattern="file[core-devops]:packages//vendor//*" />
|
||||
</component>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
25
.idea/watcherTasks.xml
generated
25
.idea/watcherTasks.xml
generated
|
|
@ -1,25 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions">
|
||||
<TaskOptions isEnabled="false">
|
||||
<option name="arguments" value="$FilePath$" />
|
||||
<option name="checkSyntaxErrors" value="true" />
|
||||
<option name="description" value="Laravel Pint - Format on save" />
|
||||
<option name="exitCodeBehavior" value="ERROR" />
|
||||
<option name="fileExtension" value="php" />
|
||||
<option name="immediateSync" value="false" />
|
||||
<option name="name" value="Pint" />
|
||||
<option name="output" value="" />
|
||||
<option name="outputFilters">
|
||||
<array />
|
||||
</option>
|
||||
<option name="outputFromStdout" value="false" />
|
||||
<option name="program" value="$ProjectFileDir$/packages/core-php/vendor/bin/pint" />
|
||||
<option name="runOnExternalChanges" value="false" />
|
||||
<option name="scopeName" value="Packages" />
|
||||
<option name="trackOnlyRoot" value="true" />
|
||||
<option name="workingDir" value="$FileDir$" />
|
||||
<envs />
|
||||
</TaskOptions>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
import { defineConfig } from 'vitepress'
|
||||
|
||||
const pkg = 'devops'
|
||||
const canonical = `https://core.help/packages/${pkg}/`
|
||||
|
||||
export default defineConfig({
|
||||
title: 'Host UK DevOps',
|
||||
description: 'Developer workspace orchestrator for Host UK',
|
||||
|
||||
srcDir: 'doc',
|
||||
outDir: '.vitepress/dist',
|
||||
|
||||
head: [
|
||||
['link', { rel: 'canonical', href: canonical }],
|
||||
['meta', { property: 'og:site_name', content: 'Host UK Documentation' }],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'core.help', link: 'https://core.help' },
|
||||
],
|
||||
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
{ text: 'Introduction', link: '/' },
|
||||
{ text: 'Quick Start', link: '/quick-start' },
|
||||
{ text: 'Commands', link: '/commands' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Configuration',
|
||||
items: [
|
||||
{ text: '.core/ Folder', link: '/core-folder' },
|
||||
{ text: 'repos.yaml', link: '/repos-yaml' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Reference',
|
||||
items: [
|
||||
{ text: 'Package Types', link: '/package-types' },
|
||||
{ text: 'Troubleshooting', link: '/troubleshooting' },
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/host-uk/core-devops' }
|
||||
],
|
||||
|
||||
footer: {
|
||||
message: 'Released under the EUPL-1.2 License.',
|
||||
copyright: 'Copyright © Host UK'
|
||||
},
|
||||
|
||||
search: {
|
||||
provider: 'local'
|
||||
},
|
||||
|
||||
editLink: {
|
||||
pattern: 'https://github.com/host-uk/core-devops/edit/dev/doc/:path',
|
||||
text: 'Edit this page on GitHub'
|
||||
}
|
||||
},
|
||||
|
||||
sitemap: {
|
||||
hostname: canonical
|
||||
},
|
||||
|
||||
transformHead({ pageData }) {
|
||||
const head: any[] = []
|
||||
const pagePath = pageData.relativePath.replace(/\.md$/, '.html').replace(/index\.html$/, '')
|
||||
head.push(['link', { rel: 'canonical', href: `${canonical}${pagePath}` }])
|
||||
return head
|
||||
}
|
||||
})
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
.dev-banner {
|
||||
background: linear-gradient(90deg, #7c3aed 0%, #2563eb 100%);
|
||||
color: white;
|
||||
padding: 0.5rem 1rem;
|
||||
text-align: center;
|
||||
font-size: 0.875rem;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.dev-banner a {
|
||||
color: #fbbf24;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.dev-banner a:hover {
|
||||
color: #fcd34d;
|
||||
}
|
||||
|
||||
.VPNav {
|
||||
top: 36px !important;
|
||||
}
|
||||
|
||||
.VPSidebar {
|
||||
top: calc(var(--vp-nav-height) + 36px) !important;
|
||||
height: calc(100vh - var(--vp-nav-height) - 36px) !important;
|
||||
}
|
||||
|
||||
.VPContent {
|
||||
padding-top: 36px;
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
import { h } from 'vue'
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import type { Theme } from 'vitepress'
|
||||
import './custom.css'
|
||||
|
||||
const Banner = () => {
|
||||
return h('div', { class: 'dev-banner' }, [
|
||||
h('span', '📚 Developer preview. '),
|
||||
h('a', { href: 'https://core.help/packages/devops/', target: '_blank' }, 'Visit core.help'),
|
||||
h('span', ' for the complete documentation.')
|
||||
])
|
||||
}
|
||||
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
Layout() {
|
||||
return h(DefaultTheme.Layout, null, {
|
||||
'layout-top': () => h(Banner)
|
||||
})
|
||||
}
|
||||
} satisfies Theme
|
||||
43
CLAUDE.md
43
CLAUDE.md
|
|
@ -53,38 +53,12 @@ See `.core/docs/core-folder-spec.md` for the full specification that each packag
|
|||
```bash
|
||||
# macOS/Linux
|
||||
git clone git@github.com:host-uk/core-devops.git && cd core-devops && make setup
|
||||
|
||||
# Windows (PowerShell as Admin)
|
||||
.\scripts\install-deps.ps1 && .\scripts\install-core.ps1 && core setup
|
||||
```
|
||||
|
||||
### Windows Setup
|
||||
|
||||
The `core` CLI is not yet available on Windows. Use these steps instead:
|
||||
|
||||
```powershell
|
||||
# 1. Install dependencies (PowerShell as Admin)
|
||||
.\scripts\install-deps.ps1
|
||||
|
||||
# 2. Authenticate GitHub CLI
|
||||
gh auth login -h github.com -p https -s workflow,repo,read:org,read:project,project
|
||||
|
||||
# 3. Clone all repos
|
||||
.\scripts\clone-repos.ps1
|
||||
|
||||
# 4. Enable PHP extensions (edit C:\tools\php84\php.ini, uncomment these):
|
||||
# extension=curl
|
||||
# extension=fileinfo
|
||||
# extension=mbstring
|
||||
# extension=openssl
|
||||
# extension=pdo_sqlite
|
||||
|
||||
# 5. Install and test a package
|
||||
cd packages/core-php
|
||||
composer install
|
||||
composer test
|
||||
```
|
||||
|
||||
### Environment Variables (macOS/Linux)
|
||||
|
||||
For `install-core.sh`:
|
||||
Environment variables for `install-core.sh`:
|
||||
- `INSTALL_DIR` - Binary location (default: `~/.local/bin`)
|
||||
- `BUILD_FROM_SOURCE` - `true`, `false`, or `auto` (default: `auto`, tries binary then builds)
|
||||
|
||||
|
|
@ -162,16 +136,9 @@ Defined in `repos.yaml`:
|
|||
## Troubleshooting
|
||||
|
||||
- **"core: command not found"** → `make install-core` (builds from https://github.com/host-uk/core)
|
||||
- **"gh: command not found"** → `brew install gh && gh auth login -h github.com -p https -s workflow,repo,read:org,read:project,project`
|
||||
- **"refusing to allow..." or "missing required scopes"** → `gh auth refresh -h github.com -s workflow,read:project,project`
|
||||
- **"gh: command not found"** → `brew install gh && gh auth login`
|
||||
- **Clone failures** → `ssh -T git@github.com` to verify SSH keys
|
||||
|
||||
### Windows-Specific
|
||||
|
||||
- **"openssl extension is required"** → Enable extensions in `C:\tools\php84\php.ini` (see setup above)
|
||||
- **"composer: command not found"** → Use PowerShell, not Git Bash: `powershell -Command "composer install"`
|
||||
- **core CLI not available** → Use `.\scripts\clone-repos.ps1` and work directly with composer
|
||||
|
||||
## This Repo's Scope
|
||||
|
||||
Don't add application code here. This repo only contains:
|
||||
|
|
|
|||
139
CONTRIBUTING.md
139
CONTRIBUTING.md
|
|
@ -1,139 +0,0 @@
|
|||
# Contributing Compute to Host UK
|
||||
|
||||
**Host UK is a UK Community Interest Company (CIC)** - a social enterprise legally required to use our work for community benefit. Our assets are locked for public good, not shareholders.
|
||||
|
||||
## The Mission
|
||||
|
||||
1. **Build tools** that make development easier (core CLI, modules)
|
||||
2. **Aggregate free compute** from community members' unused allowances
|
||||
3. **Give back** by fixing security issues in unfunded OSS projects
|
||||
|
||||
The LLMs learned to code from open source. We're directing resources back to those projects.
|
||||
|
||||
---
|
||||
|
||||
## Contribute Compute (5 minutes)
|
||||
|
||||
You don't need to write code. Your unused free tier allowances become part of a distributed network that fixes OSS.
|
||||
|
||||
### Step 1: Fork this repo
|
||||
|
||||
```bash
|
||||
gh repo fork host-uk/core-devops --clone
|
||||
cd core-devops
|
||||
```
|
||||
|
||||
### Step 2: Add your free API keys
|
||||
|
||||
```bash
|
||||
# Gemini (1500 req/day free)
|
||||
# Get key: https://aistudio.google.com/apikey
|
||||
gh secret set GEMINI_API_KEY
|
||||
|
||||
# Groq (14,400 req/day free)
|
||||
# Get key: https://console.groq.com/keys
|
||||
gh secret set GROQ_API_KEY
|
||||
|
||||
# Optional: More services
|
||||
gh secret set MISTRAL_API_KEY # https://console.mistral.ai/
|
||||
gh secret set COHERE_API_KEY # https://dashboard.cohere.com/
|
||||
```
|
||||
|
||||
### Step 3: Enable GitHub Actions
|
||||
|
||||
Go to your fork → Actions tab → Enable workflows
|
||||
|
||||
### Step 4: Done!
|
||||
|
||||
Your fork now:
|
||||
- Runs security scans (Semgrep, Trivy, Gitleaks) - **free, no keys needed**
|
||||
- Runs AI analysis when you work on PRs - **uses your free tier**
|
||||
- Contributes to the distributed verification network
|
||||
|
||||
---
|
||||
|
||||
## Contribute Verification (10 min/week)
|
||||
|
||||
Help verify other agents' work (human or AI). No agent can verify their own work.
|
||||
|
||||
### Find tasks:
|
||||
|
||||
```bash
|
||||
# Install core CLI
|
||||
make install-core
|
||||
|
||||
# Find tasks needing verification
|
||||
core issues --label agent:review
|
||||
|
||||
# Or browse: https://github.com/orgs/host-uk/projects/2
|
||||
```
|
||||
|
||||
### Verify:
|
||||
|
||||
1. Review the implementation
|
||||
2. Check tests pass
|
||||
3. Add `verified` or `verify-failed` label
|
||||
|
||||
---
|
||||
|
||||
## Contribute Code
|
||||
|
||||
Standard PR workflow:
|
||||
|
||||
```bash
|
||||
# Create branch
|
||||
git checkout -b fix/issue-42
|
||||
|
||||
# Make changes, commit
|
||||
git add . && git commit -m "fix: description"
|
||||
|
||||
# Push (CI runs on YOUR allowance, not ours)
|
||||
git push origin fix/issue-42
|
||||
|
||||
# Create PR
|
||||
gh pr create
|
||||
```
|
||||
|
||||
Your PR will be:
|
||||
- Analyzed by AI (Gemini, Groq) - your free tier
|
||||
- Scanned for security issues - free
|
||||
- Reviewed by CodeRabbit - free
|
||||
- Verified by a different contributor
|
||||
|
||||
---
|
||||
|
||||
## The Economics
|
||||
|
||||
| Who | Pays For |
|
||||
|-----|----------|
|
||||
| Microsoft | GitHub Actions (2000 min/month per user) |
|
||||
| Google | Gemini API (1500 req/day per user) |
|
||||
| Groq | Llama 3 inference (14,400 req/day per user) |
|
||||
| Contributors | Nothing ($0) |
|
||||
| Host UK | Nothing ($0) |
|
||||
| OSS Projects | Get free security fixes |
|
||||
|
||||
**100 contributors × free tiers = enterprise-scale compute for public good**
|
||||
|
||||
---
|
||||
|
||||
## Where the Work Goes
|
||||
|
||||
1. **Host UK packages** - Our tools and modules
|
||||
2. **Unfunded OSS** - Popular packages with no security budget
|
||||
3. **Community requests** - Projects our members depend on
|
||||
|
||||
We're not hoarding. We're redistributing tech resources to the commons.
|
||||
|
||||
---
|
||||
|
||||
## Questions?
|
||||
|
||||
- Discord: https://discord.gg/host-uk
|
||||
- Issues: https://github.com/host-uk/core-devops/issues
|
||||
|
||||
**License:** EUPL-1.2 (copyleft, EU-recognized, compatible with GPL)
|
||||
|
||||
---
|
||||
|
||||
*Host UK CIC - Building ethical infrastructure for the open source community*
|
||||
|
|
@ -32,7 +32,7 @@ You're now ready to develop. The workspace starts with `core-php` as the active
|
|||
core doctor
|
||||
|
||||
# See workspace status
|
||||
core dev health
|
||||
core health
|
||||
|
||||
# Run tests in the active package (core-php)
|
||||
core php test
|
||||
|
|
@ -136,12 +136,7 @@ make install-core
|
|||
|
||||
**"gh: command not found"**
|
||||
```bash
|
||||
brew install gh && gh auth login -h github.com -p https -s workflow,repo,read:org,read:project,project
|
||||
```
|
||||
|
||||
**"refusing to allow an OAuth App to create or update workflow"** or **"missing required scopes"**
|
||||
```bash
|
||||
gh auth refresh -h github.com -s workflow,read:project,project
|
||||
brew install gh && gh auth login
|
||||
```
|
||||
|
||||
**Clone failures**
|
||||
|
|
|
|||
32
SECURITY.md
32
SECURITY.md
|
|
@ -1,32 +0,0 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| dev | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them via email to: **security@host.uk.com**
|
||||
|
||||
Include:
|
||||
- Description of the vulnerability
|
||||
- Steps to reproduce
|
||||
- Potential impact
|
||||
- Any suggested fixes (optional)
|
||||
|
||||
You should receive a response within 48 hours. If the issue is confirmed, we will:
|
||||
1. Work on a fix privately
|
||||
2. Release a patch
|
||||
3. Credit you in the release notes (unless you prefer anonymity)
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
When contributing to this repository:
|
||||
- Never commit secrets, API keys, or credentials
|
||||
- Use environment variables for sensitive configuration
|
||||
- Review dependencies for known vulnerabilities
|
||||
- Follow the principle of least privilege in scripts
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
# Template Setup Guide
|
||||
|
||||
You've created a new repo from the **core-devops** template. Follow these steps to customize it.
|
||||
|
||||
## Automated Setup
|
||||
|
||||
When you first push, the `template-bootstrap.yml` workflow will:
|
||||
- ✅ Create standard labels (agent workflow, priorities, types)
|
||||
- ✅ Enable security features (Dependabot, vulnerability alerts)
|
||||
- ✅ Create a setup checklist issue
|
||||
|
||||
## Files to Customize
|
||||
|
||||
### Required Changes
|
||||
|
||||
| File | Action |
|
||||
|------|--------|
|
||||
| `repos.yaml` | Replace with your package registry or delete if single-repo |
|
||||
| `CLAUDE.md` | Update with your project's architecture and commands |
|
||||
| `README.md` | Replace with your project description |
|
||||
| `package.json` | Update name, or delete if not using VitePress |
|
||||
|
||||
### Optional Changes
|
||||
|
||||
| File | Action |
|
||||
|------|--------|
|
||||
| `.coderabbit.yaml` | Customize review instructions for your codebase |
|
||||
| `.core/workspace.yaml` | Update active package and settings |
|
||||
| `doc/` | Replace with your documentation |
|
||||
| `scripts/` | Keep if useful, or replace with your setup scripts |
|
||||
| `Makefile` | Update targets for your workflow |
|
||||
|
||||
### Files to Delete (if not needed)
|
||||
|
||||
```bash
|
||||
# If not using VitePress docs
|
||||
rm -rf .vitepress doc package.json
|
||||
|
||||
# If not a multi-repo workspace
|
||||
rm -rf packages repos.yaml .core/workspace.yaml
|
||||
|
||||
# This file (after reading!)
|
||||
rm TEMPLATE_SETUP.md
|
||||
```
|
||||
|
||||
## Secrets to Configure
|
||||
|
||||
If using the auto-project workflow:
|
||||
```bash
|
||||
# Org-level secret (already set if in host-uk org)
|
||||
gh secret set PROJECT_TOKEN --org YOUR_ORG --visibility all
|
||||
```
|
||||
|
||||
## Branch Strategy
|
||||
|
||||
The template uses `dev` as the default branch:
|
||||
- `dev` - Development (default, PRs merge here)
|
||||
- `main` - Production releases
|
||||
|
||||
To switch to `main`-only:
|
||||
```bash
|
||||
gh repo edit --default-branch main
|
||||
```
|
||||
|
||||
## Adding to Org Projects
|
||||
|
||||
```bash
|
||||
# Add repo's issues to a project when labeled
|
||||
gh workflow run auto-project.yml
|
||||
```
|
||||
|
||||
## Verification Workflow
|
||||
|
||||
The template includes the agent verification workflow:
|
||||
```
|
||||
agent:ready → agent:wip → agent:review → verified/verify-failed
|
||||
```
|
||||
|
||||
This enforces the rule: **no agent can verify their own work**.
|
||||
|
||||
---
|
||||
|
||||
Delete this file once setup is complete:
|
||||
```bash
|
||||
rm TEMPLATE_SETUP.md && git add -A && git commit -m "chore: complete template setup"
|
||||
```
|
||||
77
TODO.md
77
TODO.md
|
|
@ -1,77 +0,0 @@
|
|||
# TODO - Session Summary 2026-02-01
|
||||
|
||||
## ✅ Completed Today
|
||||
|
||||
### Issue Auto-Labeling
|
||||
- [x] Issue templates (bug_report.yml, feature_request.yml) for core + core-devops
|
||||
- [x] Auto-label workflow detects: type, project, priority, agentic keywords
|
||||
- [x] Complexity dropdown in feature request template
|
||||
- [x] Heuristic complexity detection (checklist count, code blocks, sections, file refs, keywords)
|
||||
- [x] Retroactively labeled unlabeled issues in core repo
|
||||
- [x] Test issue #70 created and auto-labeled correctly
|
||||
|
||||
### GitHub Org Setup
|
||||
- [x] Dev branches as default (all repos)
|
||||
- [x] Labels taxonomy (agent:*, priority:*, type:*, lang:*)
|
||||
- [x] Discord webhooks (7 channels × 20 repos)
|
||||
- [x] Branch protection rules
|
||||
- [x] Org security defaults enabled
|
||||
|
||||
### CodeRabbit
|
||||
- [x] Central config: host-uk/coderabbit
|
||||
- [x] Per-repo .coderabbit.yaml (21 repos)
|
||||
- [x] review_status: false
|
||||
|
||||
### CodeQL/Security
|
||||
- [x] Enabled on all public repos
|
||||
- [x] Language-appropriate scanning
|
||||
|
||||
### GitHub Projects
|
||||
- [x] Auto-add workflow (label → project)
|
||||
- [x] PROJECT_TOKEN secret set
|
||||
|
||||
### Agent Verification Workflow
|
||||
- [x] Labels: agent:ready → agent:wip → agent:review → verified
|
||||
- [x] Self-verification blocked
|
||||
- [x] core/.github/workflows/agent-verify.yml
|
||||
|
||||
### Template Repo (core-devops)
|
||||
- [x] Bootstrap workflow for new repos
|
||||
- [x] TEMPLATE_SETUP.md guide
|
||||
|
||||
### Free Tier Integration
|
||||
- [x] Gemini, Groq, Mistral, Cohere, Cloudflare workflows
|
||||
- [x] Semgrep, Trivy, Gitleaks, OSV, Checkov
|
||||
- [x] Jules dispatch workflow
|
||||
- [x] CONTRIBUTING.md + scripts/contribute.sh
|
||||
|
||||
### Docs
|
||||
- [x] VitePress setup
|
||||
- [x] core docs sync tested
|
||||
- [x] free-tier-services.md
|
||||
|
||||
### Container Images (core-images)
|
||||
- [x] docker-compose.yml + devcontainer.json (packages/ mount)
|
||||
- [x] Dual-registry workflow: GHCR + Docker Hub (lthn/*)
|
||||
- [x] DOCKERHUB_USERNAME/TOKEN secrets (org-wide)
|
||||
- [ ] Fix Dockerfile Python build (#2 - tiktoken, tree-sitter)
|
||||
- [ ] Merge dev → main to publish images
|
||||
|
||||
### Core CLI Issues
|
||||
- [x] #50 - linuxkit double-dash flags fix
|
||||
|
||||
## 🔲 Pending (Core CLI Issues Created)
|
||||
|
||||
- [ ] #46 - docs sync ignores packages_dir
|
||||
- [ ] #47 - core qa command area
|
||||
- [ ] #48 - core security command
|
||||
- [ ] #49 - core monitor (aggregate free tier findings)
|
||||
|
||||
## 🔲 Next Steps
|
||||
|
||||
- [ ] Merge dev → main on repos to deploy docs
|
||||
- [ ] Recruit first 10 contributors
|
||||
- [ ] Rotate PROJECT_TOKEN (was shared in chat)
|
||||
- [ ] Rotate DOCKERHUB_TOKEN (was shared in chat)
|
||||
- [x] Add workflow to remaining PHP repos (8 repos)
|
||||
- [ ] Set up external OSS project scanning
|
||||
134
doc/commands.md
134
doc/commands.md
|
|
@ -1,134 +0,0 @@
|
|||
# Commands Reference
|
||||
|
||||
All `core` CLI commands available in the workspace.
|
||||
|
||||
## Workspace Commands
|
||||
|
||||
### `core health`
|
||||
|
||||
Quick status summary of all repos.
|
||||
|
||||
```bash
|
||||
core health
|
||||
# Output: 18 repos │ 2 dirty │ synced
|
||||
```
|
||||
|
||||
### `core work`
|
||||
|
||||
Full workflow: status → commit → push.
|
||||
|
||||
```bash
|
||||
core work # Interactive
|
||||
core work --status # Status table only
|
||||
```
|
||||
|
||||
### `core commit`
|
||||
|
||||
Claude-assisted commits for dirty repos.
|
||||
|
||||
```bash
|
||||
core commit # Interactive
|
||||
core commit --all # Commit all without prompting
|
||||
```
|
||||
|
||||
### `core push`
|
||||
|
||||
Push repos with unpushed commits.
|
||||
|
||||
```bash
|
||||
core push # Interactive
|
||||
core push --force # Push without confirmation
|
||||
```
|
||||
|
||||
### `core pull`
|
||||
|
||||
Pull repos that are behind.
|
||||
|
||||
```bash
|
||||
core pull # Interactive
|
||||
core pull --all # Pull all repos
|
||||
```
|
||||
|
||||
## GitHub Integration
|
||||
|
||||
### `core issues`
|
||||
|
||||
List open issues across repos.
|
||||
|
||||
```bash
|
||||
core issues # All open issues
|
||||
core issues --assignee @me # Assigned to you
|
||||
```
|
||||
|
||||
### `core reviews`
|
||||
|
||||
List PRs needing review.
|
||||
|
||||
```bash
|
||||
core reviews
|
||||
```
|
||||
|
||||
### `core ci`
|
||||
|
||||
GitHub Actions workflow status.
|
||||
|
||||
```bash
|
||||
core ci
|
||||
```
|
||||
|
||||
## Analysis
|
||||
|
||||
### `core impact`
|
||||
|
||||
Show what depends on a package.
|
||||
|
||||
```bash
|
||||
core impact core-php
|
||||
```
|
||||
|
||||
## Package Commands
|
||||
|
||||
### `core php test`
|
||||
|
||||
Run Pest tests in the active package.
|
||||
|
||||
```bash
|
||||
core php test
|
||||
core php test --filter=ClassName
|
||||
```
|
||||
|
||||
### `core php lint`
|
||||
|
||||
Run Pint linter in the active package.
|
||||
|
||||
```bash
|
||||
core php lint
|
||||
```
|
||||
|
||||
### `core php dev`
|
||||
|
||||
Start Vite dev server in the active package.
|
||||
|
||||
```bash
|
||||
core php dev
|
||||
```
|
||||
|
||||
## Setup Commands
|
||||
|
||||
### `core setup`
|
||||
|
||||
Clone repos into the workspace.
|
||||
|
||||
```bash
|
||||
core setup # Default (foundation + module)
|
||||
core setup --only foundation,module # Specific types
|
||||
```
|
||||
|
||||
### `core doctor`
|
||||
|
||||
Check environment health.
|
||||
|
||||
```bash
|
||||
core doctor # Check only
|
||||
core doctor --fix # Attempt to fix issues
|
||||
```
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
# .core/ Folder
|
||||
|
||||
The `.core/` folder provides workspace configuration and Claude Code integration.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
.core/
|
||||
├── workspace.yaml # Workspace configuration
|
||||
├── plugin/
|
||||
│ ├── plugin.json # Claude Code manifest
|
||||
│ ├── skills/ # Context-aware skills
|
||||
│ └── hooks/ # Command hooks
|
||||
└── docs/
|
||||
└── core-folder-spec.md # Full specification
|
||||
```
|
||||
|
||||
## workspace.yaml
|
||||
|
||||
Defines the active package and workspace settings.
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
|
||||
# Active package for `core php test`, etc.
|
||||
active: core-php
|
||||
|
||||
# Default package types for `core setup`
|
||||
default_only:
|
||||
- foundation
|
||||
- module
|
||||
|
||||
# Paths
|
||||
packages_dir: ./packages
|
||||
|
||||
# Settings
|
||||
settings:
|
||||
suggest_core_commands: true
|
||||
show_active_in_prompt: true
|
||||
```
|
||||
|
||||
## Changing Active Package
|
||||
|
||||
Edit `.core/workspace.yaml`:
|
||||
|
||||
```yaml
|
||||
active: core-tenant
|
||||
```
|
||||
|
||||
Then commands run from workspace root target that package:
|
||||
|
||||
```bash
|
||||
core php test # Now runs in core-tenant
|
||||
```
|
||||
|
||||
## Claude Code Plugin
|
||||
|
||||
The `plugin/` folder integrates with Claude Code:
|
||||
|
||||
### plugin.json
|
||||
|
||||
Manifest defining skills and commands.
|
||||
|
||||
### skills/
|
||||
|
||||
Markdown files providing context-aware guidance:
|
||||
|
||||
- `workspace.md` - Multi-repo navigation
|
||||
- `switch-package.md` - Package switching
|
||||
- `package-status.md` - Status checking
|
||||
|
||||
### hooks/
|
||||
|
||||
Shell scripts that run before/after commands:
|
||||
|
||||
- `prefer-core.sh` - Suggests `core` commands
|
||||
|
||||
## Full Specification
|
||||
|
||||
See `.core/docs/core-folder-spec.md` for the complete specification that packages should follow.
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
# Free Tier Compute Guide
|
||||
|
||||
This project uses distributed compute from contributors' free tier allowances. Here's how to maximize it.
|
||||
|
||||
## GitHub Actions (Microsoft)
|
||||
|
||||
**Free tier:** 2,000 minutes/month for public repos
|
||||
|
||||
When you fork this repo, CI runs on YOUR allowance, not upstream's. This includes:
|
||||
- Full test suite
|
||||
- Linting and formatting
|
||||
- Security scanning
|
||||
- AI-powered triage
|
||||
|
||||
## Gemini API (Google)
|
||||
|
||||
**Free tier:** 1,500 requests/day, 1M tokens/minute
|
||||
|
||||
### Setup
|
||||
|
||||
1. Get API key: https://aistudio.google.com/apikey
|
||||
2. Add to your fork's secrets:
|
||||
```bash
|
||||
gh secret set GEMINI_API_KEY --repo YOUR_USER/YOUR_FORK
|
||||
```
|
||||
|
||||
The `ai-worker.yml` workflow will use your Gemini allowance for:
|
||||
- Code review
|
||||
- Bug detection
|
||||
- Security analysis
|
||||
|
||||
## Jules / Copilot (GitHub)
|
||||
|
||||
**Free tier:** Available with GitHub Copilot (free for OSS contributors)
|
||||
|
||||
### Trigger Jules
|
||||
|
||||
Comment on any issue:
|
||||
```
|
||||
@jules fix the authentication bug in login.php
|
||||
@jules add unit tests for the User model
|
||||
@jules refactor to use async/await
|
||||
```
|
||||
|
||||
Jules will:
|
||||
1. Analyze the issue
|
||||
2. Write code to fix it
|
||||
3. Create a PR on your fork
|
||||
4. Uses YOUR Copilot allowance
|
||||
|
||||
### Get Copilot Free
|
||||
|
||||
- Open source contributors: https://github.com/settings/copilot
|
||||
- Students: GitHub Education pack
|
||||
- Verified OSS maintainers: Free Copilot Pro
|
||||
|
||||
## CodeRabbit
|
||||
|
||||
**Free tier:** Unlimited for public repos
|
||||
|
||||
Already configured via `.coderabbit.yaml`. Reviews run automatically on PRs.
|
||||
|
||||
## Compute Distribution Model
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ CONTRIBUTOR FORK │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ GitHub │ │ Gemini │ │
|
||||
│ │ Actions │ │ 2.0 Flash │ │
|
||||
│ │ FREE │ │ FREE │ │
|
||||
│ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Jules/ │ │ CodeRabbit │ │
|
||||
│ │ Copilot │ │ FREE │ │
|
||||
│ │ FREE* │ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
│ * With Copilot Pro (free for OSS) │
|
||||
└────────────────────────────────────────────┘
|
||||
│
|
||||
│ PR (already analyzed)
|
||||
▼
|
||||
┌────────────────────────────────────────────┐
|
||||
│ UPSTREAM REPO │
|
||||
│ │
|
||||
│ Just verify fork CI passed ✓ │
|
||||
│ Cost: ~$0.001 per PR │
|
||||
└────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## For Donor Fleet Members
|
||||
|
||||
If you want to contribute compute without coding:
|
||||
|
||||
1. Fork the repo
|
||||
2. Set up your API keys (Gemini, etc.)
|
||||
3. Keep Actions enabled
|
||||
4. Pick up `agent:review` tasks to verify others' work
|
||||
|
||||
Your free tier becomes part of the distributed compute network!
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
# Free Tier Services Integration
|
||||
|
||||
> **Host UK CIC** is a UK Community Interest Company. Our assets are legally locked for community benefit - we can't extract value for shareholders. This page documents how we aggregate free compute to benefit the open source commons.
|
||||
|
||||
## The Model
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 100 CONTRIBUTORS │
|
||||
│ │
|
||||
│ Each contributes their FREE tier allowances: │
|
||||
│ • GitHub Actions: 2000 min/month │
|
||||
│ • Gemini: 1500 req/day │
|
||||
│ • Groq: 14,400 req/day │
|
||||
│ • Copilot: Free for OSS │
|
||||
│ │
|
||||
│ Total daily capacity: │
|
||||
│ • 150,000 Gemini requests │
|
||||
│ • 1,440,000 Groq requests │
|
||||
│ • 6,666 GitHub Actions hours │
|
||||
│ • Unlimited security scans │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ core monitor │
|
||||
│ │
|
||||
│ Aggregates findings → Creates tasks → Routes to agents │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────┴───────────────┐
|
||||
▼ ▼
|
||||
┌─────────────────────────┐ ┌─────────────────────────────────┐
|
||||
│ HOST UK PACKAGES │ │ UNFUNDED OSS PROJECTS │
|
||||
│ │ │ │
|
||||
│ Our tools, modules │ │ Popular packages with no │
|
||||
│ │ │ security budget - we find │
|
||||
│ │ │ and fix vulns, submit PRs │
|
||||
└─────────────────────────┘ └─────────────────────────────────┘
|
||||
```
|
||||
|
||||
**The LLMs learned from open source. We're giving back.**
|
||||
|
||||
---
|
||||
|
||||
## AI/LLM APIs (Contributor Keys)
|
||||
|
||||
| Service | Free Tier | Speed | Best For |
|
||||
|---------|-----------|-------|----------|
|
||||
| **Groq** | 14,400 req/day | ⚡ Fastest | Quick triage, bulk analysis |
|
||||
| **Gemini 2.0** | 1500 req/day | Fast | Code review, deep analysis |
|
||||
| **Mistral** | 1M tokens/month | Fast | Code generation |
|
||||
| **Cohere** | 1000 req/month | Medium | Classification, embeddings |
|
||||
| **Cloudflare AI** | 10K neurons/day | Edge | Low latency |
|
||||
| **Together.ai** | $5 credit | Fast | Multi-model |
|
||||
| **Fireworks.ai** | 600 req/min | ⚡ Fast | High throughput |
|
||||
| **Cerebras** | Free tier | ⚡⚡ Fastest | Bulk inference |
|
||||
|
||||
### Setup (2 minutes)
|
||||
|
||||
```bash
|
||||
# In your fork
|
||||
gh secret set GEMINI_API_KEY # https://aistudio.google.com/apikey
|
||||
gh secret set GROQ_API_KEY # https://console.groq.com/keys
|
||||
gh secret set MISTRAL_API_KEY # https://console.mistral.ai/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Scanners (No Keys Needed)
|
||||
|
||||
All free, unlimited, run automatically:
|
||||
|
||||
| Scanner | Finds | Output |
|
||||
|---------|-------|--------|
|
||||
| **Semgrep** | SAST vulns, code patterns | SARIF → GitHub Security |
|
||||
| **Trivy** | Container vulns, IaC issues | SARIF → GitHub Security |
|
||||
| **Gitleaks** | Leaked secrets, API keys | SARIF → GitHub Security |
|
||||
| **OSV-Scanner** | Known CVEs (Google DB) | SARIF → GitHub Security |
|
||||
| **Checkov** | IaC misconfigs | SARIF → GitHub Security |
|
||||
| **CodeQL** | Deep semantic analysis | Native GitHub |
|
||||
| **Dependabot** | Outdated deps | Native GitHub |
|
||||
|
||||
---
|
||||
|
||||
## Code Analysis Apps (Free for Public Repos)
|
||||
|
||||
Install these on your fork for extra coverage:
|
||||
|
||||
| App | Install | Provides |
|
||||
|-----|---------|----------|
|
||||
| **Snyk** | [Install](https://github.com/apps/snyk-io) | Deps + code vulns |
|
||||
| **SonarCloud** | [Install](https://github.com/apps/sonarcloud) | Code quality |
|
||||
| **CodeClimate** | [Install](https://github.com/apps/codeclimate) | Maintainability |
|
||||
| **DeepSource** | [Install](https://github.com/apps/deepsource-io) | Autofix suggestions |
|
||||
| **Codacy** | [Install](https://github.com/apps/codacy-production) | Multi-language |
|
||||
| **Socket.dev** | [Install](https://github.com/apps/socket-security) | Supply chain |
|
||||
| **GitGuardian** | [Install](https://github.com/apps/gitguardian) | Secret detection |
|
||||
| **Aikido** | [Install](https://github.com/apps/aikido-security) | Full security suite |
|
||||
| **Trunk.io** | [Install](https://github.com/apps/trunk-io) | Meta-linter (50+ tools) |
|
||||
|
||||
---
|
||||
|
||||
## AI Code Assistants (Free Tiers)
|
||||
|
||||
| Service | Free Access | Trigger |
|
||||
|---------|-------------|---------|
|
||||
| **Jules/Copilot** | OSS maintainers, students | `@jules fix this bug` |
|
||||
| **Codeium** | Free forever | IDE extension |
|
||||
| **Cody** | Free tier | IDE extension |
|
||||
| **Amazon Q** | Free tier | IDE/CLI |
|
||||
| **Continue.dev** | Free, open source | IDE extension |
|
||||
|
||||
---
|
||||
|
||||
## CI/CD Free Tiers
|
||||
|
||||
| Service | Free Allowance | Notes |
|
||||
|---------|----------------|-------|
|
||||
| **GitHub Actions** | 2000 min/month | Per user, public repos |
|
||||
| **CircleCI** | 6000 min/month | Good for heavy builds |
|
||||
| **GitLab CI** | 400 min/month | Alternative to GH |
|
||||
| **Semaphore** | 1300 min/month | Fast builds |
|
||||
| **Buildkite** | Free for OSS | Self-hosted option |
|
||||
|
||||
---
|
||||
|
||||
## Who Pays For All This?
|
||||
|
||||
| Provider | Why Free? |
|
||||
|----------|-----------|
|
||||
| **Microsoft** | GitHub market dominance, AI training data |
|
||||
| **Google** | Gemini adoption, developer mindshare |
|
||||
| **Groq** | Hardware showcase, market entry |
|
||||
| **Others** | Developer ecosystem, future enterprise sales |
|
||||
|
||||
**They need OSS developers. We need compute. Fair trade.**
|
||||
|
||||
---
|
||||
|
||||
## Joining the Network
|
||||
|
||||
```bash
|
||||
# Fork and setup (5 minutes)
|
||||
gh repo fork host-uk/core-devops --clone
|
||||
cd core-devops
|
||||
./scripts/contribute.sh
|
||||
```
|
||||
|
||||
Your unused free tier becomes part of a collective resource that:
|
||||
1. Secures Host UK packages
|
||||
2. Fixes vulnerabilities in unfunded OSS
|
||||
3. Gives back to the projects that trained the AIs
|
||||
|
||||
**Cost: $0. Impact: Massive.**
|
||||
|
||||
---
|
||||
|
||||
*Host UK CIC - Ethical infrastructure for the open source commons*
|
||||
56
doc/index.md
56
doc/index.md
|
|
@ -1,56 +0,0 @@
|
|||
---
|
||||
layout: home
|
||||
hero:
|
||||
name: "core-devops"
|
||||
text: "Developer Workspace"
|
||||
tagline: Unified entry point for Host UK development
|
||||
actions:
|
||||
- theme: brand
|
||||
text: Quick Start
|
||||
link: /quick-start
|
||||
- theme: alt
|
||||
text: View on GitHub
|
||||
link: https://github.com/host-uk/core-devops
|
||||
features:
|
||||
- title: One Command Setup
|
||||
details: Clone and run `make setup` to get a complete development environment with all dependencies.
|
||||
- title: Multi-Repo Management
|
||||
details: Manage 18+ Laravel packages from a single workspace using the `core` CLI.
|
||||
- title: Agentic-First
|
||||
details: Designed for AI-assisted development with structured issues and Claude Code integration.
|
||||
---
|
||||
|
||||
# Host UK DevOps
|
||||
|
||||
The developer workspace orchestrator for Host UK - a federated monorepo containing 18 Laravel packages.
|
||||
|
||||
## What's Included
|
||||
|
||||
| Component | Purpose |
|
||||
|-----------|---------|
|
||||
| `repos.yaml` | Package registry with dependencies |
|
||||
| `.core/` | Workspace configuration and Claude Code plugin |
|
||||
| `scripts/` | Cross-platform setup scripts |
|
||||
| `Makefile` | Setup orchestration |
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
git clone git@github.com:host-uk/core-devops.git && cd core-devops && make setup
|
||||
```
|
||||
|
||||
## Core CLI
|
||||
|
||||
The workspace is managed by the `core` CLI:
|
||||
|
||||
```bash
|
||||
core health # Status summary
|
||||
core work # Commit and push workflow
|
||||
core issues # GitHub issues across repos
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Quick Start Guide](/quick-start) - Get up and running
|
||||
- [Commands Reference](/commands) - All available commands
|
||||
- [.core/ Configuration](/core-folder) - Workspace configuration
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
# Package Types
|
||||
|
||||
Host UK packages are organised into types based on their purpose.
|
||||
|
||||
## Foundation
|
||||
|
||||
Base framework with no dependencies.
|
||||
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| `core-php` | Event-driven modules, lifecycle management |
|
||||
|
||||
## Modules
|
||||
|
||||
Infrastructure services that extend the foundation.
|
||||
|
||||
| Package | Description | Dependencies |
|
||||
|---------|-------------|--------------|
|
||||
| `core-tenant` | Multi-tenancy, workspaces, users | core-php |
|
||||
| `core-admin` | Admin panel, Livewire, Flux UI | core-php |
|
||||
| `core-api` | REST API, rate limiting, webhooks | core-php, core-tenant |
|
||||
| `core-mcp` | Model Context Protocol server | core-php |
|
||||
| `core-agentic` | AI agent orchestration | core-php, core-tenant, core-mcp |
|
||||
| `core-commerce` | Billing, subscriptions, Stripe | core-php, core-tenant |
|
||||
| `core-content` | CMS, pages, blog posts | core-php, core-tenant |
|
||||
| `core-tools` | Developer utilities | core-php |
|
||||
| `core-uptelligence` | Server monitoring | core-php, core-tenant |
|
||||
| `core-developer` | Developer portal, OAuth | core-php, core-tenant, core-api |
|
||||
|
||||
## Products
|
||||
|
||||
User-facing applications.
|
||||
|
||||
| Package | Description | Domain |
|
||||
|---------|-------------|--------|
|
||||
| `core-bio` | Link-in-bio pages | bio.host.uk.com |
|
||||
| `core-social` | Social media scheduling | social.host.uk.com |
|
||||
| `core-analytics` | Privacy-first analytics | analytics.host.uk.com |
|
||||
| `core-notify` | Push notifications | notify.host.uk.com |
|
||||
| `core-trust` | Social proof widgets | trust.host.uk.com |
|
||||
| `core-support` | Helpdesk, ticketing | - |
|
||||
|
||||
## Templates
|
||||
|
||||
Starter templates for new projects.
|
||||
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| `core-template` | Starter template |
|
||||
|
||||
## Meta
|
||||
|
||||
Workspace and tooling repos.
|
||||
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| `core-devops` | This workspace |
|
||||
| `core` | Go CLI and framework |
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
# Quick Start
|
||||
|
||||
Get a complete Host UK development environment in under 5 minutes.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Git
|
||||
- GitHub CLI (`gh`)
|
||||
- SSH key configured with GitHub
|
||||
|
||||
## Installation
|
||||
|
||||
### macOS / Linux
|
||||
|
||||
```bash
|
||||
git clone git@github.com:host-uk/core-devops.git
|
||||
cd core-devops
|
||||
make setup
|
||||
```
|
||||
|
||||
### Windows (PowerShell as Admin)
|
||||
|
||||
```powershell
|
||||
git clone git@github.com:host-uk/core-devops.git
|
||||
cd core-devops
|
||||
.\scripts\install-deps.ps1
|
||||
.\scripts\install-core.ps1
|
||||
core setup
|
||||
```
|
||||
|
||||
## What Happens
|
||||
|
||||
`make setup` does three things:
|
||||
|
||||
1. **Installs dependencies** - PHP 8.3+, Composer, Node 20+, pnpm, GitHub CLI
|
||||
2. **Installs the `core` CLI** - Multi-repo management tool
|
||||
3. **Clones all packages** - Into `packages/` (foundation and modules by default)
|
||||
|
||||
## Verify Installation
|
||||
|
||||
```bash
|
||||
core doctor
|
||||
```
|
||||
|
||||
This checks that all required tools are installed and configured.
|
||||
|
||||
## Next Steps
|
||||
|
||||
```bash
|
||||
# See workspace status
|
||||
core health
|
||||
|
||||
# Run tests in the active package
|
||||
core php test
|
||||
|
||||
# Work on a specific package
|
||||
cd packages/core-php
|
||||
composer test
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See the [Troubleshooting Guide](/troubleshooting) for common issues.
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
# repos.yaml
|
||||
|
||||
The package registry defining all repositories in the workspace.
|
||||
|
||||
## Format
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
org: host-uk
|
||||
base_path: ./packages
|
||||
|
||||
repos:
|
||||
core-php:
|
||||
type: foundation
|
||||
description: Core PHP framework
|
||||
docs: true
|
||||
ci: github-actions
|
||||
|
||||
core-tenant:
|
||||
type: module
|
||||
depends_on: [core-php]
|
||||
description: Multi-tenancy, workspaces
|
||||
|
||||
defaults:
|
||||
ci: github-actions
|
||||
license: EUPL-1.2
|
||||
branch: main
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
### Repository Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `type` | string | Package type (see below) |
|
||||
| `depends_on` | array | Dependencies on other packages |
|
||||
| `description` | string | Short description |
|
||||
| `docs` | boolean | Has documentation |
|
||||
| `ci` | string | CI system (github-actions) |
|
||||
| `domain` | string | Production domain (products only) |
|
||||
| `clone` | boolean | Whether to clone (default: true) |
|
||||
|
||||
### Package Types
|
||||
|
||||
| Type | Purpose | Examples |
|
||||
|------|---------|----------|
|
||||
| `foundation` | Base framework, no dependencies | core-php |
|
||||
| `module` | Infrastructure services | core-tenant, core-admin |
|
||||
| `product` | User-facing applications | core-bio, core-social |
|
||||
| `template` | Starter templates | core-template |
|
||||
| `meta` | Workspace repos | core-devops |
|
||||
|
||||
## Using with CLI
|
||||
|
||||
```bash
|
||||
# Clone specific types
|
||||
core setup --only foundation,module
|
||||
|
||||
# Show what depends on a package
|
||||
core impact core-php
|
||||
```
|
||||
|
||||
## Dependency Graph
|
||||
|
||||
The `depends_on` field creates a dependency graph:
|
||||
|
||||
```
|
||||
core-php (foundation)
|
||||
├── core-tenant
|
||||
├── core-admin
|
||||
├── core-api
|
||||
│ └── core-developer
|
||||
└── core-mcp
|
||||
└── core-agentic
|
||||
```
|
||||
|
||||
Products depend on both `core-php` and `core-tenant`.
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
# Troubleshooting
|
||||
|
||||
Common issues and solutions.
|
||||
|
||||
## Installation Issues
|
||||
|
||||
### "core: command not found"
|
||||
|
||||
The Core CLI isn't installed or not in PATH.
|
||||
|
||||
```bash
|
||||
make install-core
|
||||
```
|
||||
|
||||
Or manually:
|
||||
|
||||
```bash
|
||||
./scripts/install-core.sh
|
||||
```
|
||||
|
||||
### "gh: command not found"
|
||||
|
||||
Install GitHub CLI:
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
brew install gh
|
||||
|
||||
# Then authenticate
|
||||
gh auth login -h github.com -p https -s workflow,repo,read:org,read:project,project
|
||||
```
|
||||
|
||||
### Clone failures
|
||||
|
||||
Check your SSH keys:
|
||||
|
||||
```bash
|
||||
ssh -T git@github.com
|
||||
```
|
||||
|
||||
If using HTTPS:
|
||||
|
||||
```bash
|
||||
gh auth setup-git
|
||||
```
|
||||
|
||||
## GitHub Issues
|
||||
|
||||
### "refusing to allow an OAuth App to create or update workflow"
|
||||
|
||||
Missing `workflow` scope:
|
||||
|
||||
```bash
|
||||
gh auth refresh -h github.com -s workflow
|
||||
```
|
||||
|
||||
### "missing required scopes [read:project]"
|
||||
|
||||
Missing project scope:
|
||||
|
||||
```bash
|
||||
gh auth refresh -h github.com -s read:project,project
|
||||
```
|
||||
|
||||
## Workspace Issues
|
||||
|
||||
### Tests failing in wrong package
|
||||
|
||||
Check the active package in `.core/workspace.yaml`:
|
||||
|
||||
```yaml
|
||||
active: core-php # Should match the package you're testing
|
||||
```
|
||||
|
||||
### Packages not found
|
||||
|
||||
Run setup to clone packages:
|
||||
|
||||
```bash
|
||||
core setup
|
||||
```
|
||||
|
||||
Or clone specific types:
|
||||
|
||||
```bash
|
||||
core setup --only foundation,module
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
1. Run `core doctor` to check environment
|
||||
2. Check GitHub issues: https://github.com/host-uk/core-devops/issues
|
||||
3. Ask in Discord: https://discord.gg/host-uk
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
# Core Developer Environment
|
||||
# Mounts packages/ as /workspace in the container
|
||||
|
||||
services:
|
||||
dev:
|
||||
image: ghcr.io/host-uk/core-images:developer
|
||||
container_name: core-dev
|
||||
hostname: core-dev
|
||||
stdin_open: true
|
||||
tty: true
|
||||
volumes:
|
||||
# Mount packages directory as workspace
|
||||
- ./packages:/workspace
|
||||
# Persist home directory configs
|
||||
- dev-home:/root
|
||||
# SSH keys for git operations
|
||||
- ~/.ssh:/root/.ssh:ro
|
||||
# Git config
|
||||
- ~/.gitconfig:/root/.gitconfig:ro
|
||||
environment:
|
||||
- TERM=xterm-256color
|
||||
- EDITOR=nvim
|
||||
working_dir: /workspace
|
||||
# Keep container running
|
||||
command: ["/bin/zsh"]
|
||||
|
||||
volumes:
|
||||
dev-home:
|
||||
name: core-dev-home
|
||||
15
package.json
15
package.json
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "@host-uk/devops-docs",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"docs:dev": "vitepress dev",
|
||||
"docs:build": "vitepress build",
|
||||
"docs:preview": "vitepress preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vitepress": "^1.5.0",
|
||||
"vue": "^3.5.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -123,13 +123,6 @@ repos:
|
|||
description: Starter template for new projects
|
||||
docs: false
|
||||
|
||||
# Claude Code plugin
|
||||
core-claude:
|
||||
type: meta
|
||||
depends_on: []
|
||||
description: Claude Code plugin for Host UK monorepo
|
||||
docs: false
|
||||
|
||||
# This repo (meta)
|
||||
core-devops:
|
||||
type: meta
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
# Clone all Host UK repos (Windows alternative to `core setup`)
|
||||
# Run: .\scripts\clone-repos.ps1
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$repos = @(
|
||||
"core-php",
|
||||
"core-tenant",
|
||||
"core-admin",
|
||||
"core-api",
|
||||
"core-mcp",
|
||||
"core-agentic",
|
||||
"core-bio",
|
||||
"core-social",
|
||||
"core-analytics",
|
||||
"core-notify",
|
||||
"core-trust",
|
||||
"core-support",
|
||||
"core-commerce",
|
||||
"core-content",
|
||||
"core-tools",
|
||||
"core-uptelligence",
|
||||
"core-developer",
|
||||
"core-template"
|
||||
)
|
||||
|
||||
$packagesDir = Join-Path $PSScriptRoot "..\packages"
|
||||
|
||||
Write-Host "[INFO] Cloning repos to $packagesDir" -ForegroundColor Green
|
||||
|
||||
foreach ($repo in $repos) {
|
||||
$repoPath = Join-Path $packagesDir $repo
|
||||
|
||||
if (Test-Path $repoPath) {
|
||||
Write-Host "[SKIP] $repo already exists" -ForegroundColor Yellow
|
||||
continue
|
||||
}
|
||||
|
||||
Write-Host "[CLONE] $repo..." -ForegroundColor Cyan
|
||||
gh repo clone "host-uk/$repo" $repoPath
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[WARN] Failed to clone $repo" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "[DONE] Repos cloned. Run 'composer install' in each package." -ForegroundColor Green
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Host UK CIC - Contributor Setup
|
||||
# One command to join the distributed compute network
|
||||
|
||||
set -e
|
||||
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ Host UK CIC - Contributor Setup ║"
|
||||
echo "║ ║"
|
||||
echo "║ Your free tier allowances will help fix unfunded OSS ║"
|
||||
echo "║ projects. Cost to you: \$0. Impact: Massive. ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
# Check if this is a fork
|
||||
REMOTE_URL=$(git remote get-url origin 2>/dev/null || echo "")
|
||||
if [[ "$REMOTE_URL" == *"host-uk/core-devops"* ]]; then
|
||||
echo "⚠️ This is the upstream repo, not your fork."
|
||||
echo ""
|
||||
echo "Run this instead:"
|
||||
echo " gh repo fork host-uk/core-devops --clone"
|
||||
echo " cd core-devops"
|
||||
echo " ./scripts/contribute.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Fork detected"
|
||||
echo ""
|
||||
|
||||
# Check gh auth
|
||||
if ! gh auth status &>/dev/null; then
|
||||
echo "⚠️ GitHub CLI not authenticated"
|
||||
echo "Run: gh auth login"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ GitHub CLI authenticated"
|
||||
echo ""
|
||||
|
||||
# Setup secrets
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo " OPTIONAL: Add API keys for AI-powered analysis"
|
||||
echo " (Skip any you don't want - security scans work without them)"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
read -p "Add Gemini API key? (1500 req/day free) [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Get key at: https://aistudio.google.com/apikey"
|
||||
gh secret set GEMINI_API_KEY
|
||||
fi
|
||||
|
||||
read -p "Add Groq API key? (14,400 req/day free) [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Get key at: https://console.groq.com/keys"
|
||||
gh secret set GROQ_API_KEY
|
||||
fi
|
||||
|
||||
read -p "Add Mistral API key? (1M tokens/month free) [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Get key at: https://console.mistral.ai/"
|
||||
gh secret set MISTRAL_API_KEY
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo " ✅ SETUP COMPLETE"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Your fork is now part of the distributed compute network!"
|
||||
echo ""
|
||||
echo "What happens now:"
|
||||
echo " • Security scans run automatically (Semgrep, Trivy, Gitleaks)"
|
||||
echo " • AI analysis runs on your PRs (using your free tier)"
|
||||
echo " • You can verify others' work: core issues --label agent:review"
|
||||
echo ""
|
||||
echo "The compute you contribute helps fix security issues in"
|
||||
echo "unfunded open source projects. Thank you! 🙏"
|
||||
echo ""
|
||||
echo "Questions? https://discord.gg/host-uk"
|
||||
|
|
@ -27,25 +27,9 @@ if ($PSVersionTable.PSVersion.Major -lt 4) {
|
|||
}
|
||||
|
||||
$Repo = "host-uk/core"
|
||||
$Version = "v0.1.0" # Pinned version - update when releasing new versions
|
||||
$MinDiskSpaceMB = 100 # Minimum required disk space in MB
|
||||
|
||||
# Resolve latest release version from GitHub API
|
||||
function Get-LatestVersion {
|
||||
try {
|
||||
if (Test-Command gh) {
|
||||
$version = gh release view --repo $Repo --json tagName -q '.tagName' 2>$null
|
||||
if ($version) { return $version }
|
||||
}
|
||||
|
||||
# Fallback to GitHub API
|
||||
$response = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases/latest" -UseBasicParsing
|
||||
if ($response.tag_name) { return $response.tag_name }
|
||||
} catch {
|
||||
Write-Warn "Could not determine latest version, using default branch"
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
function Write-Info { Write-Host "[INFO] $args" -ForegroundColor Green }
|
||||
function Write-Warn { Write-Host "[WARN] $args" -ForegroundColor Yellow }
|
||||
function Write-Err { Write-Host "[ERROR] $args" -ForegroundColor Red; exit 1 }
|
||||
|
|
@ -160,7 +144,7 @@ function New-SecureDirectory {
|
|||
# Check parent directory for symlinks first
|
||||
$parent = Split-Path $Path -Parent
|
||||
if ($parent -and (Test-Path $parent)) {
|
||||
$null = Test-SecureDirectory -Path $parent
|
||||
Test-SecureDirectory -Path $parent
|
||||
}
|
||||
|
||||
# Create directory
|
||||
|
|
@ -169,7 +153,7 @@ function New-SecureDirectory {
|
|||
}
|
||||
|
||||
# Immediately verify it's not a symlink (minimize TOCTOU window)
|
||||
$null = Test-SecureDirectory -Path $Path
|
||||
Test-SecureDirectory -Path $Path
|
||||
|
||||
return $Path
|
||||
}
|
||||
|
|
@ -197,12 +181,10 @@ function Set-SecureDirectoryAcl {
|
|||
|
||||
# Add full control for current user only
|
||||
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
|
||||
# Pre-calculate flags to avoid -bor compatibility issues across PowerShell versions
|
||||
$inheritFlags = [System.Security.AccessControl.InheritanceFlags]([int][System.Security.AccessControl.InheritanceFlags]::ContainerInherit + [int][System.Security.AccessControl.InheritanceFlags]::ObjectInherit)
|
||||
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
||||
$currentUser,
|
||||
[System.Security.AccessControl.FileSystemRights]::FullControl,
|
||||
$inheritFlags,
|
||||
[System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit,
|
||||
[System.Security.AccessControl.PropagationFlags]::None,
|
||||
[System.Security.AccessControl.AccessControlType]::Allow
|
||||
)
|
||||
|
|
@ -229,18 +211,18 @@ function Set-SecureDirectoryAcl {
|
|||
# Download pre-built binary with integrity verification
|
||||
function Download-Binary {
|
||||
$arch = if ([Environment]::Is64BitOperatingSystem) { "amd64" } else { "386" }
|
||||
$binaryUrl = "https://github.com/$Repo/releases/latest/download/core-windows-$arch.exe"
|
||||
$checksumUrl = "https://github.com/$Repo/releases/latest/download/checksums.txt"
|
||||
$binaryUrl = "https://github.com/$Repo/releases/download/$Version/core-windows-$arch.exe"
|
||||
$checksumUrl = "https://github.com/$Repo/releases/download/$Version/checksums.txt"
|
||||
|
||||
Write-Info "Attempting to download pre-built binary..."
|
||||
Write-Info "Attempting to download pre-built binary (version $Version)..."
|
||||
Write-Info "URL: $binaryUrl"
|
||||
|
||||
# Track temp file for cleanup
|
||||
$tempExe = $null
|
||||
|
||||
try {
|
||||
# Create and verify install directory (suppress output to avoid polluting return value)
|
||||
$null = New-SecureDirectory -Path $InstallDir
|
||||
# Create and verify install directory
|
||||
New-SecureDirectory -Path $InstallDir
|
||||
|
||||
# Use a temp file in the same directory (same filesystem for atomic move)
|
||||
$tempExe = Join-Path $InstallDir "core.exe.tmp.$([System.Guid]::NewGuid().ToString('N').Substring(0,8))"
|
||||
|
|
@ -270,7 +252,7 @@ function Download-Binary {
|
|||
Test-FileHash -FilePath $tempExe -ExpectedHash $expectedHash
|
||||
|
||||
# Re-verify directory hasn't been replaced with symlink (reduce TOCTOU window)
|
||||
$null = Test-SecureDirectory -Path $InstallDir
|
||||
Test-SecureDirectory -Path $InstallDir
|
||||
|
||||
# Atomic move to final location (same filesystem)
|
||||
$finalPath = Join-Path $InstallDir "core.exe"
|
||||
|
|
@ -315,19 +297,13 @@ function Test-GitTagSignature {
|
|||
Push-Location $RepoPath
|
||||
try {
|
||||
# Attempt to verify the tag signature
|
||||
# Use $ErrorActionPreference temporarily to prevent stderr from throwing
|
||||
$oldErrorAction = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
$result = git tag -v $Tag 2>&1 | Out-String
|
||||
$exitCode = $LASTEXITCODE
|
||||
$ErrorActionPreference = $oldErrorAction
|
||||
|
||||
if ($exitCode -eq 0) {
|
||||
$result = git tag -v $Tag 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Info "GPG signature verified for tag $Tag"
|
||||
return $true
|
||||
} else {
|
||||
# Check if tag is unsigned vs signature invalid
|
||||
if ($result -match "no signature found" -or $result -match "cannot verify a non-tag") {
|
||||
if ($result -match "error: no signature found") {
|
||||
Write-Warn "Tag $Tag is not signed - continuing without signature verification"
|
||||
return $true
|
||||
} else {
|
||||
|
|
@ -350,72 +326,37 @@ function Build-FromSource {
|
|||
|
||||
# Create secure temp directory with restrictive ACL
|
||||
$tmpdir = Join-Path ([System.IO.Path]::GetTempPath()) "core-build-$([System.Guid]::NewGuid().ToString('N'))"
|
||||
$null = New-SecureDirectory -Path $tmpdir
|
||||
New-SecureDirectory -Path $tmpdir
|
||||
|
||||
# ACL is REQUIRED for temp build directories (security critical)
|
||||
$null = Set-SecureDirectoryAcl -Path $tmpdir -Required
|
||||
Set-SecureDirectoryAcl -Path $tmpdir -Required
|
||||
|
||||
try {
|
||||
# Resolve latest version for reproducible builds
|
||||
$version = Get-LatestVersion
|
||||
if ($version) {
|
||||
Write-Info "Resolved latest version: $version"
|
||||
} else {
|
||||
Write-Warn "Building from default branch (version unknown)"
|
||||
}
|
||||
|
||||
Write-Info "Cloning $Repo..."
|
||||
Write-Info "Cloning $Repo (version $Version)..."
|
||||
$cloneDir = Join-Path $tmpdir "Core"
|
||||
|
||||
# Clone specific version if available, otherwise default branch
|
||||
if ($version) {
|
||||
git clone --depth 1 --branch $version "https://github.com/$Repo.git" $cloneDir
|
||||
} else {
|
||||
git clone --depth 1 "https://github.com/$Repo.git" $cloneDir
|
||||
}
|
||||
# Clone specific tag for reproducibility
|
||||
git clone --depth 1 --branch $Version "https://github.com/$Repo.git" $cloneDir
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Err "Failed to clone repository"
|
||||
Write-Err "Failed to clone repository at version $Version"
|
||||
}
|
||||
|
||||
# Verify GPG signature on tag (if available)
|
||||
Test-GitTagSignature -RepoPath $cloneDir -Tag $Version
|
||||
|
||||
Write-Info "Building core CLI..."
|
||||
Push-Location $cloneDir
|
||||
try {
|
||||
# Explicitly set GOOS/GOARCH to ensure Windows build
|
||||
$env:GOOS = "windows"
|
||||
$env:GOARCH = "amd64"
|
||||
|
||||
$oldErrorAction = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
$buildOutput = go build -o core.exe . 2>&1 | Out-String
|
||||
$buildExitCode = $LASTEXITCODE
|
||||
$ErrorActionPreference = $oldErrorAction
|
||||
|
||||
if ($buildExitCode -ne 0) {
|
||||
# Check for Windows-specific build issues
|
||||
if ($buildOutput -match "Setpgid|Getpgid|syscall\.Kill|undefined.*syscall") {
|
||||
Write-Warn "Build failed: core CLI uses Unix-specific syscalls not available on Windows."
|
||||
Write-Warn ""
|
||||
Write-Warn "Options:"
|
||||
Write-Warn " 1. Wait for pre-built Windows binaries in GitHub releases"
|
||||
Write-Warn " 2. Use WSL (Windows Subsystem for Linux) for development"
|
||||
Write-Warn " 3. Work directly with composer in packages/ (core CLI is optional)"
|
||||
Write-Warn ""
|
||||
Write-Warn "For PHP development, you can use composer directly:"
|
||||
Write-Warn " cd packages/core-php && composer test"
|
||||
Write-Host ""
|
||||
# Don't use Write-Err here - exit gracefully
|
||||
exit 0
|
||||
} else {
|
||||
Write-Host $buildOutput
|
||||
go build -o core.exe .
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Err "Go build failed"
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
# Create and verify install directory
|
||||
$null = New-SecureDirectory -Path $InstallDir
|
||||
New-SecureDirectory -Path $InstallDir
|
||||
|
||||
# Move built binary to install location
|
||||
Move-Item (Join-Path $cloneDir "core.exe") (Join-Path $InstallDir "core.exe") -Force
|
||||
|
|
@ -483,10 +424,10 @@ function Verify {
|
|||
|
||||
# Main
|
||||
function Main {
|
||||
Write-Info "Installing Core CLI..."
|
||||
Write-Info "Installing Core CLI (version $Version)..."
|
||||
|
||||
# Check disk space before starting
|
||||
$null = Test-DiskSpace -Path $InstallDir
|
||||
Test-DiskSpace -Path $InstallDir
|
||||
|
||||
# Try download first, fallback to build
|
||||
if (-not (Download-Binary)) {
|
||||
|
|
|
|||
|
|
@ -21,24 +21,10 @@ set -e
|
|||
# - No TLS certificate pinning (relies on system CA store)
|
||||
|
||||
REPO="host-uk/core"
|
||||
VERSION="${CORE_VERSION:-latest}" # Use latest release, or set CORE_VERSION=dev for dev builds
|
||||
VERSION="v0.1.0" # Pinned version - update when releasing new versions
|
||||
INSTALL_DIR="${INSTALL_DIR:-$HOME/.local/bin}"
|
||||
BUILD_FROM_SOURCE="${BUILD_FROM_SOURCE:-auto}"
|
||||
|
||||
# Resolve "latest" to actual release tag
|
||||
resolve_version() {
|
||||
if [[ "$VERSION" == "latest" ]]; then
|
||||
if has gh; then
|
||||
VERSION=$(gh release view --repo "$REPO" --json tagName -q '.tagName' 2>/dev/null) || VERSION="dev"
|
||||
elif has curl; then
|
||||
VERSION=$(curl -fsSL "https://api.github.com/repos/$REPO/releases/latest" 2>/dev/null | grep '"tag_name"' | head -1 | cut -d'"' -f4) || VERSION="dev"
|
||||
else
|
||||
VERSION="dev"
|
||||
fi
|
||||
info "Resolved latest version: $VERSION"
|
||||
fi
|
||||
}
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
|
|
@ -89,8 +75,7 @@ verify_hash() {
|
|||
|
||||
actual_hash=$(compute_sha256 "$file")
|
||||
|
||||
# Case-insensitive compare (bash 3 compatible)
|
||||
if [[ "$(echo "$actual_hash" | tr '[:upper:]' '[:lower:]')" != "$(echo "$expected_hash" | tr '[:upper:]' '[:lower:]')" ]]; then
|
||||
if [[ "${actual_hash,,}" != "${expected_hash,,}" ]]; then
|
||||
rm -f "$file"
|
||||
error "Hash verification failed! Expected: $expected_hash, Got: $actual_hash. The downloaded file may be corrupted or tampered with."
|
||||
fi
|
||||
|
|
@ -297,7 +282,6 @@ verify() {
|
|||
}
|
||||
|
||||
main() {
|
||||
resolve_version
|
||||
info "Installing Core CLI (version $VERSION)..."
|
||||
|
||||
# Verify install directory is safe before starting
|
||||
|
|
|
|||
|
|
@ -102,28 +102,6 @@ function Main {
|
|||
}
|
||||
|
||||
Write-Info "Dependencies installed!"
|
||||
Write-Host ""
|
||||
|
||||
# Configure GitHub CLI if not already authenticated
|
||||
if (Test-Command gh) {
|
||||
$authStatus = gh auth status 2>&1 | Out-String
|
||||
if ($authStatus -match "not logged in") {
|
||||
Write-Info "Configuring GitHub CLI..."
|
||||
Write-Host "You'll need to authenticate with GitHub."
|
||||
gh auth login -h github.com -p https -s workflow,repo,read:org,read:project,project
|
||||
} else {
|
||||
# Check for missing scopes
|
||||
$missingScopes = @()
|
||||
if ($authStatus -notmatch "workflow") { $missingScopes += "workflow" }
|
||||
if ($authStatus -notmatch "read:project") { $missingScopes += "read:project,project" }
|
||||
|
||||
if ($missingScopes.Count -gt 0) {
|
||||
Write-Warn "GitHub CLI missing scopes: $($missingScopes -join ', ')"
|
||||
Write-Host "Run: gh auth refresh -h github.com -s workflow,read:project,project"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Next: Run '.\scripts\install-core.ps1' to install the core CLI"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,7 @@ verify_hash() {
|
|||
|
||||
actual_hash=$(compute_sha256 "$file")
|
||||
|
||||
# Case-insensitive compare (bash 3 compatible)
|
||||
if [[ "$(echo "$actual_hash" | tr '[:upper:]' '[:lower:]')" != "$(echo "$expected_hash" | tr '[:upper:]' '[:lower:]')" ]]; then
|
||||
if [[ "${actual_hash,,}" != "${expected_hash,,}" ]]; then
|
||||
rm -f "$file"
|
||||
error "Hash verification failed! Expected: $expected_hash, Got: $actual_hash"
|
||||
fi
|
||||
|
|
@ -287,35 +286,6 @@ main() {
|
|||
esac
|
||||
|
||||
info "Dependencies installed!"
|
||||
echo ""
|
||||
|
||||
# Configure GitHub CLI if not already authenticated
|
||||
if has gh; then
|
||||
if ! gh auth status &>/dev/null; then
|
||||
info "Configuring GitHub CLI..."
|
||||
echo "You'll need to authenticate with GitHub."
|
||||
echo "When prompted, select HTTPS and add the 'workflow' scope."
|
||||
echo ""
|
||||
gh auth login -h github.com -p https -s workflow,repo,read:org,read:project,project
|
||||
else
|
||||
# Check if required scopes are present
|
||||
local auth_status=$(gh auth status 2>&1)
|
||||
local missing_scopes=""
|
||||
|
||||
if ! echo "$auth_status" | grep -q workflow; then
|
||||
missing_scopes="workflow"
|
||||
fi
|
||||
if ! echo "$auth_status" | grep -q "read:project"; then
|
||||
missing_scopes="$missing_scopes read:project project"
|
||||
fi
|
||||
|
||||
if [[ -n "$missing_scopes" ]]; then
|
||||
warn "GitHub CLI missing scopes:$missing_scopes"
|
||||
echo "Run: gh auth refresh -h github.com -s workflow,read:project,project"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Next: Run './scripts/install-core.sh' to install the core CLI"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue