Skip to content

feat: init @semantic-release/core#1

Merged
babblebey merged 59 commits into
betafrom
start
Jun 15, 2026
Merged

feat: init @semantic-release/core#1
babblebey merged 59 commits into
betafrom
start

Conversation

@babblebey

@babblebey babblebey commented Jun 3, 2026

Copy link
Copy Markdown
Member

Phase 1: Repository and Package Scaffolding

Objective: Introduce package boundaries with minimal behavior change.

Checklist:

  • Create packages/core (or equivalent) with package metadata for @semantic-release/core.
  • Move/copy core files (index.js, lib/, type definitions) into core package structure.
  • Set module exports/types fields correctly for ESM consumers.
  • Add package-level tests/lint config wiring for core.

Deliverables:

  • Buildable/installable @semantic-release/core package in repository.
  • CI can run tests against both wrapper and core packages. (Core package side scaffolding complete; wrapper CI wiring remains for Phase 3/4 integration.)

Phase 2: Core Decoupling and Default Behavior Ownership

Objective: Make core fully composable and remove default plugin assumptions from core.

Checklist:

  • Change core config defaults so plugins is empty in core package.
  • Add explicit validation and actionable error when required steps are missing (e.g., analyzeCommits).
  • Isolate or inject terminal rendering formatter to avoid hard dependency on CLI-oriented renderer.
  • Ensure core does not depend on wrapper-only dependencies (yargs, CLI-only renderer packages).
  • Keep plugin loading behavior and plugin step contracts unchanged.

Deliverables:

  • Core runs with user-provided plugin lists.
  • Core fails fast with clear messages when mandatory lifecycle setup is missing.

Phase 3: Wrapper Package Compatibility Layer (semantic-release)

Objective: Preserve existing user behavior by making semantic-release a thin adapter.

Checklist:

  • Update wrapper index.js to delegate execution to @semantic-release/core.
  • Preserve exported API shape currently expected by programmatic users.
  • Keep CLI in wrapper package and maintain current option parsing/flags.
  • Inject current default plugin list from wrapper to emulate existing behavior.
  • Verify wrapper still masks sensitive output and preserves current logging style.

Deliverables:

  • Existing semantic-release commands work with no user config changes.
  • Wrapper package owns defaults and CLI while core remains neutral.

Reference: https://github.com/semantic-release/semantic-release/tree/feat/core-integration

Phase 4: Test Strategy and Regression Hardening

Objective: Prove no regressions in wrapper and expected behavior in core.

Checklist:

  • Add/adjust unit tests for core defaults and validation errors.
  • Add wrapper tests proving default plugin behavior parity with pre-split behavior.
  • Add integration tests for custom plugin stacks using @semantic-release/core.
  • Validate dry-run behavior, branch constraints, and fail/success hooks across both packages.
  • Ensure snapshot/log-output tests account for formatter abstraction changes.

Deliverables:

  • Green focused test matrix covering core standalone usage and wrapper compatibility.
  • Clear evidence of behavior parity for existing users.

Phase 4.5: Cracking core 😤

Objective: Make core composable and IMPERATIVELY 100% backward compactible to semantic-release

Checklist:

  • Pack @semantic-release/commit-analyzer as default core plugin with fallback support - support cases below
    • When built plugin pipeline has no analyzeCommit step implementation - fallback to core's packed @semantic-release/commit-analyzer
  • Support inline/direct plugins composition allowing user to pass plugin configuration with plain array object/sting to core
    • Build plugin pipeline from input
    • Make direct composition highest priority for plugin ahead of config (releaserc) file's plugins field, including ones built from sharable config - making direct composition the most authoritative plugin source
  • Keep support for config-driven plugins passable to core
    • Plugin pipeline is already built from this with getConfig - so expose this as an api from core
  • Support semantic-release default 4 plugins (@semantic-release/commit-analyzer, @semantic-release/release-notes-generator, @semantic-release/npm, @semantic-release/github) regardless of core having its own 1 default plugin (@semantic-release/commit-analyzer)
    • Assume semantic-release a wrapper built on core, allow wrappers the ability to build their own default config/plugins with fallback support to core commit analyzer when wrapper's default does not have any plugin that implements the analyzeCommits step
    • Support normal config overriding/prioritization behavior when a release config file is present regardless of default with fallback support to core's packed commit analyzer when wrapper's default or consumer's config does not have any plugin that implements the analyzeCommits step
  • Accept marked-terminal instance as args to render terminal markdown???
  • ......new requirement?????

Deliverables

  • semantic-release/core installable in semantic-release with zero breaking

