Add label to template variables

This commit is contained in:
Cole Davis
2025-09-12 15:21:34 -04:00
committed by Cole D
parent b5de2b9913
commit 9c4bc5dc35
8 changed files with 109 additions and 1 deletions

View File

@@ -24,7 +24,7 @@ inputs:
required: false required: false
default: "claude/" default: "claude/"
branch_name_template: branch_name_template:
description: "Template for branch naming. Available variables: {{prefix}}, {{entityType}}, {{entityNumber}}, {{timestamp}}, {{year}}, {{month}}, {{day}}, {{hour}}, {{minute}}, {{sha}}. Default: '{{prefix}}{{entityType}}-{{entityNumber}}-{{timestamp}}'" description: "Template for branch naming. Available variables: {{prefix}}, {{entityType}}, {{entityNumber}}, {{timestamp}}, {{year}}, {{month}}, {{day}}, {{hour}}, {{minute}}, {{sha}}, {{label}}. The {{label}} variable uses the first label from the issue/PR, falling back to {{entityType}} if no labels exist. Default: '{{prefix}}{{entityType}}-{{entityNumber}}-{{timestamp}}'"
required: false required: false
default: "" default: ""
allowed_bots: allowed_bots:

View File

@@ -16,6 +16,11 @@ export const PR_QUERY = `
additions additions
deletions deletions
state state
labels(first: 10) {
nodes {
name
}
}
commits(first: 100) { commits(first: 100) {
totalCount totalCount
nodes { nodes {
@@ -97,6 +102,11 @@ export const ISSUE_QUERY = `
} }
createdAt createdAt
state state
labels(first: 10) {
nodes {
name
}
}
comments(first: 100) { comments(first: 100) {
nodes { nodes {
id id

View File

@@ -14,6 +14,14 @@ import type { Octokits } from "../api/client";
import type { FetchDataResult } from "../data/fetcher"; import type { FetchDataResult } from "../data/fetcher";
import { generateBranchName } from "../../utils/branch-template"; import { generateBranchName } from "../../utils/branch-template";
/**
* Extracts the first label from GitHub data, or returns undefined if no labels exist
*/
function extractFirstLabel(githubData: FetchDataResult): string | undefined {
const labels = githubData.contextData.labels?.nodes;
return labels && labels.length > 0 ? labels[0]?.name : undefined;
}
export type BranchInfo = { export type BranchInfo = {
baseBranch: string; baseBranch: string;
claudeBranch?: string; claudeBranch?: string;
@@ -102,6 +110,9 @@ export async function setupBranch(
sourceSHA = sourceBranchRef.data.object.sha; sourceSHA = sourceBranchRef.data.object.sha;
console.log(`Source branch SHA: ${sourceSHA}`); console.log(`Source branch SHA: ${sourceSHA}`);
// Extract first label from GitHub data
const firstLabel = extractFirstLabel(githubData);
// Generate branch name using template or default format // Generate branch name using template or default format
const newBranch = generateBranchName( const newBranch = generateBranchName(
branchNameTemplate, branchNameTemplate,
@@ -109,6 +120,7 @@ export async function setupBranch(
entityType, entityType,
entityNumber, entityNumber,
sourceSHA, sourceSHA,
firstLabel,
); );
// For commit signing, defer branch creation to the file ops server // For commit signing, defer branch creation to the file ops server

View File

@@ -61,6 +61,11 @@ export type GitHubPullRequest = {
additions: number; additions: number;
deletions: number; deletions: number;
state: string; state: string;
labels: {
nodes: Array<{
name: string;
}>;
};
commits: { commits: {
totalCount: number; totalCount: number;
nodes: Array<{ nodes: Array<{
@@ -84,6 +89,11 @@ export type GitHubIssue = {
author: GitHubAuthor; author: GitHubAuthor;
createdAt: string; createdAt: string;
state: string; state: string;
labels: {
nodes: Array<{
name: string;
}>;
};
comments: { comments: {
nodes: GitHubComment[]; nodes: GitHubComment[];
}; };

View File

@@ -15,6 +15,7 @@ export interface BranchTemplateVariables {
hour: string; hour: string;
minute: string; minute: string;
sha?: string; sha?: string;
label?: string;
} }
/** /**
@@ -46,6 +47,7 @@ export function createBranchTemplateVariables(
entityType: string, entityType: string,
entityNumber: number, entityNumber: number,
sha?: string, sha?: string,
label?: string,
): BranchTemplateVariables { ): BranchTemplateVariables {
const now = new Date(); const now = new Date();
@@ -60,6 +62,7 @@ export function createBranchTemplateVariables(
hour: String(now.getHours()).padStart(2, "0"), hour: String(now.getHours()).padStart(2, "0"),
minute: String(now.getMinutes()).padStart(2, "0"), minute: String(now.getMinutes()).padStart(2, "0"),
sha: sha?.substring(0, 8), // First 8 characters of SHA sha: sha?.substring(0, 8), // First 8 characters of SHA
label: label || entityType, // Fall back to entityType if no label
}; };
} }
@@ -72,12 +75,14 @@ export function generateBranchName(
entityType: string, entityType: string,
entityNumber: number, entityNumber: number,
sha?: string, sha?: string,
label?: string,
): string { ): string {
const variables = createBranchTemplateVariables( const variables = createBranchTemplateVariables(
branchPrefix, branchPrefix,
entityType, entityType,
entityNumber, entityNumber,
sha, sha,
label,
); );
let branchName: string; let branchName: string;

View File

@@ -81,6 +81,7 @@ describe("branch template utilities", () => {
expect(result.entityType).toBe("issue"); expect(result.entityType).toBe("issue");
expect(result.entityNumber).toBe(123); expect(result.entityNumber).toBe(123);
expect(result.sha).toBe("abcdef12"); expect(result.sha).toBe("abcdef12");
expect(result.label).toBe("issue"); // fallback to entityType
expect(result.timestamp).toMatch(/^\d{8}-\d{4}$/); expect(result.timestamp).toMatch(/^\d{8}-\d{4}$/);
expect(result.year).toMatch(/^\d{4}$/); expect(result.year).toMatch(/^\d{4}$/);
expect(result.month).toMatch(/^\d{2}$/); expect(result.month).toMatch(/^\d{2}$/);
@@ -103,6 +104,33 @@ describe("branch template utilities", () => {
const result = createBranchTemplateVariables("test/", "pr", 456); const result = createBranchTemplateVariables("test/", "pr", 456);
expect(result.sha).toBeUndefined(); expect(result.sha).toBeUndefined();
}); });
it("should use provided label when available", () => {
const result = createBranchTemplateVariables(
"test/",
"issue",
123,
undefined,
"bug",
);
expect(result.label).toBe("bug");
});
it("should fallback to entityType when label is not provided", () => {
const result = createBranchTemplateVariables("test/", "pr", 456);
expect(result.label).toBe("pr");
});
it("should fallback to entityType when label is empty string", () => {
const result = createBranchTemplateVariables(
"test/",
"issue",
789,
undefined,
"",
);
expect(result.label).toBe("issue");
});
}); });
describe("generateBranchName", () => { describe("generateBranchName", () => {
@@ -153,5 +181,40 @@ describe("branch template utilities", () => {
expect(result).toBe("fix/pr-789-abcdef12"); expect(result).toBe("fix/pr-789-abcdef12");
}); });
it("should use label in template when provided", () => {
const template = "{{prefix}}{{label}}/{{entityNumber}}";
const result = generateBranchName(
template,
"feature/",
"issue",
123,
undefined,
"bug",
);
expect(result).toBe("feature/bug/123");
});
it("should fallback to entityType when label template is used but no label provided", () => {
const template = "{{prefix}}{{label}}-{{entityNumber}}";
const result = generateBranchName(template, "fix/", "pr", 456);
expect(result).toBe("fix/pr-456");
});
it("should handle template with both label and entityType", () => {
const template = "{{prefix}}{{label}}-{{entityType}}_{{entityNumber}}";
const result = generateBranchName(
template,
"dev/",
"issue",
789,
undefined,
"enhancement",
);
expect(result).toBe("dev/enhancement-issue_789");
});
}); });
}); });

View File

@@ -61,6 +61,7 @@ describe("generatePrompt", () => {
body: "This is a test PR", body: "This is a test PR",
author: { login: "testuser" }, author: { login: "testuser" },
state: "OPEN", state: "OPEN",
labels: { nodes: [] },
createdAt: "2023-01-01T00:00:00Z", createdAt: "2023-01-01T00:00:00Z",
additions: 15, additions: 15,
deletions: 5, deletions: 5,
@@ -475,6 +476,7 @@ describe("generatePrompt", () => {
body: "The login form is not working", body: "The login form is not working",
author: { login: "testuser" }, author: { login: "testuser" },
state: "OPEN", state: "OPEN",
labels: { nodes: [] },
createdAt: "2023-01-01T00:00:00Z", createdAt: "2023-01-01T00:00:00Z",
comments: { comments: {
nodes: [], nodes: [],

View File

@@ -28,6 +28,9 @@ describe("formatContext", () => {
additions: 50, additions: 50,
deletions: 30, deletions: 30,
state: "OPEN", state: "OPEN",
labels: {
nodes: [],
},
commits: { commits: {
totalCount: 3, totalCount: 3,
nodes: [], nodes: [],
@@ -63,6 +66,9 @@ Changed Files: 2 files`,
author: { login: "test-user" }, author: { login: "test-user" },
createdAt: "2023-01-01T00:00:00Z", createdAt: "2023-01-01T00:00:00Z",
state: "OPEN", state: "OPEN",
labels: {
nodes: [],
},
comments: { comments: {
nodes: [], nodes: [],
}, },