CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-semantic-release--github

semantic-release plugin to publish a GitHub release and comment on released Pull Requests/Issues

Pending
Overview
Eval results
Files

utilities.mddocs/

Utilities

Helper functions for URL parsing, templating, error handling, and GitHub-specific operations. These utilities support the core plugin functionality with specialized operations for GitHub integration.

Capabilities

GitHub URL Parsing

Parses various GitHub repository URL formats to extract owner and repository names.

/**
 * Parses GitHub repository URLs to extract owner and repo names
 * @param repositoryUrl - Git repository URL in various formats
 * @returns Object containing owner and repo, or empty object if parsing fails
 */
function parseGitHubUrl(repositoryUrl: string): { owner?: string; repo?: string };

Supported URL Formats:

  • HTTPS: https://github.com/owner/repo.git
  • SSH: git@github.com:owner/repo.git
  • GitHub Enterprise: https://github.company.com/owner/repo.git
  • No protocol: github.com/owner/repo
  • With authentication: https://user:token@github.com/owner/repo.git

Usage Examples:

import parseGitHubUrl from "@semantic-release/github/lib/parse-github-url.js";

// Standard GitHub URLs
parseGitHubUrl("https://github.com/semantic-release/github.git");
// Returns: { owner: "semantic-release", repo: "github" }

parseGitHubUrl("git@github.com:semantic-release/github.git");
// Returns: { owner: "semantic-release", repo: "github" }

// GitHub Enterprise
parseGitHubUrl("https://github.company.com/team/project.git");
// Returns: { owner: "team", repo: "project" }

// With authentication
parseGitHubUrl("https://user:token@github.com/owner/repo.git");
// Returns: { owner: "owner", repo: "repo" }

// Invalid URLs
parseGitHubUrl("not-a-git-url");
// Returns: {}

parseGitHubUrl("https://gitlab.com/owner/repo.git");
// Returns: {} (not a GitHub URL)

Comment Generation

Template-based comment generation for success and failure scenarios.

/**
 * Generates success comment content for resolved issues and PRs
 * @param issue - GitHub issue or PR object
 * @param releaseInfos - Array of release information objects with URL and name
 * @param nextRelease - Next release information with version
 * @returns Rendered comment content as string
 */
function getSuccessComment(issue: Issue, releaseInfos: ReleaseInfo[], nextRelease: NextRelease): string;

/**
 * Generates failure comment content for release failures
 * @param branch - Branch information object with name
 * @param errors - Array of semantic-release errors that caused the failure
 * @returns Rendered comment content as string
 */
function getFailComment(branch: Branch, errors: SemanticReleaseError[]): string;

Template Variables Available:

  • nextRelease: Version, tag, name, notes, channel
  • branch: Branch name and channel information
  • lastRelease: Previous release information
  • commits: Array of commits in the release
  • releases: Array of published releases
  • errors: Array of errors (in failure comments)

Usage Examples:

import getSuccessComment from "@semantic-release/github/lib/get-success-comment.js";
import getFailComment from "@semantic-release/github/lib/get-fail-comment.js";

// Success comment generation
const successTemplate = `
🎉 This issue has been resolved in version ${nextRelease.version}

**Release Information:**
- **Version:** ${nextRelease.version}
- **Tag:** ${nextRelease.gitTag}  
- **Release Notes:** [View on GitHub](${releases[0].url})

The fix is now available for installation.
`;

const successComment = getSuccessComment(successTemplate, {
  nextRelease: {
    version: "1.2.0",
    gitTag: "v1.2.0",
    name: "1.2.0",
    notes: "Bug fixes and improvements"
  },
  releases: [{ url: "https://github.com/owner/repo/releases/tag/v1.2.0" }]
});

// Failure comment generation
const failTemplate = `
❌ The automated release failed on branch \`${branch.name}\`.

**Error Details:**
${errors.map(error => \`- \${error.message}\`).join('\\n')}

**Troubleshooting:**
1. Check the [build logs](${env.BUILD_URL || 'CI system'})
2. Verify GitHub token permissions
3. Review the configuration for errors

This issue will be automatically updated when the release is retried.
`;

const failComment = getFailComment(failTemplate, {
  branch: { name: "main" },
  errors: [
    new Error("GitHub token expired"),
    new Error("Network timeout during asset upload")
  ],
  env: { BUILD_URL: "https://ci.example.com/build/123" }
});

Release Link Generation

Generates formatted markdown links for releases across multiple channels.

/**
 * Generates release link markdown from release information
 * @param releases - Array of release objects with URLs and metadata
 * @returns Formatted markdown string with release links
 */
