cli/.gh-actions/workflows/bugseti-release.yml

310 lines
10 KiB
YAML
Raw Normal View History

feat: BugSETI app, WebSocket hub, browser automation, and MCP tools (#336) * feat: add security logging and fix framework regressions This commit implements comprehensive security event logging and resolves critical regressions in the core framework. Security Logging: - Enhanced `pkg/log` with a `Security` level and helper. - Added `log.Username()` to consistently identify the executing user. - Instrumented GitHub CLI auth, Agentic configuration, filesystem sandbox, MCP handlers, and MCP TCP transport with security logs. - Added `SecurityStyle` to the CLI for consistent visual representation of security events. UniFi Security (CodeQL): - Refactored `pkg/unifi` to remove hardcoded `InsecureSkipVerify`, resolving a high-severity alert. - Added a `--verify-tls` flag and configuration option to control TLS verification. - Updated command handlers to support the new verification parameter. Framework Fixes: - Restored original signatures for `MustServiceFor`, `Config()`, and `Display()` in `pkg/framework/core`, which had been corrupted during a merge. - Fixed `pkg/framework/framework.go` and `pkg/framework/core/runtime_pkg.go` to match the restored signatures. - These fixes resolve project-wide compilation errors caused by the signature mismatches. I encountered significant blockers due to a corrupted state of the `dev` branch after a merge, which introduced breaking changes in the core framework's DI system. I had to manually reconcile these signatures with the expected usage across the codebase to restore build stability. * feat(mcp): add RAG tools (query, ingest, collections) Add vector database tools to the MCP server for RAG operations: - rag_query: Search for relevant documentation using semantic similarity - rag_ingest: Ingest files or directories into the vector database - rag_collections: List available collections Uses existing internal/cmd/rag exports (QueryDocs, IngestDirectory, IngestFile) and pkg/rag for Qdrant client access. Default collection is "hostuk-docs" with topK=5 for queries. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(mcp): add metrics tools (record, query) Add MCP tools for recording and querying AI/security metrics events. The metrics_record tool writes events to daily JSONL files, and the metrics_query tool provides aggregated statistics by type, repo, and agent. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add 'core mcp serve' command Add CLI command to start the MCP server for AI tool integration. - Create internal/cmd/mcpcmd package with serve subcommand - Support --workspace flag for directory restriction - Handle SIGINT/SIGTERM for clean shutdown - Register in full.go build variant Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ws): add WebSocket hub package for real-time streaming Add pkg/ws package implementing a hub pattern for WebSocket connections: - Hub manages client connections, broadcasts, and channel subscriptions - Client struct represents connected WebSocket clients - Message types: process_output, process_status, event, error, ping/pong - Channel-based subscription system (subscribe/unsubscribe) - SendProcessOutput and SendProcessStatus for process streaming integration - Full test coverage including concurrency tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(mcp): add process management and WebSocket MCP tools Add MCP tools for process management: - process_start: Start a new external process - process_stop: Gracefully stop a running process - process_kill: Force kill a process - process_list: List all managed processes - process_output: Get captured process output - process_input: Send input to process stdin Add MCP tools for WebSocket: - ws_start: Start WebSocket server for real-time streaming - ws_info: Get hub statistics (clients, channels) Update Service struct with optional process.Service and ws.Hub fields, new WithProcessService and WithWSHub options, getter methods, and Shutdown method for cleanup. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(webview): add browser automation package via Chrome DevTools Protocol Add pkg/webview package for browser automation: - webview.go: Main interface with Connect, Navigate, Click, Type, QuerySelector, Screenshot, Evaluate - cdp.go: Chrome DevTools Protocol WebSocket client implementation - actions.go: DOM action types (Click, Type, Hover, Scroll, etc.) and ActionSequence builder - console.go: Console message capture and filtering with ConsoleWatcher and ExceptionWatcher - angular.go: Angular-specific helpers for router navigation, component access, and Zone.js stability Add MCP tools for webview: - webview_connect/disconnect: Connection management - webview_navigate: Page navigation - webview_click/type/query/wait: DOM interaction - webview_console: Console output capture - webview_eval: JavaScript execution - webview_screenshot: Screenshot capture Add documentation: - docs/mcp/angular-testing.md: Guide for Angular application testing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: document new packages and BugSETI application - Update CLAUDE.md with documentation for: - pkg/ws (WebSocket hub for real-time streaming) - pkg/webview (Browser automation via CDP) - pkg/mcp (MCP server tools: process, ws, webview) - BugSETI application overview - Add comprehensive README for BugSETI with: - Installation and configuration guide - Usage workflow documentation - Architecture overview - Contributing guidelines Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(bugseti): add BugSETI system tray app with auto-update BugSETI - Distributed Bug Fixing like SETI@home but for code Features: - System tray app with Wails v3 - GitHub issue fetching with label filters - Issue queue with priority management - AI context seeding via seed-agent-developer skill - Automated PR submission flow - Stats tracking and leaderboard - Cross-platform notifications - Self-updating with stable/beta/nightly channels Includes: - cmd/bugseti: Main application with Angular frontend - internal/bugseti: Core services (fetcher, queue, seeder, submit, config, stats, notify) - internal/bugseti/updater: Auto-update system (checker, downloader, installer) - .github/workflows/bugseti-release.yml: CI/CD for all platforms Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: resolve import cycle and code duplication - Remove pkg/log import from pkg/io/local to break import cycle (pkg/log/rotation.go imports pkg/io, creating circular dependency) - Use stderr logging for security events in sandbox escape detection - Remove unused sync/atomic import from core.go - Fix duplicate LogSecurity function declarations in cli/log.go - Update workspace/service.go Crypt() call to match interface Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: update tests for new function signatures and format code - Update core_test.go: Config(), Display() now panic instead of returning error - Update runtime_pkg_test.go: sr.Config() now panics instead of returning error - Update MustServiceFor tests to use assert.Panics - Format BugSETI, MCP tools, and webview packages with gofmt Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Snider <631881+Snider@users.noreply.github.com> Co-authored-by: Claude <developers@lethean.io> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:22:05 +00:00
# BugSETI Release Workflow
# Builds for all platforms and creates GitHub releases
name: "BugSETI Release"
on:
push:
tags:
- 'bugseti-v*.*.*' # Stable: bugseti-v1.0.0
- 'bugseti-v*.*.*-beta.*' # Beta: bugseti-v1.0.0-beta.1
- 'bugseti-nightly-*' # Nightly: bugseti-nightly-20260205
permissions:
contents: write
env:
APP_NAME: bugseti
WAILS_VERSION: "3"
jobs:
# Determine release channel from tag
prepare:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
channel: ${{ steps.version.outputs.channel }}
prerelease: ${{ steps.version.outputs.prerelease }}
steps:
- name: Determine version and channel
id: version
env:
TAG: ${{ github.ref_name }}
run: |
if [[ "$TAG" == bugseti-nightly-* ]]; then
VERSION="${TAG#bugseti-}"
CHANNEL="nightly"
PRERELEASE="true"
elif [[ "$TAG" == *-beta.* ]]; then
VERSION="${TAG#bugseti-v}"
CHANNEL="beta"
PRERELEASE="true"
else
VERSION="${TAG#bugseti-v}"
CHANNEL="stable"
PRERELEASE="false"
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "channel=${CHANNEL}" >> "$GITHUB_OUTPUT"
echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT"
echo "Tag: $TAG"
echo "Version: $VERSION"
echo "Channel: $CHANNEL"
echo "Prerelease: $PRERELEASE"
build:
needs: prepare
strategy:
fail-fast: false
matrix:
include:
# macOS ARM64 (Apple Silicon)
- os: macos-latest
goos: darwin
goarch: arm64
ext: ""
archive: tar.gz
# macOS AMD64 (Intel)
- os: macos-13
goos: darwin
goarch: amd64
ext: ""
archive: tar.gz
# Linux AMD64
- os: ubuntu-latest
goos: linux
goarch: amd64
ext: ""
archive: tar.gz
# Linux ARM64
- os: ubuntu-24.04-arm
goos: linux
goarch: arm64
ext: ""
archive: tar.gz
# Windows AMD64
- os: windows-latest
goos: windows
goarch: amd64
ext: ".exe"
archive: zip
runs-on: ${{ matrix.os }}
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
VERSION: ${{ needs.prepare.outputs.version }}
CHANNEL: ${{ needs.prepare.outputs.channel }}
defaults:
run:
working-directory: cmd/bugseti
steps:
- uses: actions/checkout@v6
- name: Setup Go
uses: host-uk/build/actions/setup/go@v4.0.0
with:
go-version: "1.25"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Wails CLI
run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest
- name: Install frontend dependencies
working-directory: cmd/bugseti/frontend
run: npm ci
- name: Generate bindings
run: wails3 generate bindings -f '-tags production' -clean=false -ts -i
- name: Build frontend
working-directory: cmd/bugseti/frontend
run: npm run build
- name: Install Linux dependencies
if: matrix.goos == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev
- name: Build BugSETI
shell: bash
env:
EXT: ${{ matrix.ext }}
ARCHIVE: ${{ matrix.archive }}
COMMIT_SHA: ${{ github.sha }}
run: |
BINARY="${APP_NAME}${EXT}"
ARCHIVE_PREFIX="${APP_NAME}-${GOOS}-${GOARCH}"
BUILD_FLAGS="-tags production -trimpath -buildvcs=false"
# Version injection via ldflags
LDFLAGS="-s -w"
LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Version=${VERSION}"
LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Channel=${CHANNEL}"
LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Commit=${COMMIT_SHA}"
LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.BuildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
if [ "$GOOS" = "windows" ]; then
export CGO_ENABLED=0
LDFLAGS="${LDFLAGS} -H windowsgui"
# Generate Windows syso resource
cd build
wails3 generate syso -arch ${GOARCH} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_${GOARCH}.syso 2>/dev/null || true
cd ..
elif [ "$GOOS" = "darwin" ]; then
export CGO_ENABLED=1
export CGO_CFLAGS="-mmacosx-version-min=10.15"
export CGO_LDFLAGS="-mmacosx-version-min=10.15"
export MACOSX_DEPLOYMENT_TARGET="10.15"
else
export CGO_ENABLED=1
fi
mkdir -p bin
go build ${BUILD_FLAGS} -ldflags="${LDFLAGS}" -o "./bin/${BINARY}"
# Clean up syso files
rm -f *.syso
# Package based on platform
if [ "$GOOS" = "darwin" ]; then
# Create .app bundle
mkdir -p "./bin/BugSETI.app/Contents/"{MacOS,Resources}
cp build/darwin/icons.icns "./bin/BugSETI.app/Contents/Resources/" 2>/dev/null || true
cp "./bin/${BINARY}" "./bin/BugSETI.app/Contents/MacOS/"
cp build/darwin/Info.plist "./bin/BugSETI.app/Contents/"
codesign --force --deep --sign - "./bin/BugSETI.app" 2>/dev/null || true
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "BugSETI.app"
elif [ "$GOOS" = "windows" ]; then
cd ./bin && zip "${ARCHIVE_PREFIX}.zip" "${BINARY}" && cd ..
else
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "${BINARY}"
fi
# Rename raw binary for individual download
mv "./bin/${BINARY}" "./bin/${ARCHIVE_PREFIX}${EXT}"
# Generate checksum
cd ./bin
sha256sum "${ARCHIVE_PREFIX}.${ARCHIVE}" > "${ARCHIVE_PREFIX}.${ARCHIVE}.sha256"
sha256sum "${ARCHIVE_PREFIX}${EXT}" > "${ARCHIVE_PREFIX}${EXT}.sha256"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bugseti-${{ matrix.goos }}-${{ matrix.goarch }}
path: |
cmd/bugseti/bin/bugseti-*
retention-days: 7
release:
needs: [prepare, build]
runs-on: ubuntu-latest
env:
TAG_NAME: ${{ github.ref_name }}
VERSION: ${{ needs.prepare.outputs.version }}
CHANNEL: ${{ needs.prepare.outputs.channel }}
PRERELEASE: ${{ needs.prepare.outputs.prerelease }}
REPO: ${{ github.repository }}
steps:
- uses: actions/checkout@v6
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: List release files
run: |
echo "=== Release files ==="
ls -la dist/
echo "=== Checksums ==="
cat dist/*.sha256
- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Determine release title
if [ "$CHANNEL" = "nightly" ]; then
TITLE="BugSETI Nightly (${VERSION})"
elif [ "$CHANNEL" = "beta" ]; then
TITLE="BugSETI v${VERSION} (Beta)"
else
TITLE="BugSETI v${VERSION}"
fi
# Create release notes
cat > release-notes.md << EOF
## BugSETI ${VERSION}
**Channel:** ${CHANNEL}
### Downloads
| Platform | Architecture | Binary | Archive |
|----------|-------------|--------|---------|
| macOS | ARM64 (Apple Silicon) | [bugseti-darwin-arm64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-arm64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-arm64.tar.gz) |
| macOS | AMD64 (Intel) | [bugseti-darwin-amd64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-amd64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-amd64.tar.gz) |
| Linux | AMD64 | [bugseti-linux-amd64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-amd64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-amd64.tar.gz) |
| Linux | ARM64 | [bugseti-linux-arm64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-arm64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-arm64.tar.gz) |
| Windows | AMD64 | [bugseti-windows-amd64.exe](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-windows-amd64.exe) | [zip](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-windows-amd64.zip) |
### Checksums (SHA256)
\`\`\`
$(cat dist/*.sha256)
\`\`\`
---
*BugSETI - Distributed Bug Fixing, like SETI@home but for code*
EOF
# Build release command
RELEASE_ARGS=(
--title "$TITLE"
--notes-file release-notes.md
)
if [ "$PRERELEASE" = "true" ]; then
RELEASE_ARGS+=(--prerelease)
fi
# Create the release
gh release create "$TAG_NAME" \
"${RELEASE_ARGS[@]}" \
dist/*
# Scheduled nightly builds
nightly:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Create nightly tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DATE=$(date -u +%Y%m%d)
TAG="bugseti-nightly-${DATE}"
# Delete existing nightly tag for today if it exists
gh release delete "$TAG" --yes 2>/dev/null || true
git push origin ":refs/tags/$TAG" 2>/dev/null || true
# Create new tag
git tag "$TAG"
git push origin "$TAG"