semantic-release plugin to publish a GitHub release and comment on released Pull Requests/Issues
—
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.
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://github.com/owner/repo.gitgit@github.com:owner/repo.githttps://github.company.com/owner/repo.gitgithub.com/owner/repohttps://user:token@github.com/owner/repo.gitUsage 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)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, channelbranch: Branch name and channel informationlastRelease: Previous release informationcommits: Array of commits in the releasereleases: Array of published releaseserrors: 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" }
});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)"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:
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})`);
}
}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 configurationEINVALIDSUCCESSCOMMENT - Invalid success comment formatEINVALIDFAILTITLE - Invalid fail title formatEINVALIDFAILCOMMENT - Invalid fail comment formatEINVALIDLABELS - Invalid labels configurationEINVALIDASSIGNEES - Invalid assignees configurationEINVALIDRELEASEDLABELS - Invalid released labels configurationEINVALIDADDRELEASES - Invalid addReleases configurationEINVALIDDRAFTRELEASE - Invalid draftRelease configurationEINVALIDPROXY - Invalid proxy configurationEINVALIDGITHUBURL - Invalid GitHub repository URLEMISMATCHGITHUBURL - Repository URL mismatchEMISSINGREPO - Repository not foundEGHNOPERMISSION - Insufficient GitHub permissionsEINVALIDGHTOKEN - Invalid GitHub tokenENOGHTOKEN - Missing GitHub tokenEINVALIDRELEASEBODYTEMPLATE - Invalid release body templateEINVALIDRELEASENAMETEMPLATE - Invalid release name templateEINVALIDDISCUSSIONCATEGORYNAME - Invalid discussion categoryUsage 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 permissionsDetermines 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:
true if branch.prerelease is explicitly set to true or a stringfalse if branch.prerelease is explicitly set to falsefalse for main/stable branches (typically "main", "master")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)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"
}
});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