Files
Olabode Lawal-Shittabey 1beed123fa feat: integrate @semantic-release/core engine (#4256)
This pull request refactors the core logic of the package to use the
`@semantic-release/core` engine directly, removes legacy and duplicated
code, and centralizes configuration. The changes simplify the codebase
by delegating most of the release logic to the upstream core package,
making the CLI wrapper thinner and easier to maintain. Several internal
utility files for branch and tag handling are also removed, as their
logic is now handled by `@semantic-release/core`.

### Migration to Core Engine

* The CLI now delegates release logic to `@semantic-release/core`, using
its `resolveConfig`, `getLogger`, and other helpers, instead of
maintaining a custom implementation. This reduces maintenance overhead
and ensures alignment with the core release logic.
* The documentation is updated to explain that `semantic-release` uses
`@semantic-release/core` as its engine, and provides guidance for
advanced use cases.

### Configuration and Defaults

* A new `SEMANTIC_RELEASE_DEFAULT_CONFIG` constant is introduced,
centralizing the default plugin stack for releases.

### Codebase Simplification

* Removes internal implementations for branch expansion, tag retrieval,
and normalization, as well as related validation and error handling
logic. These are now handled by the core engine.
2026-10-06 06:42:49 +01:00

85 lines
3.3 KiB
JavaScript

import test from "ava";
import * as td from "testdouble";
const SEMANTIC_RELEASE_DEFAULT_CONFIG = {
plugins: [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
"@semantic-release/github",
],
};
test.afterEach.always(() => {
td.reset();
});
test.serial("wrapper forwards environment params and delegates to core", async (t) => {
const core = await td.replaceEsm("@semantic-release/core");
const logger = { log: td.func("log"), warn: td.func("warn") };
const plugins = { verifyConditions: td.func("verifyConditions") };
const resolvedOptions = { repositoryUrl: "https://example.com/repo.git", dryRun: true };
const env = {};
const stdout = { write: td.func("stdout.write") };
const stderr = { write: td.func("stderr.write") };
td.when(core.default(td.matchers.isA(Object))).thenResolve({ ok: true });
td.when(core.resolveEnvCi(td.matchers.isA(Object))).thenReturn({ isCi: true, branch: "next", isPr: false });
td.when(core.getLogger(td.matchers.isA(Object))).thenReturn(logger);
td.when(core.resolveConfig(td.matchers.isA(Object), td.matchers.isA(Object), td.matchers.isA(Object))).thenResolve({
plugins,
options: resolvedOptions,
});
const semanticRelease = (await import("../index.js")).default;
const result = await semanticRelease({ dryRun: true }, { cwd: process.cwd(), env, stdout, stderr });
const [{ args }] = td.explain(core.default).calls;
const [callArg] = args;
const { context, plugins: receivedPlugins } = callArg;
const [{ args: resolveConfigArgs }] = td.explain(core.resolveConfig).calls;
const [, , configOptions] = resolveConfigArgs;
t.deepEqual(receivedPlugins, plugins);
t.is(typeof callArg.formatOutput, "function");
t.deepEqual(configOptions, { baseConfig: SEMANTIC_RELEASE_DEFAULT_CONFIG, buildPlugins: true });
t.is(context.envCi.branch, "next");
t.is(context.cwd, process.cwd());
t.is(context.env, env);
t.is(context.stdout, stdout);
t.is(context.stderr, stderr);
t.is(context.options.repositoryUrl, resolvedOptions.repositoryUrl);
td.verify(logger.log(td.matchers.contains("Running semantic-release version")));
const formatted = await callArg.formatOutput("## Title");
t.true(formatted.includes("Title"));
t.deepEqual(result, { ok: true });
});
test.serial("wrapper computes dry-run policy upstream before calling core", async (t) => {
const core = await td.replaceEsm("@semantic-release/core");
const logger = { log: td.func("log"), warn: td.func("warn") };
td.when(core.default(td.matchers.isA(Object))).thenResolve(true);
td.when(core.resolveEnvCi(td.matchers.isA(Object))).thenReturn({ isCi: false, branch: "next", isPr: false });
td.when(core.getLogger(td.matchers.isA(Object))).thenReturn(logger);
td.when(core.resolveConfig(td.matchers.isA(Object), td.matchers.isA(Object), td.matchers.isA(Object))).thenResolve({
plugins: {},
options: { repositoryUrl: "https://example.com/repo.git", dryRun: true },
});
const semanticRelease = (await import("../index.js")).default;
await semanticRelease({});
const [{ args }] = td.explain(core.default).calls;
const [callArg] = args;
const { context } = callArg;
t.false("skipRelease" in context);
td.verify(logger.warn("This run was not triggered in a known CI environment, running in dry-run mode."));
});