Phase 5: Documentation and Migration Guidance

Objective: Make adoption and upgrade path clear.

Checklist:

  • Add @semantic-release/core usage docs with minimal and advanced examples.
  • Update semantic-release docs to explain default behavior remains and where customization lives.
  • Publish migration guidance for users who want custom CLIs/plugin stacks.
  • Document dependency ownership (what is bundled in wrapper vs expected in core consumers).
  • Update TypeScript examples for both packages.

Deliverables:

Phase 6: Release and Rollout

Objective: Ship safely with clear communication and rollback options.

Checklist:

  • Publish @semantic-release/core initial version with release notes.
  • Publish updated semantic-release wrapper release with explicit compatibility notes.
  • Monitor issue tracker for integration and plugin-resolution regressions.
  • Prepare patch follow-up path for wrapper compatibility issues.
  • Collect user feedback on core composability and CLI extension experience.

Deliverables:

  • Stable release of both packages.
  • Post-release triage checklist executed.

Related Issue

babblebey added 9 commits June 2, 2026 08:50
- Add `get-last-release.js` to determine the last tagged release.
- Introduce `get-logger.js` for logging purposes.
- Create `get-next-version.js` to calculate the next version based on the last release.
- Implement `get-release-to-add.js` to find releases merged from higher branches.
- Add `git.js` for Git operations including fetching tags and commits.
- Introduce `hide-sensitive.js` to mask sensitive environment variables.
- Create `plugins/index.js` to manage plugin loading and configuration.
- Implement `plugins/normalize.js` for normalizing plugin options.
- Add `plugins/pipeline.js` to execute plugins in a pipeline.
- Create `plugins/utils.js` for utility functions related to plugins.
- Implement `utils.js` for various utility functions including version handling.
- Add `verify.js` to validate the configuration and environment.
- Update `package.json` to reflect new structure and dependencies.
…ove linting scripts

- Added "types" field to specify TypeScript definitions file.
- Updated "exports" to include types alongside the default entry point.
- Included "index.d.ts" in the "files" array for distribution.
- Added "lint:core" script to run core linting.
- Updated "test" script to include a "test:core" alias for consistency.
- Changed the test command to use AVA with verbose output.
- Added AVA configuration for test files, node arguments, and timeout.
- Updated devDependencies to include AVA version 8.0.1.
babblebey added 9 commits June 4, 2026 18:43
- Introduced a noop plugin for testing purposes.
- Added a result configuration plugin to return pluginConfig and context.
- Enhanced get-config tests to validate plugin options and context handling.
- Created git utility functions for tagging and adding notes.
- Implemented extensive tests for plugin normalization, including various input formats and error handling.
- Developed pipeline tests to ensure sequential execution of plugin functions with error handling.
- Added utility tests for plugin validation and loading mechanisms.
- Ensured compatibility with shareable config modules and proper error reporting for invalid plugin configurations.
…ve data, utility functions, and verification logic

- Implemented tests for various git operations including fetching, tagging, and branch management in `git.test.js`.
- Added tests for hiding sensitive environment variables in `hide-sensitive.test.js`.
- Created utility function tests in `utils.test.js` covering version extraction and comparison.
- Developed verification tests in `verify.test.js` to ensure proper error handling and validation of branch and tag formats.
@socket-security

socket-security Bot commented Jun 6, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @pnpm/network.ca-file is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/@semantic-release/commit-analyzer@13.0.1npm/@pnpm/network.ca-file@1.0.2

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@pnpm/network.ca-file@1.0.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm es-abstract is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/ls-engines@0.10.0npm/es-abstract@1.24.2

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/es-abstract@1.24.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm execa is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/execa@9.6.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/execa@9.6.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm highlight.js is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/@semantic-release/commit-analyzer@13.0.1npm/highlight.js@10.7.3

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/highlight.js@10.7.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm js-yaml is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/cosmiconfig@9.0.1npm/js-yaml@4.2.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/js-yaml@4.2.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm npm is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/@semantic-release/commit-analyzer@13.0.1npm/npm@11.16.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/npm@11.16.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm npm is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/@semantic-release/commit-analyzer@13.0.1npm/npm@11.16.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/npm@11.16.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@babblebey
babblebey changed the base branch from main to beta June 6, 2026 19:10
@babblebey
babblebey marked this pull request as ready for review June 9, 2026 21:50
@gr2m

gr2m commented Jun 10, 2026

Copy link
Copy Markdown
Member

Phase 6: Release and Rollout

Objective: Ship safely with clear communication and rollback options.

