@mridang/semantic-release-gomod 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +134 -0
- package/dist/exec.d.ts +15 -0
- package/dist/exec.js +8 -0
- package/dist/exec.js.map +1 -0
- package/dist/gomod.d.ts +65 -0
- package/dist/gomod.js +177 -0
- package/dist/gomod.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.js +113 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin-config.d.ts +58 -0
- package/dist/plugin-config.js +43 -0
- package/dist/plugin-config.js.map +1 -0
- package/package.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Semantic Release - Gomod
|
|
2
|
+
|
|
3
|
+
A [semantic-release](https://github.com/semantic-release/semantic-release)
|
|
4
|
+
plugin to automatically tag and release multi-module Go repositories.
|
|
5
|
+
|
|
6
|
+
This plugin automates the release workflow for Go monorepos that use the
|
|
7
|
+
multi-module pattern. During `prepare`, it pins every submodule `go.mod`
|
|
8
|
+
require line that references the root module to the new release version and
|
|
9
|
+
optionally runs `go mod tidy`. During `publish`, it creates and pushes a
|
|
10
|
+
per-module git tag for every `go.mod` in the repository, following the
|
|
11
|
+
standard `<subpath>/vX.Y.Z` naming that the Go module proxy requires. This
|
|
12
|
+
eliminates the need for manual tagging scripts, ensuring every module in
|
|
13
|
+
your monorepo is consistently released together.
|
|
14
|
+
|
|
15
|
+
## Why?
|
|
16
|
+
|
|
17
|
+
Releasing a multi-module Go repository involves more than just creating a
|
|
18
|
+
single Git tag. For each submodule to be resolvable by the Go module proxy
|
|
19
|
+
and `go get`, it must have its own version tag in the form
|
|
20
|
+
`<path>/vX.Y.Z` (e.g., `assert/cert/manager/v1.2.3`). Keeping require
|
|
21
|
+
lines pinned to the new version across all submodules adds further
|
|
22
|
+
complexity. This multi-step process is a common point of friction in an
|
|
23
|
+
otherwise automated pipeline.
|
|
24
|
+
|
|
25
|
+
Without this plugin, developers typically face one of two issues:
|
|
26
|
+
|
|
27
|
+
- **Manual Tagging:** The most common method is a shell script that walks
|
|
28
|
+
the repository, updates require lines, and pushes tags for each `go.mod`.
|
|
29
|
+
This adds toil, is error-prone, and is not reusable across projects.
|
|
30
|
+
- **Incomplete Automation:** Other tooling may create the root tag but
|
|
31
|
+
skip submodule tags, leaving submodules unreachable via `go get` until
|
|
32
|
+
someone manually creates the missing tags.
|
|
33
|
+
|
|
34
|
+
This plugin provides a lightweight and direct solution. It auto-discovers
|
|
35
|
+
every `go.mod` in the repository, pins inter-module dependencies to the
|
|
36
|
+
new version, and creates the correct per-module tag for each one — all
|
|
37
|
+
within a standard `semantic-release` pipeline with zero required
|
|
38
|
+
configuration.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
Install using NPM with the following command:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
npm install --save-dev @mridang/semantic-release-gomod
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
To use this plugin, add it to your semantic-release configuration file
|
|
51
|
+
(e.g., `.releaserc.js`, `release.config.js`, or in your `package.json`).
|
|
52
|
+
|
|
53
|
+
The plugin's `prepare` step pins require lines in submodule `go.mod` files.
|
|
54
|
+
For these changes to be included in the release commit, the plugin should be
|
|
55
|
+
placed **before** `@semantic-release/git` in the `plugins` array.
|
|
56
|
+
|
|
57
|
+
> [!IMPORTANT]
|
|
58
|
+
> This plugin updates `go.mod` files during the `prepare` step. For these
|
|
59
|
+
> changes to be included in your release commit, you **must** configure
|
|
60
|
+
> the `@semantic-release/git` plugin to include your `go.mod` and `go.sum`
|
|
61
|
+
> files in its `assets` array.
|
|
62
|
+
|
|
63
|
+
### Example Configuration (`.releaserc.js`)
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
module.exports = {
|
|
67
|
+
branches: ['main', 'next'],
|
|
68
|
+
plugins: [
|
|
69
|
+
'@semantic-release/commit-analyzer',
|
|
70
|
+
'@mridang/semantic-release-gomod',
|
|
71
|
+
'@semantic-release/release-notes-generator',
|
|
72
|
+
'@semantic-release/github',
|
|
73
|
+
[
|
|
74
|
+
'@semantic-release/git',
|
|
75
|
+
{
|
|
76
|
+
assets: ['go.mod', 'go.sum', '**/go.mod', '**/go.sum'],
|
|
77
|
+
message:
|
|
78
|
+
'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Configuration Options
|
|
86
|
+
|
|
87
|
+
All options are case-sensitive and lowercased in the JSON configuration.
|
|
88
|
+
|
|
89
|
+
- **`modules` (string | string[], optional):**
|
|
90
|
+
Glob patterns (relative to the repository root) matching submodule
|
|
91
|
+
`go.mod` files. When omitted, the plugin auto-discovers every `go.mod`
|
|
92
|
+
in the repository except the root-level one.
|
|
93
|
+
Example: `["assert/**/go.mod", "env/**/go.mod"]`.
|
|
94
|
+
|
|
95
|
+
- **`skipGoModTidy` (boolean, optional):**
|
|
96
|
+
Skip running `go mod tidy` in each submodule directory after pinning the
|
|
97
|
+
require version. Useful when Go is not available in the CI environment or
|
|
98
|
+
for debugging. Default: `false`.
|
|
99
|
+
|
|
100
|
+
- **`pushTags` (boolean, optional):**
|
|
101
|
+
Push the created submodule tags to the remote origin after creating them
|
|
102
|
+
locally. Set to `false` to create tags locally only. Default: `true`.
|
|
103
|
+
|
|
104
|
+
## Tag Naming
|
|
105
|
+
|
|
106
|
+
The git tag created for each module is derived from the relative path of
|
|
107
|
+
its `go.mod` directory to the repository root:
|
|
108
|
+
|
|
109
|
+
| `go.mod` location | Git tag |
|
|
110
|
+
| ------------------------------ | ---------------------------- |
|
|
111
|
+
| `./go.mod` | `v1.2.3` |
|
|
112
|
+
| `./assert/cert/manager/go.mod` | `assert/cert/manager/v1.2.3` |
|
|
113
|
+
| `./env/flux/helm/go.mod` | `env/flux/helm/v1.2.3` |
|
|
114
|
+
|
|
115
|
+
## Known Issues
|
|
116
|
+
|
|
117
|
+
- None.
|
|
118
|
+
|
|
119
|
+
## Useful links
|
|
120
|
+
|
|
121
|
+
- **[Go Modules Reference](https://go.dev/ref/mod):** Official Go modules
|
|
122
|
+
documentation.
|
|
123
|
+
- **[Module version numbering](https://go.dev/doc/modules/version-numbers):**
|
|
124
|
+
How Go module version numbers work.
|
|
125
|
+
|
|
126
|
+
## Contributing
|
|
127
|
+
|
|
128
|
+
If you have suggestions for how this plugin could be improved, or
|
|
129
|
+
want to report a bug, open an issue — we'd love all and any
|
|
130
|
+
contributions.
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
Apache License 2.0 © 2024 Mridang Agarwalla
|
package/dist/exec.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ExecSyncOptions } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* A function that executes a shell command synchronously.
|
|
4
|
+
* Accepting this as a parameter makes the callers unit-testable
|
|
5
|
+
* without needing to mock Node.js built-in modules.
|
|
6
|
+
*
|
|
7
|
+
* Implementations must throw when the command exits with a non-zero
|
|
8
|
+
* status (matching the default behaviour of Node's `execSync`).
|
|
9
|
+
* Callers are responsible for catching and handling failures.
|
|
10
|
+
*/
|
|
11
|
+
export type ExecFn = (cmd: string, opts?: ExecSyncOptions) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Default executor that delegates to Node's built-in `execSync`.
|
|
14
|
+
*/
|
|
15
|
+
export declare const defaultExec: ExecFn;
|
package/dist/exec.js
ADDED
package/dist/exec.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAwB,MAAM,eAAe,CAAC;AAa/E;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAW,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;IAC/C,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC,CAAC"}
|
package/dist/gomod.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type ExecFn } from './exec.js';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal logger interface compatible with the semantic-release context logger.
|
|
4
|
+
*/
|
|
5
|
+
interface Logger {
|
|
6
|
+
log(message: string, ...args: unknown[]): void;
|
|
7
|
+
warn(message: string, ...args: unknown[]): void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Walk `root` recursively and return the absolute paths of every
|
|
11
|
+
* go.mod file found, excluding the root-level go.mod itself.
|
|
12
|
+
*
|
|
13
|
+
* When `globPatterns` are provided the walk is skipped and the
|
|
14
|
+
* patterns are expanded against `root` instead.
|
|
15
|
+
*
|
|
16
|
+
* @param root Absolute path to the repository root.
|
|
17
|
+
* @param globPatterns Optional array of glob patterns relative to root.
|
|
18
|
+
* @returns Sorted array of absolute go.mod paths (submodules only).
|
|
19
|
+
*/
|
|
20
|
+
export declare function discoverSubmoduleGoMods(root: string, globPatterns?: readonly string[]): readonly string[];
|
|
21
|
+
/**
|
|
22
|
+
* Read a go.mod file and extract the module declaration.
|
|
23
|
+
*
|
|
24
|
+
* @param goModPath Absolute path to the go.mod file.
|
|
25
|
+
* @returns The module import path, e.g. `"github.com/mridang/wilhelm"`.
|
|
26
|
+
* @throws Error if no `module` line is found.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readModulePath(goModPath: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Update every `require` line in a go.mod file whose import path
|
|
31
|
+
* starts with `rootModule`, replacing the version with `newVersion`.
|
|
32
|
+
* Lines with `// indirect` comments are preserved as-is.
|
|
33
|
+
*
|
|
34
|
+
* Handles both single-line requires and require blocks.
|
|
35
|
+
*
|
|
36
|
+
* @param filePath Absolute path to the go.mod file to rewrite.
|
|
37
|
+
* @param rootModule Root module import path (e.g. `"github.com/mridang/wilhelm"`).
|
|
38
|
+
* @param newVersion New semver string without leading `v` (e.g. `"1.2.3"`).
|
|
39
|
+
*/
|
|
40
|
+
export declare function updateGoModRequires(filePath: string, rootModule: string, newVersion: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Derive the git tag prefix for a submodule given its go.mod path
|
|
43
|
+
* and the repository root.
|
|
44
|
+
*
|
|
45
|
+
* - Root module (`./go.mod`) → `""` (tag = `"v1.2.3"`)
|
|
46
|
+
* - Submodule (`./assert/cert/manager/go.mod`) → `"assert/cert/manager"`
|
|
47
|
+
*
|
|
48
|
+
* @param goModPath Absolute path to the go.mod file.
|
|
49
|
+
* @param repoRoot Absolute path to the repository root.
|
|
50
|
+
* @returns Tag prefix string (empty string for the root module).
|
|
51
|
+
*/
|
|
52
|
+
export declare function deriveTagPrefix(goModPath: string, repoRoot: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Create a git tag locally and optionally push it to origin.
|
|
55
|
+
* Silently ignores the case where the tag already exists so the
|
|
56
|
+
* plugin can be called idempotently.
|
|
57
|
+
*
|
|
58
|
+
* @param repoRoot Absolute path to the repository root.
|
|
59
|
+
* @param tag Full tag string, e.g. `"assert/cert/manager/v1.2.3"`.
|
|
60
|
+
* @param push When true, push the tag to `origin`.
|
|
61
|
+
* @param logger semantic-release logger.
|
|
62
|
+
* @param exec Command executor (injectable for testing).
|
|
63
|
+
*/
|
|
64
|
+
export declare function createAndPushTag(repoRoot: string, tag: string, push: boolean, logger: Logger, exec?: ExecFn): void;
|
|
65
|
+
export {};
|
package/dist/gomod.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { defaultExec } from './exec.js';
|
|
4
|
+
/**
|
|
5
|
+
* Read a directory, returning an empty array on any I/O error.
|
|
6
|
+
*/
|
|
7
|
+
function safeReadDir(dir) {
|
|
8
|
+
try {
|
|
9
|
+
return fs.readdirSync(dir, { withFileTypes: true });
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Walk `root` recursively and return the absolute paths of every
|
|
17
|
+
* go.mod file found, excluding the root-level go.mod itself.
|
|
18
|
+
*
|
|
19
|
+
* When `globPatterns` are provided the walk is skipped and the
|
|
20
|
+
* patterns are expanded against `root` instead.
|
|
21
|
+
*
|
|
22
|
+
* @param root Absolute path to the repository root.
|
|
23
|
+
* @param globPatterns Optional array of glob patterns relative to root.
|
|
24
|
+
* @returns Sorted array of absolute go.mod paths (submodules only).
|
|
25
|
+
*/
|
|
26
|
+
export function discoverSubmoduleGoMods(root, globPatterns) {
|
|
27
|
+
if (globPatterns && globPatterns.length > 0) {
|
|
28
|
+
const results = globPatterns.flatMap((pattern) => expandGlob(root, pattern));
|
|
29
|
+
return [...new Set(results)].sort();
|
|
30
|
+
}
|
|
31
|
+
// Auto-discover: walk the tree
|
|
32
|
+
return walkForGoMods(root)
|
|
33
|
+
.filter((f) => f !== path.join(root, 'go.mod'))
|
|
34
|
+
.sort();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Recursively walk `dir` and return absolute paths of all go.mod files.
|
|
38
|
+
*/
|
|
39
|
+
function walkForGoMods(dir) {
|
|
40
|
+
return safeReadDir(dir).flatMap((entry) => {
|
|
41
|
+
if (entry.name === 'vendor' || entry.name === 'node_modules')
|
|
42
|
+
return [];
|
|
43
|
+
const full = path.join(dir, entry.name);
|
|
44
|
+
if (entry.isDirectory())
|
|
45
|
+
return [...walkForGoMods(full)];
|
|
46
|
+
if (entry.isFile() && entry.name === 'go.mod')
|
|
47
|
+
return [full];
|
|
48
|
+
return [];
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Minimal glob expander supporting `**` as a recursive wildcard.
|
|
53
|
+
* Only handles the patterns this plugin actually uses, e.g.
|
|
54
|
+
* `"assert/**\/go.mod"` or `"env/*\/go.mod"`.
|
|
55
|
+
*/
|
|
56
|
+
function expandGlob(root, pattern) {
|
|
57
|
+
return matchParts(root, pattern.split('/'));
|
|
58
|
+
}
|
|
59
|
+
function matchParts(dir, parts) {
|
|
60
|
+
if (parts.length === 0)
|
|
61
|
+
return [];
|
|
62
|
+
const [head, ...tail] = parts;
|
|
63
|
+
if (head === '**') {
|
|
64
|
+
// Zero levels: continue with tail from current dir.
|
|
65
|
+
// One or more levels: descend into each subdirectory.
|
|
66
|
+
return [
|
|
67
|
+
...matchParts(dir, tail),
|
|
68
|
+
...safeReadDir(dir)
|
|
69
|
+
.filter((e) => e.isDirectory())
|
|
70
|
+
.flatMap((e) => matchParts(path.join(dir, e.name), parts)),
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
if (tail.length === 0) {
|
|
74
|
+
// Last segment — must be a file (single statSync avoids TOCTOU)
|
|
75
|
+
const candidate = path.join(dir, head);
|
|
76
|
+
try {
|
|
77
|
+
return fs.statSync(candidate).isFile() ? [candidate] : [];
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (head === '*') {
|
|
84
|
+
// Single-level wildcard
|
|
85
|
+
return safeReadDir(dir)
|
|
86
|
+
.filter((e) => e.isDirectory())
|
|
87
|
+
.flatMap((e) => matchParts(path.join(dir, e.name), tail));
|
|
88
|
+
}
|
|
89
|
+
// Literal segment — safeReadDir handles missing/unreadable paths gracefully
|
|
90
|
+
return matchParts(path.join(dir, head), tail);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Read a go.mod file and extract the module declaration.
|
|
94
|
+
*
|
|
95
|
+
* @param goModPath Absolute path to the go.mod file.
|
|
96
|
+
* @returns The module import path, e.g. `"github.com/mridang/wilhelm"`.
|
|
97
|
+
* @throws Error if no `module` line is found.
|
|
98
|
+
*/
|
|
99
|
+
export function readModulePath(goModPath) {
|
|
100
|
+
const content = fs.readFileSync(goModPath, 'utf8');
|
|
101
|
+
for (const line of content.split('\n')) {
|
|
102
|
+
const m = line.match(/^module\s+(\S+)/);
|
|
103
|
+
if (m)
|
|
104
|
+
return m[1];
|
|
105
|
+
}
|
|
106
|
+
throw new Error(`No module declaration found in ${goModPath}`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Update every `require` line in a go.mod file whose import path
|
|
110
|
+
* starts with `rootModule`, replacing the version with `newVersion`.
|
|
111
|
+
* Lines with `// indirect` comments are preserved as-is.
|
|
112
|
+
*
|
|
113
|
+
* Handles both single-line requires and require blocks.
|
|
114
|
+
*
|
|
115
|
+
* @param filePath Absolute path to the go.mod file to rewrite.
|
|
116
|
+
* @param rootModule Root module import path (e.g. `"github.com/mridang/wilhelm"`).
|
|
117
|
+
* @param newVersion New semver string without leading `v` (e.g. `"1.2.3"`).
|
|
118
|
+
*/
|
|
119
|
+
export function updateGoModRequires(filePath, rootModule, newVersion) {
|
|
120
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
121
|
+
// Escape slashes and dots in the module path for use in regex
|
|
122
|
+
const escaped = rootModule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
123
|
+
// Match: <module_path_starting_with_root> <v-prefixed-version> [optional comment]
|
|
124
|
+
const pattern = new RegExp(`(${escaped}[^\\s]*)\\s+v[0-9]\\S*`, 'g');
|
|
125
|
+
const updated = content.replace(pattern, `$1 v${newVersion}`);
|
|
126
|
+
if (updated !== content) {
|
|
127
|
+
fs.writeFileSync(filePath, updated, 'utf8');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Derive the git tag prefix for a submodule given its go.mod path
|
|
132
|
+
* and the repository root.
|
|
133
|
+
*
|
|
134
|
+
* - Root module (`./go.mod`) → `""` (tag = `"v1.2.3"`)
|
|
135
|
+
* - Submodule (`./assert/cert/manager/go.mod`) → `"assert/cert/manager"`
|
|
136
|
+
*
|
|
137
|
+
* @param goModPath Absolute path to the go.mod file.
|
|
138
|
+
* @param repoRoot Absolute path to the repository root.
|
|
139
|
+
* @returns Tag prefix string (empty string for the root module).
|
|
140
|
+
*/
|
|
141
|
+
export function deriveTagPrefix(goModPath, repoRoot) {
|
|
142
|
+
return path.relative(repoRoot, path.dirname(goModPath));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Create a git tag locally and optionally push it to origin.
|
|
146
|
+
* Silently ignores the case where the tag already exists so the
|
|
147
|
+
* plugin can be called idempotently.
|
|
148
|
+
*
|
|
149
|
+
* @param repoRoot Absolute path to the repository root.
|
|
150
|
+
* @param tag Full tag string, e.g. `"assert/cert/manager/v1.2.3"`.
|
|
151
|
+
* @param push When true, push the tag to `origin`.
|
|
152
|
+
* @param logger semantic-release logger.
|
|
153
|
+
* @param exec Command executor (injectable for testing).
|
|
154
|
+
*/
|
|
155
|
+
export function createAndPushTag(repoRoot, tag, push, logger, exec = defaultExec) {
|
|
156
|
+
try {
|
|
157
|
+
exec(`git tag "${tag}"`, { cwd: repoRoot, stdio: 'pipe' });
|
|
158
|
+
logger.log('Created tag %s', tag);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
162
|
+
if (msg.includes('already exists')) {
|
|
163
|
+
logger.log('Tag %s already exists, skipping', tag);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (push) {
|
|
170
|
+
exec(`git push origin "refs/tags/${tag}"`, {
|
|
171
|
+
cwd: repoRoot,
|
|
172
|
+
stdio: 'pipe',
|
|
173
|
+
});
|
|
174
|
+
logger.log('Pushed tag %s', tag);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=gomod.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gomod.js","sourceRoot":"","sources":["../src/gomod.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { PrepareContext, PublishContext, VerifyConditionsContext } from 'semantic-release';
|
|
2
|
+
import { type ExecFn } from './exec.js';
|
|
3
|
+
import { GomodPluginConfig } from './plugin-config.js';
|
|
4
|
+
/**
|
|
5
|
+
* Verify that all preconditions for the plugin are met:
|
|
6
|
+
* - A root `go.mod` exists in the working directory.
|
|
7
|
+
* - `git` is available on PATH.
|
|
8
|
+
*
|
|
9
|
+
* A warning (not an error) is emitted when no submodule go.mod files
|
|
10
|
+
* are found, since the plugin is still useful for single-module repos
|
|
11
|
+
* (it will create the root tag in the publish step).
|
|
12
|
+
*
|
|
13
|
+
* @param pluginConfig The plugin configuration.
|
|
14
|
+
* @param context The semantic-release context.
|
|
15
|
+
* @param exec Command executor (injectable for testing).
|
|
16
|
+
*/
|
|
17
|
+
export declare function verifyConditions(pluginConfig: GomodPluginConfig, context: VerifyConditionsContext, exec?: ExecFn): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Pin every submodule `go.mod` require line that references the root
|
|
20
|
+
* module (or any of its sub-paths) to the new release version.
|
|
21
|
+
*
|
|
22
|
+
* Optionally runs `go mod tidy` in each submodule directory afterward.
|
|
23
|
+
* The actual commit is handled by `@semantic-release/git`.
|
|
24
|
+
*
|
|
25
|
+
* @param pluginConfig The plugin configuration.
|
|
26
|
+
* @param context The semantic-release context.
|
|
27
|
+
* @param exec Command executor (injectable for testing).
|
|
28
|
+
*/
|
|
29
|
+
export declare function prepare(pluginConfig: GomodPluginConfig, context: PrepareContext, exec?: ExecFn): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Create and push a git tag for every module in the repository,
|
|
32
|
+
* including the root module.
|
|
33
|
+
*
|
|
34
|
+
* semantic-release creates the root tag (`vX.Y.Z`) before calling
|
|
35
|
+
* publish; this step creates it silently when it already exists and
|
|
36
|
+
* then creates all submodule tags
|
|
37
|
+
* (e.g. `assert/cert/manager/vX.Y.Z`).
|
|
38
|
+
*
|
|
39
|
+
* @param pluginConfig The plugin configuration.
|
|
40
|
+
* @param context The semantic-release context.
|
|
41
|
+
* @param exec Command executor (injectable for testing).
|
|
42
|
+
*/
|
|
43
|
+
export declare function publish(pluginConfig: GomodPluginConfig, context: PublishContext, exec?: ExecFn): Promise<void>;
|
|
44
|
+
declare const _default: {
|
|
45
|
+
readonly verifyConditions: typeof verifyConditions;
|
|
46
|
+
readonly prepare: typeof prepare;
|
|
47
|
+
readonly publish: typeof publish;
|
|
48
|
+
};
|
|
49
|
+
export default _default;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import SemanticReleaseError from '@semantic-release/error';
|
|
4
|
+
import { defaultExec } from './exec.js';
|
|
5
|
+
import { GomodConfig } from './plugin-config.js';
|
|
6
|
+
import { createAndPushTag, deriveTagPrefix, discoverSubmoduleGoMods, readModulePath, updateGoModRequires, } from './gomod.js';
|
|
7
|
+
/**
|
|
8
|
+
* Verify that all preconditions for the plugin are met:
|
|
9
|
+
* - A root `go.mod` exists in the working directory.
|
|
10
|
+
* - `git` is available on PATH.
|
|
11
|
+
*
|
|
12
|
+
* A warning (not an error) is emitted when no submodule go.mod files
|
|
13
|
+
* are found, since the plugin is still useful for single-module repos
|
|
14
|
+
* (it will create the root tag in the publish step).
|
|
15
|
+
*
|
|
16
|
+
* @param pluginConfig The plugin configuration.
|
|
17
|
+
* @param context The semantic-release context.
|
|
18
|
+
* @param exec Command executor (injectable for testing).
|
|
19
|
+
*/
|
|
20
|
+
export async function verifyConditions(pluginConfig, context, exec = defaultExec) {
|
|
21
|
+
const { logger } = context;
|
|
22
|
+
const cwd = context.cwd ?? process.cwd();
|
|
23
|
+
const config = new GomodConfig(pluginConfig);
|
|
24
|
+
const rootGoMod = path.join(cwd, 'go.mod');
|
|
25
|
+
if (!fs.existsSync(rootGoMod)) {
|
|
26
|
+
throw new SemanticReleaseError('go.mod not found.', 'EMISSINGGOMOD', `A \`go.mod\` file is required at the repository root but was not found in ${cwd}. Ensure the plugin is configured for a Go module repository.`);
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
exec('git --version', { stdio: 'pipe' });
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new SemanticReleaseError('git is not available.', 'ENOGIT', 'The `git` executable could not be found. Ensure git is installed and available on PATH.');
|
|
33
|
+
}
|
|
34
|
+
const submodules = discoverSubmoduleGoMods(cwd, config.getModules());
|
|
35
|
+
if (submodules.length === 0) {
|
|
36
|
+
logger.log('No submodule go.mod files found — operating in single-module mode.');
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
logger.log('Found %d submodule(s).', submodules.length);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Pin every submodule `go.mod` require line that references the root
|
|
44
|
+
* module (or any of its sub-paths) to the new release version.
|
|
45
|
+
*
|
|
46
|
+
* Optionally runs `go mod tidy` in each submodule directory afterward.
|
|
47
|
+
* The actual commit is handled by `@semantic-release/git`.
|
|
48
|
+
*
|
|
49
|
+
* @param pluginConfig The plugin configuration.
|
|
50
|
+
* @param context The semantic-release context.
|
|
51
|
+
* @param exec Command executor (injectable for testing).
|
|
52
|
+
*/
|
|
53
|
+
export async function prepare(pluginConfig, context, exec = defaultExec) {
|
|
54
|
+
const { logger, nextRelease: { version }, } = context;
|
|
55
|
+
const cwd = context.cwd ?? process.cwd();
|
|
56
|
+
const config = new GomodConfig(pluginConfig);
|
|
57
|
+
const rootGoMod = path.join(cwd, 'go.mod');
|
|
58
|
+
const rootModule = readModulePath(rootGoMod);
|
|
59
|
+
logger.log('Root module: %s', rootModule);
|
|
60
|
+
const submodules = discoverSubmoduleGoMods(cwd, config.getModules());
|
|
61
|
+
if (submodules.length === 0) {
|
|
62
|
+
logger.log('No submodules to update.');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const goModPath of submodules) {
|
|
66
|
+
logger.log('Pinning requires in %s', path.relative(cwd, goModPath));
|
|
67
|
+
updateGoModRequires(goModPath, rootModule, version);
|
|
68
|
+
if (!config.isSkipGoModTidy()) {
|
|
69
|
+
const modDir = path.dirname(goModPath);
|
|
70
|
+
try {
|
|
71
|
+
exec('go mod tidy', { cwd: modDir, stdio: 'pipe' });
|
|
72
|
+
logger.log('go mod tidy OK in %s', path.relative(cwd, modDir));
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
76
|
+
logger.warn('go mod tidy failed in %s: %s', path.relative(cwd, modDir), msg);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
logger.log('Prepared %d submodule(s) for v%s.', submodules.length, version);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create and push a git tag for every module in the repository,
|
|
84
|
+
* including the root module.
|
|
85
|
+
*
|
|
86
|
+
* semantic-release creates the root tag (`vX.Y.Z`) before calling
|
|
87
|
+
* publish; this step creates it silently when it already exists and
|
|
88
|
+
* then creates all submodule tags
|
|
89
|
+
* (e.g. `assert/cert/manager/vX.Y.Z`).
|
|
90
|
+
*
|
|
91
|
+
* @param pluginConfig The plugin configuration.
|
|
92
|
+
* @param context The semantic-release context.
|
|
93
|
+
* @param exec Command executor (injectable for testing).
|
|
94
|
+
*/
|
|
95
|
+
export async function publish(pluginConfig, context, exec = defaultExec) {
|
|
96
|
+
const { logger, nextRelease: { version }, } = context;
|
|
97
|
+
const cwd = context.cwd ?? process.cwd();
|
|
98
|
+
const config = new GomodConfig(pluginConfig);
|
|
99
|
+
// All go.mod files: submodules + root
|
|
100
|
+
const submodules = discoverSubmoduleGoMods(cwd, config.getModules());
|
|
101
|
+
const allGoMods = [
|
|
102
|
+
path.join(cwd, 'go.mod'),
|
|
103
|
+
...submodules,
|
|
104
|
+
];
|
|
105
|
+
for (const goModPath of allGoMods) {
|
|
106
|
+
const prefix = deriveTagPrefix(goModPath, cwd);
|
|
107
|
+
const tag = prefix ? `${prefix}/v${version}` : `v${version}`;
|
|
108
|
+
createAndPushTag(cwd, tag, config.isPushTagsEnabled(), logger, exec);
|
|
109
|
+
}
|
|
110
|
+
logger.log('Tagged %d module(s) at v%s.', allGoMods.length, version);
|
|
111
|
+
}
|
|
112
|
+
export default { verifyConditions, prepare, publish };
|
|
113
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Config } from 'semantic-release';
|
|
2
|
+
/**
|
|
3
|
+
* Raw plugin configuration as provided by the user in their
|
|
4
|
+
* semantic-release config file. All fields are optional — the
|
|
5
|
+
* plugin works with zero configuration by auto-detecting all
|
|
6
|
+
* submodule go.mod files in the repository.
|
|
7
|
+
*/
|
|
8
|
+
export interface GomodPluginConfig extends Config {
|
|
9
|
+
/**
|
|
10
|
+
* Glob patterns (relative to cwd) that match submodule go.mod files.
|
|
11
|
+
* When omitted, the plugin walks the repository and treats every
|
|
12
|
+
* go.mod file except the root-level one as a submodule.
|
|
13
|
+
*
|
|
14
|
+
* @example ["assert/**\/go.mod", "env/**\/go.mod"]
|
|
15
|
+
*/
|
|
16
|
+
readonly modules?: string | readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* Skip running `go mod tidy` in each submodule directory after
|
|
19
|
+
* pinning the require version. Useful when Go is not available in
|
|
20
|
+
* the CI environment or for debugging. Defaults to false.
|
|
21
|
+
*/
|
|
22
|
+
readonly skipGoModTidy?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Push the created submodule tags to the remote origin after
|
|
25
|
+
* creating them locally. Set to false to create tags locally only.
|
|
26
|
+
* Defaults to true.
|
|
27
|
+
*/
|
|
28
|
+
readonly pushTags?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* GomodConfig wraps the raw plugin config and exposes derived values
|
|
32
|
+
* with sensible defaults. It centralises option reading so the plugin
|
|
33
|
+
* lifecycle hooks stay small and consistent.
|
|
34
|
+
*/
|
|
35
|
+
export declare class GomodConfig {
|
|
36
|
+
private readonly config;
|
|
37
|
+
constructor(config: GomodPluginConfig);
|
|
38
|
+
/**
|
|
39
|
+
* Returns the user-supplied glob patterns for submodule go.mod files,
|
|
40
|
+
* normalised to an array. Returns undefined when not configured,
|
|
41
|
+
* which signals the plugin to auto-discover.
|
|
42
|
+
*
|
|
43
|
+
* @returns Readonly array of glob strings, or undefined for auto-detection.
|
|
44
|
+
*/
|
|
45
|
+
getModules(): readonly string[] | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Whether to skip `go mod tidy` after pinning submodule versions.
|
|
48
|
+
*
|
|
49
|
+
* @returns true only when explicitly set to true.
|
|
50
|
+
*/
|
|
51
|
+
isSkipGoModTidy(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Whether to push submodule tags to origin after creating them.
|
|
54
|
+
*
|
|
55
|
+
* @returns true unless explicitly disabled.
|
|
56
|
+
*/
|
|
57
|
+
isPushTagsEnabled(): boolean;
|
|
58
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GomodConfig wraps the raw plugin config and exposes derived values
|
|
3
|
+
* with sensible defaults. It centralises option reading so the plugin
|
|
4
|
+
* lifecycle hooks stay small and consistent.
|
|
5
|
+
*/
|
|
6
|
+
export class GomodConfig {
|
|
7
|
+
config;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Returns the user-supplied glob patterns for submodule go.mod files,
|
|
13
|
+
* normalised to an array. Returns undefined when not configured,
|
|
14
|
+
* which signals the plugin to auto-discover.
|
|
15
|
+
*
|
|
16
|
+
* @returns Readonly array of glob strings, or undefined for auto-detection.
|
|
17
|
+
*/
|
|
18
|
+
getModules() {
|
|
19
|
+
const { modules } = this.config;
|
|
20
|
+
if (!modules)
|
|
21
|
+
return undefined;
|
|
22
|
+
if (typeof modules === 'string')
|
|
23
|
+
return [modules];
|
|
24
|
+
return modules;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Whether to skip `go mod tidy` after pinning submodule versions.
|
|
28
|
+
*
|
|
29
|
+
* @returns true only when explicitly set to true.
|
|
30
|
+
*/
|
|
31
|
+
isSkipGoModTidy() {
|
|
32
|
+
return this.config.skipGoModTidy === true;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether to push submodule tags to origin after creating them.
|
|
36
|
+
*
|
|
37
|
+
* @returns true unless explicitly disabled.
|
|
38
|
+
*/
|
|
39
|
+
isPushTagsEnabled() {
|
|
40
|
+
return this.config.pushTags !== false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=plugin-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-config.js","sourceRoot":"","sources":["../src/plugin-config.ts"],"names":[],"mappings":"AAiCA;;;;GAIG;AACH,MAAM,OAAO,WAAW;IACO;IAA7B,YAA6B,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;IAAG,CAAC;IAE1D;;;;;;OAMG;IACH,UAAU;QACR,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAClD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,IAAI,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,iBAAiB;QACf,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,KAAK,CAAC;IACxC,CAAC;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mridang/semantic-release-gomod",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"prepack": "tsc",
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"test": "jest --verbose --config=jest.config.mjs --runInBand",
|
|
9
|
+
"test:watch": "npm run test -- --watch",
|
|
10
|
+
"test:debug": "jest --verbose --config=jest.config.mjs --runInBand --detectOpenHandles",
|
|
11
|
+
"format": "prettier --write .",
|
|
12
|
+
"format:check": "prettier --check .",
|
|
13
|
+
"lint": "npx eslint .",
|
|
14
|
+
"lint:fix": "npx eslint . --fix"
|
|
15
|
+
},
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"semver",
|
|
20
|
+
"nodejs",
|
|
21
|
+
"semantic-release",
|
|
22
|
+
"go",
|
|
23
|
+
"golang",
|
|
24
|
+
"gomod"
|
|
25
|
+
],
|
|
26
|
+
"author": {
|
|
27
|
+
"name": "Mridang Agarwalla",
|
|
28
|
+
"email": "mridang.agarwalla@gmail.com",
|
|
29
|
+
"url": "https://github.com/mridang"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"license": "Apache-2.0",
|
|
35
|
+
"description": "Semantic Release plugin for multi-module Go repositories: pins submodule require lines and creates per-module git tags",
|
|
36
|
+
"private": false,
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=22.0.0"
|
|
39
|
+
},
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/mridang/semantic-release-gomod.git"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/mridang/semantic-release-gomod",
|
|
45
|
+
"bugs": "https://github.com/mridang/semantic-release-gomod/issues",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@semantic-release/error": "^4.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@jest/globals": "^30.0.3",
|
|
51
|
+
"@mridang/eslint-defaults": "^1.4.0",
|
|
52
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
53
|
+
"@semantic-release/git": "^10.0.1",
|
|
54
|
+
"@semantic-release/github": "^12.0.0",
|
|
55
|
+
"@semantic-release/npm": "^13.1.1",
|
|
56
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
57
|
+
"@tsconfig/node22": "^22.0.2",
|
|
58
|
+
"@types/jest": "^30.0.0",
|
|
59
|
+
"@types/node": "^22.18.12",
|
|
60
|
+
"@types/semantic-release__error": "^3.0.3",
|
|
61
|
+
"eslint": "^9.27.0",
|
|
62
|
+
"jest": "^30.0.3",
|
|
63
|
+
"jest-junit": "^17.0.0",
|
|
64
|
+
"knip": "^5.43.6",
|
|
65
|
+
"prettier": "^3.1.1",
|
|
66
|
+
"semantic-release": "^25.0.1",
|
|
67
|
+
"ts-jest": "^29.4.0",
|
|
68
|
+
"typescript": "^5.9.3"
|
|
69
|
+
},
|
|
70
|
+
"publishConfig": {
|
|
71
|
+
"access": "public"
|
|
72
|
+
}
|
|
73
|
+
}
|