linear skill
This commit is contained in:
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Get details for a specific Linear issue
|
||||
// Usage: linear-issue.js <identifier> [--comments]
|
||||
|
||||
import { getClient, formatDate } from "./lib.js";
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
const showComments = args.includes("--comments");
|
||||
const filtered = args.filter((a) => a !== "--comments");
|
||||
|
||||
const identifier = filtered[0];
|
||||
|
||||
if (!identifier) {
|
||||
console.log("Usage: linear-issue.js <identifier> [--comments]");
|
||||
console.log("\nExamples:");
|
||||
console.log(" linear-issue.js ATT-1234");
|
||||
console.log(" linear-issue.js ATT-1234 --comments");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const client = getClient();
|
||||
|
||||
// Parse team key and issue number from identifier (e.g. "SIP-1205")
|
||||
const parts = identifier.match(/^([A-Za-z]+)-(\d+)$/);
|
||||
if (!parts) {
|
||||
console.error(`Invalid identifier format: ${identifier}. Expected format: TEAM-123`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const teamKey = parts[1].toUpperCase();
|
||||
const issueNumber = parseInt(parts[2], 10);
|
||||
|
||||
// Find the issue by team key + number
|
||||
const issues = await client.issues({
|
||||
filter: {
|
||||
team: { key: { eq: teamKey } },
|
||||
number: { eq: issueNumber },
|
||||
},
|
||||
first: 1,
|
||||
});
|
||||
|
||||
const issue = issues.nodes[0];
|
||||
if (!issue) {
|
||||
console.error(`Issue ${identifier} not found.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const state = await issue.state;
|
||||
const team = await issue.team;
|
||||
const assignee = await issue.assignee;
|
||||
const labels = await issue.labels();
|
||||
const parent = await issue.parent;
|
||||
const project = await issue.project;
|
||||
const cycle = await issue.cycle;
|
||||
|
||||
console.log(`=== ${issue.identifier}: ${issue.title} ===`);
|
||||
console.log(`URL: ${issue.url}`);
|
||||
console.log(`State: ${state?.name || "Unknown"}`);
|
||||
console.log(`Priority: ${issue.priorityLabel}`);
|
||||
console.log(`Team: ${team?.key || "?"}`);
|
||||
console.log(`Assignee: ${assignee?.name || "Unassigned"}`);
|
||||
if (project) console.log(`Project: ${project.name}`);
|
||||
if (cycle) console.log(`Cycle: ${cycle.name || cycle.number}`);
|
||||
if (parent) console.log(`Parent: ${parent.identifier} - ${parent.title}`);
|
||||
if (labels.nodes.length > 0) {
|
||||
console.log(`Labels: ${labels.nodes.map((l) => l.name).join(", ")}`);
|
||||
}
|
||||
console.log(`Created: ${formatDate(issue.createdAt)}`);
|
||||
console.log(`Updated: ${formatDate(issue.updatedAt)}`);
|
||||
if (issue.dueDate) console.log(`Due: ${issue.dueDate}`);
|
||||
console.log(`\nDescription:\n${issue.description || "(empty)"}`);
|
||||
|
||||
if (showComments) {
|
||||
const comments = await issue.comments();
|
||||
if (comments.nodes.length > 0) {
|
||||
console.log(`\n--- Comments (${comments.nodes.length}) ---`);
|
||||
for (const comment of comments.nodes) {
|
||||
const author = await comment.user;
|
||||
console.log(`\n[${formatDate(comment.createdAt)}] ${author?.name || "Unknown"}:`);
|
||||
console.log(comment.body);
|
||||
}
|
||||
} else {
|
||||
console.log("\nNo comments.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user