Checklist:

  • Publish @semantic-release/core initial version with release notes.
  • Publish updated semantic-release wrapper release with explicit compatibility notes.
  • Monitor issue tracker for integration and plugin-resolution regressions.
  • Prepare patch follow-up path for wrapper compatibility issues.
  • Collect user feedback on core composability and CLI extension experience.

Deliverables:

  • Stable release of both packages.
  • Post-release triage checklist executed.

I would add a follow up issue with the above checklist as deliverable

@babblebey babblebey mentioned this pull request Jun 10, 2026
5 tasks

@gr2m gr2m left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two things I couldn't asses for myself in detail yet but didn't want to block the PR farther, we can do follow ups to investigate

  • options.originalRepositoryURL is undefined for every direct core consumer. index.js:49 logs Run automated release ... on repository ${options.originalRepositoryURL}, but
    nothing in core sets that field — upstream set it in the entry point, the wrapper branch sets it manually, and core's own integration test has to set it by hand
    (test/integration.test.js:24). Anyone following the README examples gets "on repository undefined". resolveConfig should set it (or run() should capture options.repositoryUrl
    before getGitAuthUrl overwrites it with the credential-embedding URL — callers shouldn't need to know this internal detail).

  • The output formatter was removed, not injected. formatOutput is a hardcoded identity function, so dry-run release notes and error details (markdown) print raw to the
    terminal. Phase 2's "Isolate or inject terminal rendering formatter" is checked, but there's no injection point — and the wrapper can't compensate because core writes to
    stdout/stderr itself (the wrapper branch even still carries marked/marked-terminal as now-dead dependencies). The PR's own Phase 4.5 leaves "Accept marked-terminal instance as
    args???" unchecked while claiming "IMPERATIVELY 100% backward compatible". Since fixing this later changes core's public API, I'd add the injection point now: accept an
    optional formatOutput on the input (defaulting to identity), and have the wrapper pass its marked-terminal renderer.

And a few smanller nits

  • Context validation: the default export validates context.options and plugins with clear TypeErrors, but omitting envCi, logger, stdout, or stderr produces destructuring
    crashes deep inside run(). Validate the full contract up front — it's literally Phase 2's "fails fast with clear messages" goal.
  • index.d.ts accuracy: doc comments still claim the default plugins are the four wrapper plugins (stale for core); the plugins input is typed only as Record<string, fn>
    although arrays of plugin specs are accepted (that's the headline "direct composition" feature); FailContext.errors shadows the global AggregateError.
  • Test coverage gaps in this repo: resolve-config.test.js is 147 lines / 5 tests vs upstream's 729-line get-config.test.js — the extends/shareable-config edge cases are
    untested here despite the file being modified. And the ~2,000-line behavioral suite for the engine now lives only in the wrapper repo, so core can regress independently of its
    own CI. Port these over time.
  • README nits: getLogger streams are documented as "optional; defaults are process streams" but get-logger.js has no defaults — getLogger({}) produces a broken logger. Also
    document explicitly that core does not do CI guards (PR skip, auto dry-run) and does not set GIT_AUTHOR_*/GIT_ASKPASS env vars — callers own those.
  • package.json hygiene: drop the "start": "node index.js" script (meaningless for a library); the prettier glob "*.{js,json,md}" only checks root-level files, so lib/ and
    test/ are unlinted; no eslint despite upstream having lint rules.
  • Library behavior of hookStd: core always hooks the global process.stdout/process.stderr for sensitive-value masking — defensible, but surprising for an embeddable library;
    consider scoping to the provided streams or making it configurable.
  • The rewritten error-doc links (semantic-release.org/usage/..., /foundation/plugins) all resolve correctly — I spot-checked them.

Comment thread package.json
@babblebey

Copy link
Copy Markdown
Member Author

Addressed the nits except these...

  • Test coverage gaps in this repo: resolve-config.test.js is 147 lines / 5 tests vs upstream's 729-line get-config.test.js — the extends/shareable-config edge cases are
    untested here despite the file being modified. And the ~2,000-line behavioral suite for the engine now lives only in the wrapper repo, so core can regress independently of its
    own CI. Port these over time.

...and...

  • Library behavior of hookStd: core always hooks the global process.stdout/process.stderr for sensitive-value masking — defensible, but surprising for an embeddable library;
    consider scoping to the provided streams or making it configurable.

I'd prefer in a follow-up PR 🤔

@babblebey
babblebey merged commit 3e29e37 into beta Jun 15, 2026
8 checks passed
@babblebey
babblebey deleted the start branch June 15, 2026 19:36
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0-beta.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants