Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
28ab0a6
feat: add telemetry instrumentation for release validation and metric…
ashleyshaw Aug 30, 2026
5584923
feat: add telemetry infrastructure (client, schemas, tests, docs)
ashleyshaw Aug 30, 2026
24cc5c1
fix: Move telemetry scripts to correct location and add governance rules
ashleyshaw Sep 1, 2026
1571791
fix: Complete script relocation and add comprehensive test coverage
ashleyshaw Sep 1, 2026
c7b3d2e
docs(telemetry): align script coverage target with policy
ashleyshaw Sep 1, 2026
bdaf116
Potential fix for pull request finding 'Unused variable, import, func…
ashleyshaw Sep 2, 2026
e2ba4a8
Potential fix for pull request finding 'Unused variable, import, func…
ashleyshaw Sep 2, 2026
01aca5c
Potential fix for pull request finding 'Unused variable, import, func…
ashleyshaw Sep 2, 2026
ca298cb
fix: Address CodeRabbit review findings for telemetry instrumentation PR
ashleyshaw Sep 2, 2026
b776863
Merge branch 'develop' into ashleyshaw-feat/release-telemetry-instrum…
ashleyshaw Sep 2, 2026
290b094
Potential fix for pull request finding 'Unused variable, import, func…
ashleyshaw Sep 2, 2026
90aaba1
fix: Apply CodeRabbit review feedback for telemetry instrumentation
ashleyshaw Sep 2, 2026
1c591ce
fix: Add workflow orchestrator to AGENTS.md quick reference table
ashleyshaw Sep 2, 2026
9ecb076
Fix CodeRabbit issues in PR #2581
coderabbitai[bot] Sep 2, 2026
663d7b9
Fix CodeRabbit issues in PR #2581
coderabbitai[bot] Sep 2, 2026
2eb1dfb
Merge branch 'develop' into ashleyshaw-feat/release-telemetry-instrum…
ashleyshaw Sep 3, 2026
7c4938d
Apply batched suggestions from code review
ashleyshaw Sep 3, 2026
8a1bd25
Apply batched suggestions from code review
ashleyshaw Sep 3, 2026
a9cbd29
fix: correct schema paths, coverage wording and orchestrator test con…
Copilot Sep 3, 2026
22eeb58
fix: align orchestrator tests with generateReports contract and strip…
Copilot Sep 3, 2026
9185d0d
test: restore module-level spies between orchestrator tests
Copilot Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions .github/agentic-workflows/release.agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
import fs from "fs";
import path from "path";
import { execSync } from "child_process";
import {
createTelemetryClient,
} from "../../scripts/telemetry/telemetry-client.js";
import { EVENT_SCHEMAS } from "../../scripts/telemetry/event-schemas.js";

