BlackRoad Tools - ERP, CRM, manifest profiler, and DevOps utilities: Core Tools: - manifest_profile.py (937 lines) - Kubernetes manifest analysis - pully.py (735 lines) - Pull request automation - build_cluster_manifests.py (515 lines) - K8s cluster builders - erp.py (478 lines) - Enterprise resource planning - crm.py (405 lines) - Customer relationship management - build_metaverse_roster.py (331 lines) - Agent roster management - storage.py (305 lines) - Storage abstractions - agent_test_pipeline.py (304 lines) - Test automation - holo_cli.py (259 lines) - Holographic display CLI DevOps Scripts: - orin_bootstrap.sh - Jetson Orin setup - install_self_heal_pack.sh - Self-healing infrastructure - deploy_openwebui.sh - OpenWebUI deployment - triton_setup.sh - NVIDIA Triton setup Subdirectories: - branch-cleanup/ - Git branch management - kpis/ - KPI dashboards - metrics/ - Metrics collection - miners/ - Data mining tools - pulse/ - Health monitoring - tools-adapter/ - Integration adapters 11,351 lines of Python across 116 code files. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
132 lines
3.4 KiB
TypeScript
132 lines
3.4 KiB
TypeScript
import { Octokit } from '@octokit/core';
|
|
import { paginateGraphQL } from '@octokit/plugin-paginate-graphql';
|
|
|
|
const OctokitWithPlugins = Octokit.plugin(paginateGraphQL);
|
|
|
|
export interface MergedPR {
|
|
number: number;
|
|
mergedAt: string;
|
|
headRefName: string;
|
|
headRefOid: string;
|
|
baseRefName: string;
|
|
}
|
|
|
|
export interface BranchInfo {
|
|
name: string;
|
|
protected: boolean;
|
|
exists: boolean;
|
|
}
|
|
|
|
export interface CompareResult {
|
|
status: 'ahead' | 'behind' | 'identical' | 'diverged';
|
|
ahead_by: number;
|
|
behind_by: number;
|
|
}
|
|
|
|
export class GitHubQLClient {
|
|
private octokit: InstanceType<typeof OctokitWithPlugins>;
|
|
|
|
constructor(token: string) {
|
|
this.octokit = new OctokitWithPlugins({ auth: token });
|
|
}
|
|
|
|
async getDefaultBranch(owner: string, repo: string): Promise<string> {
|
|
const { data } = await this.octokit.request('GET /repos/{owner}/{repo}', {
|
|
owner,
|
|
repo,
|
|
});
|
|
return data.default_branch;
|
|
}
|
|
|
|
async getMergedPRs(owner: string, repo: string): Promise<MergedPR[]> {
|
|
const query = `
|
|
query($owner: String!, $repo: String!, $cursor: String) {
|
|
repository(owner: $owner, name: $repo) {
|
|
pullRequests(first: 100, after: $cursor, states: MERGED, orderBy: {field: UPDATED_AT, direction: DESC}) {
|
|
pageInfo {
|
|
hasNextPage
|
|
endCursor
|
|
}
|
|
nodes {
|
|
number
|
|
mergedAt
|
|
headRefName
|
|
headRefOid
|
|
baseRefName
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`;
|
|
|
|
const results: MergedPR[] = [];
|
|
const iterator = this.octokit.graphql.paginate.iterator(query, {
|
|
owner,
|
|
repo,
|
|
});
|
|
|
|
for await (const response of iterator) {
|
|
const prs = response.repository.pullRequests.nodes;
|
|
results.push(...prs);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
async checkBranch(owner: string, repo: string, branch: string): Promise<BranchInfo> {
|
|
try {
|
|
const { data } = await this.octokit.request('GET /repos/{owner}/{repo}/branches/{branch}', {
|
|
owner,
|
|
repo,
|
|
branch,
|
|
});
|
|
return {
|
|
name: branch,
|
|
protected: data.protected,
|
|
exists: true,
|
|
};
|
|
} catch (error: any) {
|
|
if (error.status === 404) {
|
|
return { name: branch, protected: false, exists: false };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async compareCommits(owner: string, repo: string, base: string, head: string): Promise<CompareResult> {
|
|
try {
|
|
const { data } = await this.octokit.request('GET /repos/{owner}/{repo}/compare/{basehead}', {
|
|
owner,
|
|
repo,
|
|
basehead: `${base}...${head}`,
|
|
});
|
|
|
|
return {
|
|
status: data.status as CompareResult['status'],
|
|
ahead_by: data.ahead_by,
|
|
behind_by: data.behind_by,
|
|
};
|
|
} catch (error: any) {
|
|
if (error.status === 404) {
|
|
// Branch might be deleted already
|
|
return { status: 'diverged', ahead_by: 0, behind_by: 0 };
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async isBranchReachable(owner: string, repo: string, base: string, head: string): Promise<boolean> {
|
|
const result = await this.compareCommits(owner, repo, base, head);
|
|
|
|
// Safe to delete if:
|
|
// - behind (head is behind base, so fully contained)
|
|
// - identical (head === base)
|
|
// NOT safe if ahead (has commits not in base)
|
|
return result.status === 'behind' || result.status === 'identical';
|
|
}
|
|
|
|
getOctokit() {
|
|
return this.octokit;
|
|
}
|
|
}
|