semantic-release-linear-app 0.4.0-next.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * semantic-release-linear-app
3
3
  * A semantic-release plugin to update Linear issues with version labels
4
4
  */
5
- import { verifyConditions } from './lib/verify.js';
6
- import { success } from './lib/success.js';
5
+ import { verifyConditions } from "./lib/verify";
6
+ import { success } from "./lib/success";
7
7
  export { verifyConditions, success };
8
- export type { PluginConfig } from './types.js';
8
+ export type { PluginConfig } from "./types";
package/dist/index.js CHANGED
@@ -1,7 +1,11 @@
1
+ "use strict";
1
2
  /**
2
3
  * semantic-release-linear-app
3
4
  * A semantic-release plugin to update Linear issues with version labels
4
5
  */
5
- import { verifyConditions } from './lib/verify.js';
6
- import { success } from './lib/success.js';
7
- export { verifyConditions, success };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.success = exports.verifyConditions = void 0;
8
+ const verify_1 = require("./lib/verify");
9
+ Object.defineProperty(exports, "verifyConditions", { enumerable: true, get: function () { return verify_1.verifyConditions; } });
10
+ const success_1 = require("./lib/success");
11
+ Object.defineProperty(exports, "success", { enumerable: true, get: function () { return success_1.success; } });
@@ -1,4 +1,4 @@
1
- import { LinearContext } from '../types.js';
1
+ import { LinearContext } from '../types';
2
2
  /** Store Linear context for access across hooks */
3
3
  export declare function setLinearContext(ctx: LinearContext): void;
4
4
  export declare function getLinearContext(): LinearContext | null;
@@ -1,3 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setLinearContext = setLinearContext;
4
+ exports.getLinearContext = getLinearContext;
1
5
  /**
2
6
  * Module-level storage for Linear context between semantic-release hooks.
3
7
  * semantic-release creates separate context objects per hook, so we need
@@ -5,9 +9,9 @@
5
9
  */
6
10
  let linearContext = null;
7
11
  /** Store Linear context for access across hooks */
