semantic-release plugin to publish a GitHub release and comment on released Pull Requests/Issues
—
Configuration resolution system that merges plugin options with environment variables and applies sensible defaults. The configuration system provides flexibility while maintaining backwards compatibility and security best practices.
Main configuration resolution function that processes plugin options and environment variables into a unified configuration object.
/**
* Resolves plugin configuration with environment variable fallbacks
* @param pluginConfig - Raw plugin configuration from semantic-release
* @param context - Contains environment variables and semantic-release context
* @returns Fully resolved configuration with defaults applied
*/
function resolveConfig(
pluginConfig: PluginConfig,
context: { env: NodeJS.ProcessEnv }
): ResolvedConfig;Resolution Priority (highest to lowest):
Usage Example:
import resolveConfig from "@semantic-release/github/lib/resolve-config.js";
const config = resolveConfig(
{
assets: ["dist/*.js"],
successComment: "Released in ${nextRelease.version}",
labels: ["automated-release"]
},
{
env: {
GITHUB_TOKEN: "ghp_xxxxxxxxxxxx",
GH_URL: "https://github.company.com",
HTTP_PROXY: "http://proxy:8080"
}
}
);
// Result includes resolved values with environment variable fallbacks
console.log(config.githubToken); // "ghp_xxxxxxxxxxxx"
console.log(config.githubUrl); // "https://github.company.com"
console.log(config.proxy); // "http://proxy:8080"Complete plugin configuration interface with all available options and their types.
interface PluginConfig {
/** GitHub server URL (for GitHub Enterprise) */
githubUrl?: string;
/** Full GitHub API URL (overrides githubUrl + prefix) */
githubApiUrl?: string;
/** GitHub API path prefix relative to githubUrl */
githubApiPathPrefix?: string;
/** HTTP proxy configuration or false to disable */
proxy?: ProxyConfig | false;
/** Files to upload as release assets */
assets?: AssetConfig[];
/** Comment template for successful releases, or false to disable */
successComment?: string | false;
/** Condition for when to add success comments */
successCommentCondition?: string | false;
/** Title for failure issues, or false to disable */
failTitle?: string | false;
/** Comment template for failure issues, or false to disable */
failComment?: string | false;
/** Condition for when to create failure issues */
failCommentCondition?: string | false;
/** Labels to add to failure issues, or false to disable */
labels?: string[] | false;
/** Users to assign to failure issues */
assignees?: string[];
/** Labels to add to resolved issues/PRs, or false to disable */
releasedLabels?: string[] | false;
/** Where to add release information in existing releases */
addReleases?: "top" | "bottom" | false;
/** Whether to create draft releases */
draftRelease?: boolean;
/** Template for release names */
releaseNameTemplate?: string;
/** Template for release body content */
releaseBodyTemplate?: string;
/** GitHub discussion category for releases, or false to disable */
discussionCategoryName?: string | false;
}
type AssetConfig = string | {
path: string | string[];
name?: string;
label?: string;
};
interface ProxyConfig {
host: string;
port: number;
secureProxy?: boolean;
headers?: Record<string, string>;
}The complete resolved configuration object returned by resolveConfig().
interface ResolvedConfig {
/** GitHub authentication token from GH_TOKEN or GITHUB_TOKEN */
githubToken: string;
/** GitHub server URL with environment variable fallback */
githubUrl?: string;
/** GitHub API path prefix with environment variable fallback */
githubApiPathPrefix: string;
/** GitHub API URL with environment variable fallback */
githubApiUrl?: string;
/** Resolved proxy configuration */
proxy: ProxyConfig | false;
/** Processed asset configurations */
assets?: AssetConfig[];
/** Success comment template */
successComment?: string | false;
/** Success comment condition */
successCommentCondition?: string | false;
/** Failure issue title */
failTitle: string | false;
/** Failure comment template */
failComment?: string | false;
/** Failure comment condition */
failCommentCondition?: string | false;
/** Issue labels */
labels: string[] | false;
/** Issue assignees */
assignees?: string[];
/** Released issue/PR labels */
releasedLabels: string[] | false;
/** Release information positioning */
addReleases: "top" | "bottom" | false;
/** Draft release flag */
draftRelease: boolean;
/** Release body template */
releaseBodyTemplate: string;
/** Release name template */
releaseNameTemplate: string;
/** Discussion category name */
discussionCategoryName: string | false;
}Complete list of supported environment variables with their purposes and fallbacks.
// Authentication (required)
process.env.GITHUB_TOKEN // Primary GitHub token
process.env.GH_TOKEN // Alternative GitHub token
// GitHub Enterprise endpoints
process.env.GITHUB_URL // GitHub server URL
process.env.GH_URL // Alternative GitHub server URL
process.env.GITHUB_PREFIX // API path prefix
process.env.GH_PREFIX // Alternative API path prefix
process.env.GITHUB_API_URL // Full API URL (overrides URL + prefix)
// Network configuration
process.env.HTTP_PROXY // HTTP proxy URL
process.env.http_proxy // Alternative HTTP proxy URL (lowercase)Environment Variable Examples:
# GitHub.com (default)
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx"
# GitHub Enterprise with separate URL and prefix
export GITHUB_TOKEN="ghs_xxxxxxxxxxxx"
export GITHUB_URL="https://github.company.com"
export GITHUB_PREFIX="/api/v3"
# GitHub Enterprise with direct API URL
export GITHUB_TOKEN="ghs_xxxxxxxxxxxx"
export GITHUB_API_URL="https://api.github.company.com/v3"
# With proxy
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx"
export HTTP_PROXY="http://proxy.company.com:8080"Built-in default values applied when no explicit configuration or environment variables are provided.
const DEFAULTS = {
// GitHub API
githubApiPathPrefix: "", // Empty prefix for GitHub.com
proxy: false, // No proxy by default
// Release management
draftRelease: false, // Create published releases
releaseBodyTemplate: "<%= nextRelease.notes %>",
releaseNameTemplate: "<%= nextRelease.name %>",
discussionCategoryName: false, // No discussions by default
// Issue/PR management
failTitle: "The automated release is failing 🚨",
labels: ["semantic-release"], // Default failure issue labels
releasedLabels: [ // Default released labels with template
"released<%= nextRelease.channel ? ` on @${nextRelease.channel}` : \"\" %>"
],
addReleases: false, // Don't modify existing releases
// Comments (no defaults - explicitly configured or disabled)
successComment: undefined, // Must be explicitly set
failComment: undefined, // Must be explicitly set
assets: undefined, // No assets by default
assignees: undefined // No assignees by default
};Configuration supports Lodash templates for dynamic content generation using semantic-release context.
// Available template variables from semantic-release context:
interface TemplateContext {
nextRelease: {
version: string; // "1.0.0"
gitTag: string; // "v1.0.0"
name: string; // "1.0.0"
notes: string; // Release notes markdown
channel?: string; // Release channel name
};
branch: {
name: string; // "main"
channel?: string; // Channel name if different from branch
};
lastRelease?: {
version: string;
gitTag: string;
};
commits: Array<{
hash: string;
message: string;
}>;
errors?: Error[]; // Available in failure templates
}Template Examples:
{
// Release templates
releaseNameTemplate: "Release ${nextRelease.version}",
releaseBodyTemplate: `
## What's Changed
${nextRelease.notes}
## Installation
\`npm install package@${nextRelease.version}\`
`,
// Comment templates
successComment: `
🎉 This issue has been resolved in version ${nextRelease.version}
The release is available on:
- [GitHub release](${releases[0].url})
- [npm package](https://www.npmjs.com/package/package/v/${nextRelease.version})
`,
failComment: `
❌ The automated release from \`${branch.name}\` branch failed.
**Error Details:**
${errors.map(error => \`- \${error.message}\`).join('\\n')}
`,
// Dynamic labels
releasedLabels: [
"released",
"v${nextRelease.version}",
"channel-${nextRelease.channel || 'default'}"
]
}All configuration options are validated before use, with detailed error messages for invalid values.
// Validation rules applied:
{
proxy: "String URL or Object with host/port, or false",
assets: "Array of strings or objects with path property",
successComment: "Non-empty string or false",
failTitle: "Non-empty string or false",
failComment: "Non-empty string or false",
labels: "Array of non-empty strings or false",
assignees: "Array of non-empty strings",
releasedLabels: "Array of non-empty strings or false",
addReleases: "One of: false, 'top', 'bottom'",
draftRelease: "Boolean",
releaseBodyTemplate: "Non-empty string",
releaseNameTemplate: "Non-empty string",
discussionCategoryName: "Non-empty string or false"
}Configuration Error Handling:
import { verifyConditions } from "@semantic-release/github";
try {
await verifyConditions({
assets: "invalid-type", // Should be array
labels: [123], // Should be strings
proxy: "not-a-url" // Invalid proxy format
}, context);
} catch (error) {
// AggregateError with detailed validation errors
error.errors.forEach(err => {
console.log(err.code); // "EINVALIDASSETS", "EINVALIDLABELS", etc.
console.log(err.message); // Human-readable error message
console.log(err.details); // Detailed explanation with examples
});
}Install with Tessl CLI
npx tessl i tessl/npm-semantic-release--github