// ============================================================================
// Configuration
Expand Down Expand Up @@ -68,6 +72,12 @@ class ReleaseAgent {
this.workflowId = `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.log = [];
this.decisions = {};

// Initialize telemetry client
this.telemetry = createTelemetryClient({
eventSchemas: EVENT_SCHEMAS,
});
this.validationStartTime = null;
}

// ========================================================================
Expand Down Expand Up @@ -477,6 +487,21 @@ Respond with JSON:

async execute() {
try {
// Emit: release.validation.started
this.validationStartTime = Date.now();
this.telemetry.emit('release.validation.started', {
safe: {
component: 'release-agent',
version: '1.0.0',
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
trigger: this.dryRun ? 'dry-run' : 'manual'
},
restricted: {
repositoryName: this.getRepositoryName(),
changelogPath: CHANGELOG_FILE,
versionFile: VERSION_FILE
}
});

// Step 1: Initialize & Pre-flight
await this.initialize();

Expand All @@ -486,12 +511,43 @@ Respond with JSON:
// Steps 3-9: Safety Gates
const gatesPass = await this.runSafetyGates();
if (!gatesPass) {
// Emit: release.gate.failure
this.telemetry.emit('release.gate.failure', {
safe: {
component: 'release-agent',
gateName: 'safety-gates',
failureReason: 'One or more safety gates failed',
recoverable: false
},
restricted: {
repositoryName: this.getRepositoryName(),
changelogPath: CHANGELOG_FILE,
errorDetails: 'Safety gates validation failed'
}
});
throw new Error("❌ One or more safety gates failed. Release aborted.");
}

// Step 10: Report & Cleanup
await this.report();

// Emit: release.validation.completed
const validationDuration = Date.now() - this.validationStartTime;
this.telemetry.emit('release.validation.completed', {
safe: {
component: 'release-agent',
version: this.nextVersion,
validationDuration,
gatesPassed: 7,
warningCount: 0
},
restricted: {
repositoryName: this.getRepositoryName(),
changelogPath: CHANGELOG_FILE,
validationResults: JSON.stringify(this.decisions)
}
});

console.log("\n✅ MVP Workflow Complete!\n");
console.log("Next Steps:");
console.log("1. Review the generated report");
Expand All @@ -502,7 +558,39 @@ Respond with JSON:
} catch (error) {
console.error(`\n❌ Workflow Failed: ${error.message}\n`);
this.addLog(`Error: ${error.message}`);

// Emit: release.gate.failure for unexpected errors
if (!error.message.includes('safety gates')) {
this.telemetry.emit('release.gate.failure', {
safe: {
component: 'release-agent',
gateName: 'execution',
failureReason: 'Unexpected error during release',
recoverable: false
},
restricted: {
repositoryName: this.getRepositoryName(),
errorDetails: error.message,
stackTrace: error.stack
}
});
}

throw error;
} finally {
// Flush telemetry data
await this.telemetry.flush();
}
}

getRepositoryName() {
try {
// Get repository name from git remote
const remote = execSync('git remote get-url origin', { encoding: 'utf-8' }).trim();
const match = remote.match(/github\.com[:/](.+?)(?:\.git)?$/);
return match ? match[1] : 'unknown/unknown';
} catch (_e) {
return 'unknown/unknown';
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions .github/instructions/file-organisation.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,32 @@ projects, or plugin bundles.
| `skills/` | Self-contained skills. | Each skill uses `SKILL.md`; assets stay inside the skill folder. |
| `workflows/` | Portable agentic workflows. | GitHub Actions stay in `.github/workflows/`. |

## Repository Scripts Location (CRITICAL)

**ALL scripts belong in `scripts/` at the root, NOT in `.github/scripts/`.**

| Script Type | Correct Location | WRONG Location |
| --- | --- | --- |
| Repository automation scripts | `scripts/automation/` | ❌ `.github/scripts/automation/` |
| Metrics collection scripts | `scripts/metrics/` | ❌ `.github/scripts/metrics/` |
| Telemetry scripts | `scripts/telemetry/` | ❌ `.github/scripts/telemetry/` |
| Release scripts | `scripts/release/` | ❌ `.github/scripts/release/` |
| Validation scripts | `scripts/validation/` | ❌ `.github/scripts/validation/` |
| Badge generation scripts | `scripts/badges/` | ❌ `.github/scripts/badges/` |
| **ONLY EXCEPTION:** Website browser scripts | `.github/website/src/scripts/` | ✅ Correct location for browser-specific code |
Comment thread
coderabbitai[bot] marked this conversation as resolved.

**Rules:**
- `.github/` is for GitHub-native governance files only (templates, workflows, configs)
- All executable scripts belong in `scripts/` with appropriate subfolders
- The ONLY exception is `.github/website/src/scripts/` for website browser code
- When in doubt, check existing script locations in `scripts/` directory
- Never create new scripts under `.github/scripts/` - this path should not exist

## File Type Mapping

| File Type | Canonical Location | Rule |
| --- | --- | --- |
| **Repository scripts** | `scripts/{category}/` | **ALWAYS root `scripts/`, never `.github/scripts/`** |
| Repo GitHub workflow | `.github/workflows/` | Keep executable GitHub Actions here. |
| Portable agentic workflow | `workflows/` | Use for tool-neutral AI processes. |
| Repo community-health file | `.github/` | Keep issue, PR, support, security, and governance files in place. |
Expand Down
Loading
Loading