function getReleaseLinks(releases: Release[]): string;

interface Release {
  url: string;
  name?: string;
  channel?: string;
}

Usage Examples:

import getReleaseLinks from "@semantic-release/github/lib/get-release-links.js";

// Single release
const singleRelease = getReleaseLinks([
  { url: "https://github.com/owner/repo/releases/tag/v1.0.0", name: "1.0.0" }
]);
// Returns: "- [1.0.0](https://github.com/owner/repo/releases/tag/v1.0.0)"

// Multiple releases with channels
const multipleReleases = getReleaseLinks([
  { 
    url: "https://github.com/owner/repo/releases/tag/v1.0.0", 
    name: "1.0.0",
    channel: "stable"
  },
  { 
    url: "https://github.com/owner/repo/releases/tag/v1.1.0-beta.1", 
    name: "1.1.0-beta.1",
    channel: "beta"
  }
]);
// Returns: "- [1.0.0](https://github.com/owner/repo/releases/tag/v1.0.0) (stable)\n- [1.1.0-beta.1](https://github.com/owner/repo/releases/tag/v1.1.0-beta.1) (beta)"

Issue Discovery

Finds semantic-release related issues in the repository for management and updates.

/**
 * Finds semantic-release related issues in the repository
 * @param octokit - Configured Octokit instance
 * @param logger - Logger instance for debug output
 * @param labels - Array of label names to filter by (optional)
 * @param owner - Repository owner
 * @param repo - Repository name
 * @returns Promise resolving to array of matching issues
 */
async function findSRIssues(
  octokit: Octokit,
  logger: Logger,
  labels: string[] | undefined,
  owner: string,
  repo: string
): Promise<Issue[]>;

interface Issue {
  id: number;
  number: number;
  title: string;
  body: string;
  state: "open" | "closed";
  labels: string[];
  assignees: string[];
  html_url: string;
}

Issue Detection Logic:

  • Searches for issues containing the semantic-release identifier comment
  • Filters by semantic-release labels
  • Identifies both open and closed failure issues
  • Returns issues that may need updates or closure

Usage Examples:

import findSRIssues from "@semantic-release/github/lib/find-sr-issues.js";
import { SemanticReleaseOctokit } from "@semantic-release/github/lib/octokit.js";

const octokit = new SemanticReleaseOctokit({ auth: process.env.GITHUB_TOKEN });

// Find existing semantic-release issues
const issues = await findSRIssues(
  octokit,
  console, // logger
  ["semantic-release"], // labels
  "semantic-release", // owner
  "github" // repo
);

console.log(`Found ${issues.length} semantic-release issues`);

// Process issues
for (const issue of issues) {
  if (issue.state === "open") {
    console.log(`Open failure issue: ${issue.title} (#${issue.number})`);
  } else {
    console.log(`Resolved issue: ${issue.title} (#${issue.number})`);
  }
}

Error Handling

Creates standardized semantic-release error objects with detailed messages and documentation links.

/**
 * Creates semantic-release error objects with standardized format
 * @param code - Error code identifying the specific error type
 * @param context - Additional context data for error message templating
 * @returns Formatted error object with message and details
 */
function getError(code: string, context?: any): SemanticReleaseError;

interface SemanticReleaseError extends Error {
  name: string;
  message: string;
  details: string;
  code: string;
}

Available Error Codes:

  • EINVALIDASSETS - Invalid assets configuration
  • EINVALIDSUCCESSCOMMENT - Invalid success comment format
  • EINVALIDFAILTITLE - Invalid fail title format
  • EINVALIDFAILCOMMENT - Invalid fail comment format
  • EINVALIDLABELS - Invalid labels configuration
  • EINVALIDASSIGNEES - Invalid assignees configuration
  • EINVALIDRELEASEDLABELS - Invalid released labels configuration
  • EINVALIDADDRELEASES - Invalid addReleases configuration
  • EINVALIDDRAFTRELEASE - Invalid draftRelease configuration
  • EINVALIDPROXY - Invalid proxy configuration
  • EINVALIDGITHUBURL - Invalid GitHub repository URL
  • EMISMATCHGITHUBURL - Repository URL mismatch
  • EMISSINGREPO - Repository not found
  • EGHNOPERMISSION - Insufficient GitHub permissions
  • EINVALIDGHTOKEN - Invalid GitHub token
  • ENOGHTOKEN - Missing GitHub token
  • EINVALIDRELEASEBODYTEMPLATE - Invalid release body template
  • EINVALIDRELEASENAMETEMPLATE - Invalid release name template
  • EINVALIDDISCUSSIONCATEGORYNAME - Invalid discussion category