8
- export function setLinearContext(ctx) {
12
+ function setLinearContext(ctx) {
9
13
  linearContext = ctx;
10
14
  }
11
- export function getLinearContext() {
15
+ function getLinearContext() {
12
16
  return linearContext;
13
17
  }
@@ -1,4 +1,4 @@
1
- import { LinearIssue, LinearLabel, LinearViewer } from '../types.js';
1
+ import { LinearIssue, LinearLabel, LinearViewer } from '../types';
2
2
  /**
3
3
  * Linear API client for GraphQL operations
4
4
  */
@@ -1,8 +1,14 @@
1
- import fetch from 'node-fetch';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LinearClient = void 0;
7
+ const node_fetch_1 = __importDefault(require("node-fetch"));
2
8
  /**
3
9
  * Linear API client for GraphQL operations
4
10
  */
5
- export class LinearClient {
11
+ class LinearClient {
6
12
  apiKey;
7
13
  apiUrl = 'https://api.linear.app/graphql';
8
14
  constructor(apiKey) {
@@ -12,7 +18,7 @@ export class LinearClient {
12
18
  * Execute a GraphQL query
13
19
  */
14
20
  async query(query, variables = {}) {
15
- const response = await fetch(this.apiUrl, {
21
+ const response = await (0, node_fetch_1.default)(this.apiUrl, {
16
22
  method: 'POST',
17
23
  headers: {
18
24
  Authorization: this.apiKey,
@@ -186,3 +192,4 @@ export class LinearClient {
186
192
  return data.commentCreate.comment;
187
193
  }
188
194
  }
195
+ exports.LinearClient = LinearClient;
@@ -1,14 +1,17 @@
1
+ "use strict";
1
2
  /**
2
3
  * Extract Linear issue IDs from branch name ONLY
3
4
  * This enforces a single source of truth for issue tracking
4
5
  */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseIssuesFromBranch = parseIssuesFromBranch;
5
8
  /**
6
9
  * Extract Linear issue IDs from a branch name
7
10
  * @param branchName - The branch name to parse
8
11
  * @param teamKeys - Optional list of team keys to filter by
9
12
  * @returns Array of unique issue identifiers
10
13
  */
11
- export function parseIssuesFromBranch(branchName, teamKeys = null) {
14
+ function parseIssuesFromBranch(branchName, teamKeys = null) {
12
15
  const issues = new Set();
13
16
  // Build regex pattern based on team keys
14
17
  const teamPattern = teamKeys ? `(?:${teamKeys.join('|')})` : '[A-Z]+';
@@ -1,25 +1,26 @@
1
- import { describe, test, expect } from '@jest/globals';
2
- import { parseIssuesFromBranch } from './parse-issues.js';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const parse_issues_1 = require("./parse-issues");
3
4
  describe('parse-issues', () => {
4
5
  test('extracts Linear issue IDs from branch name', () => {
5
6
  const branchName = 'feature/ENG-123-add-new-feature';
6
- const result = parseIssuesFromBranch(branchName);
7
+ const result = (0, parse_issues_1.parseIssuesFromBranch)(branchName);
7
8
  expect(result).toEqual(['ENG-123']);
8
9
  });
9
10
  test('extracts multiple issue IDs from branch name', () => {
10
11
  const branchName = 'fix/ENG-123-FEAT-456-bug-fix';
11
- const result = parseIssuesFromBranch(branchName);
12
+ const result = (0, parse_issues_1.parseIssuesFromBranch)(branchName);
12
13
  expect(result).toEqual(expect.arrayContaining(['ENG-123', 'FEAT-456']));
13
14
  expect(result).toHaveLength(2);
14
15
  });
15
16
  test('filters by team keys when provided', () => {
16
17
  const branchName = 'feature/ENG-123-OTHER-456';
17
- const result = parseIssuesFromBranch(branchName, ['ENG']);
18
+ const result = (0, parse_issues_1.parseIssuesFromBranch)(branchName, ['ENG']);
18
19
  expect(result).toEqual(['ENG-123']);
19
20
  });
20
21
  test('returns empty array for branch without issues', () => {
21
22
  const branchName = 'feature/no-issues-here';
22
- const result = parseIssuesFromBranch(branchName);
23
+ const result = (0, parse_issues_1.parseIssuesFromBranch)(branchName);
23
24
  expect(result).toEqual([]);
24
25
  });
25
26
  });
@@ -1,5 +1,5 @@
1
1
  import { SuccessContext } from 'semantic-release';
2
- import { PluginConfig } from '../types.js';
2
+ import { PluginConfig } from '../types';
3
3
  /**
4
4
  * Update Linear issues after a successful release
5
5
  */
@@ -1,7 +1,10 @@
1
- import { execa } from 'execa';
2
- import { LinearClient } from './linear-client.js';
3
- import { parseIssuesFromBranch } from './parse-issues.js';
4
- import { getLinearContext } from './context.js';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.success = success;
4
+ const execa_1 = require("execa");
5
+ const linear_client_1 = require("./linear-client");
6
+ const parse_issues_1 = require("./parse-issues");
7
+ const context_1 = require("./context");
5
8
  /**
6
9
  * Find source branches that contain the given commits
7
10
  */
@@ -13,7 +16,7 @@ async function findSourceBranches(commits, logger) {
13
16
  // Check all commits to find all source branches
14
17
  for (const commit of commits) {
15
18
  try {
16
- const { stdout } = await execa('git', [
19
+ const { stdout } = await (0, execa_1.execa)('git', [
17
20
  'branch',
18
21
  '-r',
19
22
  '--contains',
@@ -40,9 +43,9 @@ async function findSourceBranches(commits, logger) {
40
43
  /**
41
44
  * Update Linear issues after a successful release
42
45
  */
43
- export async function success(pluginConfig, context) {
46
+ async function success(pluginConfig, context) {
44
47
  const { logger, nextRelease, commits } = context;
45
- const linear = getLinearContext();
48
+ const linear = (0, context_1.getLinearContext)();
46
49
  if (!linear) {
47
50
  logger.log('Linear context not found, skipping issue updates');
48
51
  return;
@@ -61,7 +64,7 @@ export async function success(pluginConfig, context) {
61
64
  // Extract Linear issue IDs from all found branches
62
65
  const issueIds = new Set();
63
66
  for (const branchName of Array.from(sourceBranches)) {
64
- const branchIssues = parseIssuesFromBranch(branchName, linear.teamKeys);
67
+ const branchIssues = (0, parse_issues_1.parseIssuesFromBranch)(branchName, linear.teamKeys);
65
68
  branchIssues.forEach((id) => issueIds.add(id));
66
69
  }
67
70
  if (issueIds.size === 0) {
@@ -79,7 +82,7 @@ export async function success(pluginConfig, context) {
79
82
  return;
80
83
  }
81
84
  // Initialize Linear client and prepare label
82
- const client = new LinearClient(linear.apiKey);
85
+ const client = new linear_client_1.LinearClient(linear.apiKey);
83
86
  const labelColor = getLabelColor(nextRelease.type);
84
87
  // Ensure the version label exists
85
88
  const label = await client.ensureLabel(labelName, labelColor);
@@ -1,5 +1,5 @@
1
1
  import { VerifyConditionsContext } from 'semantic-release';
2
- import { PluginConfig } from '../types.js';
2
+ import { PluginConfig } from '../types';
3
3
  /**
4
4
  * Verify the plugin configuration and Linear API access
5
5
  */
@@ -1,37 +1,43 @@
1
- import SemanticReleaseError from '@semantic-release/error';
2
- import { LinearClient } from './linear-client.js';
3
- import { setLinearContext } from './context.js';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.verifyConditions = verifyConditions;
7
+ const error_1 = __importDefault(require("@semantic-release/error"));
8
+ const linear_client_1 = require("./linear-client");
9
+ const context_1 = require("./context");
4
10
  /**
5
11
  * Verify the plugin configuration and Linear API access
6
12
  */
7
- export async function verifyConditions(pluginConfig, context) {
13
+ async function verifyConditions(pluginConfig, context) {
8
14
  const { logger } = context;
9
15
  const { token, teamKeys = [] } = pluginConfig;
10
16
  // Check for token in config or environment
11
17
  const linearToken = token || process.env.LINEAR_TOKEN;
12
18
  if (!linearToken) {
13
- throw new SemanticReleaseError('No Linear token found', 'ENOLINEARTOKEN', 'Please provide LINEAR_TOKEN environment variable.');
19
+ throw new error_1.default('No Linear token found', 'ENOLINEARTOKEN', 'Please provide LINEAR_TOKEN environment variable.');
14
20
  }
15
21
  // Validate team keys format if provided
16
22
  const teamKeyPattern = /^[A-Z]+$/;
17
23
  const branchPattern = /^[A-Za-z0-9._-]+\/[A-Za-z0-9][A-Za-z0-9._-]*$/;
18
24
  const invalidTeamKeys = teamKeys.filter((key) => !teamKeyPattern.test(key) && !branchPattern.test(key));
19
25
  if (invalidTeamKeys.length > 0) {
20
- throw new SemanticReleaseError('Invalid team key format', 'EINVALIDTEAMKEY', 'Team keys must be uppercase letters (e.g. SD) or branch names (e.g. caio/tk-519-title). ' +
26
+ throw new error_1.default('Invalid team key format', 'EINVALIDTEAMKEY', 'Team keys must be uppercase letters (e.g. SD) or branch names (e.g. caio/tk-519-title). ' +
21
27
  `Invalid: ${invalidTeamKeys.join(', ')}`);
22
28
  }
23
29
  // Test API connection
24
- const client = new LinearClient(linearToken);
30
+ const client = new linear_client_1.LinearClient(linearToken);
25
31
  try {
26
32
  logger.log('Verifying Linear API access...');
27
33
  await client.testConnection();
28
34
  logger.log('✓ Linear API access verified');
29
35
  }
30
36
  catch (error) {
31
- throw new SemanticReleaseError('Failed to connect to Linear API', 'ELINEARCONNECTION', `Could not connect to Linear API: ${error.message}`);
37
+ throw new error_1.default('Failed to connect to Linear API', 'ELINEARCONNECTION', `Could not connect to Linear API: ${error.message}`);
32
38
  }
33
39
  // Store validated config for other lifecycle methods
34
- setLinearContext({
40
+ (0, context_1.setLinearContext)({
35
41
  apiKey: linearToken,
36
42
  teamKeys: teamKeys.length > 0 ? teamKeys : null,
37
43
  labelPrefix: pluginConfig.labelPrefix || 'v',
@@ -1,6 +1,7 @@
1
- import { jest, describe, test, expect, beforeEach } from '@jest/globals';
2
- // ESM mocks must be set up before imports
3
- jest.unstable_mockModule('@semantic-release/error', () => {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Minimal ESM mocks
4
+ jest.mock('@semantic-release/error', () => {
4
5
  class SemanticReleaseError extends Error {
5
6
  code;
6
7
  constructor(message, code) {
@@ -8,15 +9,15 @@ jest.unstable_mockModule('@semantic-release/error', () => {
8
9
  this.code = code;
9
10
  }
10
11
  }
11
- return { default: SemanticReleaseError };
12
+ return { __esModule: true, default: SemanticReleaseError };
12
13
  });
13
- jest.unstable_mockModule('./linear-client.js', () => ({
14
- LinearClient: jest.fn(() => ({
15
- testConnection: jest.fn(() => Promise.resolve({})),
14
+ jest.mock('./linear-client', () => ({
15
+ LinearClient: jest.fn().mockImplementation(() => ({
16
+ testConnection: jest.fn().mockResolvedValue({}),
16
17
  })),
17
18
  }));
18
- jest.unstable_mockModule('node-fetch', () => ({ default: jest.fn() }));
19
- const { verifyConditions } = await import('./verify.js');
19
+ jest.mock('node-fetch', () => ({ __esModule: true, default: jest.fn() }));
20
+ const verify_1 = require("./verify");
20
21
  describe('verify', () => {
21
22
  const mockContext = {
22
23
  logger: { log: jest.fn(), error: jest.fn() },
@@ -25,15 +26,15 @@ describe('verify', () => {
25
26
  delete process.env.LINEAR_TOKEN;
26
27
  });
27
28
  test('throws without token', async () => {
28
- await expect(verifyConditions({}, mockContext)).rejects.toThrow('No Linear token found');
29
+ await expect((0, verify_1.verifyConditions)({}, mockContext)).rejects.toThrow('No Linear token found');
29
30
  });
30
31
  test('validates team key format', async () => {
31
32
  // Validation happens BEFORE the API call, so it fails fast
32
- await expect(verifyConditions({ token: 'test', teamKeys: ['eng-123'] }, mockContext)).rejects.toThrow('Invalid team key format');
33
+ await expect((0, verify_1.verifyConditions)({ token: 'test', teamKeys: ['eng-123'] }, mockContext)).rejects.toThrow('Invalid team key format');
33
34
  });
34
35
  test('accepts valid branch like team key', async () => {
35
36
  // Accepts branch patterns without hitting API
36
- await expect(verifyConditions({
37
+ await expect((0, verify_1.verifyConditions)({
37
38
  token: 'test',
38
39
  teamKeys: ['caio/tk-519-title'],
39
40
  }, mockContext)).resolves.toBeUndefined();
package/dist/types.js CHANGED
@@ -1 +1,2 @@
1
- export {};
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "semantic-release-linear-app",
3
- "version": "0.4.0-next.2",
3
+ "version": "0.4.0",
4
4
  "description": "Semantic-release plugin to update Linear issues with version labels",
5
- "type": "module",
6
5
  "main": "dist/index.js",
7
6
  "types": "dist/index.d.ts",
8
7
  "engines": {
@@ -18,27 +17,13 @@
18
17
  "lint": "eslint src/**/*.ts",
19
18
  "format": "prettier --write src/**/*.ts",
20
19
  "prepare": "husky",
21
- "test": "NODE_OPTIONS='--experimental-vm-modules' jest",
20
+ "test": "jest",
22
21
  "test:watch": "jest --watch",
23
22
  "validate": "pnpm lint && pnpm type-check && pnpm build && pnpm test"
24
23
  },
25
24
  "jest": {
26
- "preset": "ts-jest/presets/default-esm",
25
+ "preset": "ts-jest",
27
26
  "testEnvironment": "node",
28
- "extensionsToTreatAsEsm": [
29
- ".ts"
30
- ],
31
- "moduleNameMapper": {
32
- "^(\\.{1,2}/.*)\\.js$": "$1"
33
- },
34
- "transform": {
35
- "^.+\\.tsx?$": [
36
- "ts-jest",
37
- {
38
- "useESM": true
39
- }
40
- ]
41
- },
42
27
  "testMatch": [
43
28
  "**/*.test.ts"
44
29
  ]
@@ -66,7 +51,6 @@
66
51
  "node-fetch": "^3.3.2"
67
52
  },
68
53
  "devDependencies": {
69
- "@jest/globals": "^30.2.0",
70
54
  "@semantic-release/commit-analyzer": "^13.0.1",
71
55
  "@semantic-release/git": "^10.0.1",
72
56
  "@semantic-release/github": "^12.0.2",
package/src/index.ts CHANGED
@@ -3,10 +3,10 @@
3
3
  * A semantic-release plugin to update Linear issues with version labels
4
4
  */
5
5
 
6
- import { verifyConditions } from './lib/verify.js';
7
- import { success } from './lib/success.js';
6
+ import { verifyConditions } from "./lib/verify";
7
+ import { success } from "./lib/success";
8
8
 
9
9
  export { verifyConditions, success };
10
10
 
11
11
  // Also export types for consumers who use TypeScript
12
- export type { PluginConfig } from './types.js';
12
+ export type { PluginConfig } from "./types";
@@ -1,4 +1,4 @@
1
- import { LinearContext } from '../types.js';
1
+ import { LinearContext } from '../types';
2
2
 
3
3
  /**
4
4
  * Module-level storage for Linear context between semantic-release hooks.
@@ -1,5 +1,5 @@
1
1
  import fetch from 'node-fetch';
2
- import { LinearIssue, LinearLabel, LinearViewer } from '../types.js';
2
+ import { LinearIssue, LinearLabel, LinearViewer } from '../types';
3
3
 
4
4
  interface GraphQLResponse<T> {
5
5
  data?: T;
@@ -1,5 +1,4 @@
1
- import { describe, test, expect } from '@jest/globals';
2
- import { parseIssuesFromBranch } from './parse-issues.js';
1
+ import { parseIssuesFromBranch } from './parse-issues';
3
2
 
4
3
  describe('parse-issues', () => {
5
4
  test('extracts Linear issue IDs from branch name', () => {
@@ -1,9 +1,9 @@
1
1
  import { SuccessContext } from 'semantic-release';
2
2
  import { execa } from 'execa';
3
- import { LinearClient } from './linear-client.js';
4
- import { parseIssuesFromBranch } from './parse-issues.js';
5
- import { PluginConfig, ReleaseType } from '../types.js';
6
- import { getLinearContext } from './context.js';
3
+ import { LinearClient } from './linear-client';
4
+ import { parseIssuesFromBranch } from './parse-issues';
5
+ import { PluginConfig, ReleaseType } from '../types';
6
+ import { getLinearContext } from './context';
7
7
 
8
8
  /**
9
9
  * Find source branches that contain the given commits
@@ -1,7 +1,5 @@
1
- import { jest, describe, test, expect, beforeEach } from '@jest/globals';
2
-
3
- // ESM mocks must be set up before imports
4
- jest.unstable_mockModule('@semantic-release/error', () => {
1
+ // Minimal ESM mocks
2
+ jest.mock('@semantic-release/error', () => {
5
3
  class SemanticReleaseError extends Error {
6
4
  code: string;
7
5
  constructor(message: string, code: string) {
@@ -9,24 +7,24 @@ jest.unstable_mockModule('@semantic-release/error', () => {
9
7
  this.code = code;
10
8
  }
11
9
  }
12
- return { default: SemanticReleaseError };
10
+ return { __esModule: true, default: SemanticReleaseError };
13
11
  });
14
12
 
15
- jest.unstable_mockModule('./linear-client.js', () => ({
16
- LinearClient: jest.fn(() => ({
17
- testConnection: jest.fn(() => Promise.resolve({})),
13
+ jest.mock('./linear-client', () => ({
14
+ LinearClient: jest.fn().mockImplementation(() => ({
15
+ testConnection: jest.fn().mockResolvedValue({}),
18
16
  })),
19
17
  }));
20
18
 
21
- jest.unstable_mockModule('node-fetch', () => ({ default: jest.fn() }));
19
+ jest.mock('node-fetch', () => ({ __esModule: true, default: jest.fn() }));
22
20
 
23
- const { verifyConditions } = await import('./verify.js');
24
- import type { VerifyConditionsContext } from 'semantic-release';
21
+ import { verifyConditions } from './verify';
22
+ import { VerifyConditionsContext } from 'semantic-release';
25
23
 
26
24
  describe('verify', () => {
27
25
  const mockContext = {
28
26
  logger: { log: jest.fn(), error: jest.fn() },
29
- } as unknown as VerifyConditionsContext;
27
+ } as VerifyConditionsContext;
30
28
 
31
29
  beforeEach(() => {
32
30
  delete process.env.LINEAR_TOKEN;
package/src/lib/verify.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import SemanticReleaseError from '@semantic-release/error';
2
2
  import { VerifyConditionsContext } from 'semantic-release';
3
- import { LinearClient } from './linear-client.js';
4
- import { PluginConfig } from '../types.js';
5
- import { setLinearContext } from './context.js';
3
+ import { LinearClient } from './linear-client';
4
+ import { PluginConfig } from '../types';
5
+ import { setLinearContext } from './context';
6
6
 
7
7
  /**
8
8
  * Verify the plugin configuration and Linear API access