Usage Examples:

import getError from "@semantic-release/github/lib/get-error.js";

// Configuration validation errors
const assetsError = getError("EINVALIDASSETS", {
  assets: "invalid-string-should-be-array"
});
console.log(assetsError.message); // "Invalid `assets` option."
console.log(assetsError.details); // Detailed explanation with documentation links

// Authentication errors  
const tokenError = getError("ENOGHTOKEN", {
  owner: "semantic-release",
  repo: "github"
});
console.log(tokenError.code);    // "ENOGHTOKEN"
console.log(tokenError.message); // "No GitHub token specified."

// Repository access errors
const permissionError = getError("EGHNOPERMISSION", {
  owner: "private-org",
  repo: "secret-repo"
});
console.log(permissionError.details); // Instructions for fixing permissions

Prerelease Detection

Determines whether a branch or release should be marked as a prerelease.

/**
 * Determines if a release should be marked as prerelease based on branch configuration
 * @param branchConfig - Branch configuration object with type and prerelease settings
 * @returns True if the release should be marked as prerelease
 */
function isPrerelease(branchConfig: BranchConfig): boolean;

interface BranchConfig {
  type: "prerelease" | "release";
  main?: boolean;
  prerelease?: boolean | string;
}

Prerelease Logic:

  • Returns true if branch.prerelease is explicitly set to true or a string
  • Returns false if branch.prerelease is explicitly set to false
  • Returns false for main/stable branches (typically "main", "master")
  • Returns true for feature branches and channels like "beta", "alpha", "next"

Usage Examples:

import isPrerelease from "@semantic-release/github/lib/is-prerelease.js";

// Stable branches
isPrerelease({ name: "main" });
// Returns: false

isPrerelease({ name: "master" });  
// Returns: false

// Prerelease branches
isPrerelease({ name: "beta", prerelease: "beta" });
// Returns: true

isPrerelease({ name: "develop", prerelease: true });
// Returns: true

// Explicit configuration
isPrerelease({ name: "release", prerelease: false });
// Returns: false (explicitly disabled)

Template Processing

Internal template processing utilities used throughout the plugin.

/**
 * Internal utilities for template processing (from lodash-es)
 * Used throughout the plugin for dynamic content generation
 */

// Template compilation and execution
function template(templateString: string): (context: any) => string;

// Array and object utilities
function castArray<T>(value: T | T[]): T[];
function defaultTo<T>(value: T | null | undefined, defaultValue: T): T;
function isNil(value: any): value is null | undefined;
function merge<T>(target: T, ...sources: Partial<T>[]): T;

// String and validation utilities  
function isString(value: any): value is string;
function isPlainObject(value: any): value is Record<string, any>;
function isArray(value: any): value is any[];
function isBoolean(value: any): value is boolean;
function isNumber(value: any): value is number;

Template Processing Examples:

import { template } from "lodash-es";

// Create reusable templates
const releaseTemplate = template("Released version ${version} on ${date}");
const commentTemplate = template(`
## Release ${nextRelease.version}

This ${nextRelease.channel ? 'prerelease' : 'stable release'} includes:
${nextRelease.notes}
`);

// Execute templates with context
const releaseMessage = releaseTemplate({
  version: "1.0.0",
  date: new Date().toISOString()
});

const comment = commentTemplate({
  nextRelease: {
    version: "1.1.0-beta.1",
    channel: "beta",
    notes: "- Bug fixes\n- New features"
  }
});

Constants and Identifiers

Shared constants used throughout the plugin for consistent identification and labeling.

// Issue identification marker
const ISSUE_ID = "<!-- semantic-release:github -->";

// Release type identifier
const RELEASE_NAME = "GitHub release";

// Default failure issue label
const RELEASE_FAIL_LABEL = "semantic-release";

Usage in Generated Content:

// Issues created by the plugin include the identifier
const issueBody = `
${ISSUE_ID}

## Release Failure

The automated release process failed...
`;

// Release results include the consistent name
const releaseResult = {
  url: "https://github.com/owner/repo/releases/tag/v1.0.0",
  name: RELEASE_NAME,  // "GitHub release"
  id: 12345
};

// Default labels applied to failure issues
const defaultLabels = [RELEASE_FAIL_LABEL]; // ["semantic-release"]

Install with Tessl CLI

npx tessl i tessl/npm-semantic-release--github

docs

asset-management.md

configuration.md

github-integration.md

index.md

plugin-lifecycle.md

utilities.md

tile.json