opencode-github-release 0.3.1 → 0.4.1
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 +15 -1
- package/dist/index.js +50 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,13 +44,25 @@ Create a patch release with notes "Fixed login bug"
|
|
|
44
44
|
Create a release
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
**Suggest a bump (without releasing):**
|
|
48
|
+
```
|
|
49
|
+
What version should I use?
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Override dirty tree check:**
|
|
53
|
+
```
|
|
54
|
+
Create a major release with force: true
|
|
55
|
+
```
|
|
56
|
+
|
|
47
57
|
## How it works
|
|
48
58
|
|
|
49
59
|
When you request a release, the plugin fetches the latest git tag from the repository and computes the next version from it. If you specify a bump (`patch`/`minor`/`major`) or an explicit version, it creates the tag and release immediately. If you don't specify either (e.g., just "create a release"), the plugin instead runs `suggest_bump` — it analyzes commits since the latest tag using conventional commit conventions: `fix` → patch, `feat` → minor, `BREAKING CHANGE` → major — and presents the suggestion for your confirmation before proceeding.
|
|
50
60
|
|
|
51
61
|
If you don't provide release notes, the plugin automatically generates them from the commit history via `gh release create --generate-notes`.
|
|
52
62
|
|
|
53
|
-
`create_release`
|
|
63
|
+
`create_release` checks for uncommitted changes before proceeding. If the working tree is dirty, it returns a warning and asks you to commit, stash, or pass `force: true`.
|
|
64
|
+
|
|
65
|
+
It expects conventional commit messages (`feat:`, `fix:`, `BREAKING CHANGE:`) for accurate auto-suggestion. Commits that follow this convention are classified as:
|
|
54
66
|
|
|
55
67
|
- `fix:` → patch bump
|
|
56
68
|
- `feat:` → minor bump
|
|
@@ -69,6 +81,8 @@ Commits: 3
|
|
|
69
81
|
Suggested bump: major -> v1.0.0
|
|
70
82
|
```
|
|
71
83
|
|
|
84
|
+
You can invoke `suggest_bump` directly at any time ("Suggest a bump") — it analyzes commits since the latest tag and recommends a bump without creating anything.
|
|
85
|
+
|
|
72
86
|
## Prerequisites
|
|
73
87
|
|
|
74
88
|
- [Git](https://git-scm.com/)
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,10 @@ var plugin = async ({ $ }) => {
|
|
|
41
41
|
const latestTag = tagResult.trim();
|
|
42
42
|
const logText = await $`git log ${latestTag}..HEAD --oneline 2>/dev/null || true`.text();
|
|
43
43
|
if (!logText) {
|
|
44
|
-
return
|
|
44
|
+
return {
|
|
45
|
+
title: "No new commits",
|
|
46
|
+
output: `No new commits since ${latestTag}. No release needed.`
|
|
47
|
+
};
|
|
45
48
|
}
|
|
46
49
|
const lines = logText.split("\n");
|
|
47
50
|
const entries = lines.map((line) => {
|
|
@@ -64,14 +67,17 @@ var plugin = async ({ $ }) => {
|
|
|
64
67
|
const tag = e.breaking ? "[BREAKING]" : e.type === "feat" ? "[feat]" : e.type === "fix" ? "[fix]" : " ";
|
|
65
68
|
return ` ${tag} ${e.hash} ${e.subject}`;
|
|
66
69
|
}).join("\n");
|
|
67
|
-
return
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
return {
|
|
71
|
+
title: "Bump suggestion",
|
|
72
|
+
output: [
|
|
73
|
+
`Latest tag: ${latestTag}`,
|
|
74
|
+
`Commits: ${entries.length}`,
|
|
75
|
+
"",
|
|
76
|
+
output,
|
|
77
|
+
"",
|
|
78
|
+
`Suggested bump: ${suggestedBump} -> ${bumpVersion(latestTag, suggestedBump)}`
|
|
79
|
+
].join("\n")
|
|
80
|
+
};
|
|
75
81
|
}
|
|
76
82
|
}),
|
|
77
83
|
create_release: tool({
|
|
@@ -90,18 +96,24 @@ var plugin = async ({ $ }) => {
|
|
|
90
96
|
const status = (await $`git status --porcelain`.text()).trim();
|
|
91
97
|
if (status && !force) {
|
|
92
98
|
const count = status.split("\n").length;
|
|
93
|
-
return
|
|
99
|
+
return {
|
|
100
|
+
title: "Uncommitted files",
|
|
101
|
+
output: `${count} uncommitted file(s) detected. Call create_release with force: true to proceed anyway, or commit/stash first.`
|
|
102
|
+
};
|
|
94
103
|
}
|
|
95
104
|
await $`git fetch --tags --force 2>/dev/null || true`.quiet();
|
|
96
105
|
const tagResult = await $`git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0"`.text();
|
|
97
106
|
const latestTag = tagResult.trim();
|
|
98
107
|
const newTag = version ? version.startsWith("v") ? version : `v${version}` : bumpVersion(latestTag, bump);
|
|
99
108
|
const branch = (await $`git rev-parse --abbrev-ref HEAD`.text()).trim();
|
|
100
|
-
let
|
|
109
|
+
let unpushedBefore = [];
|
|
101
110
|
if (branch !== "HEAD") {
|
|
102
|
-
const
|
|
103
|
-
if (
|
|
104
|
-
|
|
111
|
+
const before = (await $`git log origin/${branch}..HEAD --oneline 2>/dev/null || true`.text()).trim();
|
|
112
|
+
if (before) {
|
|
113
|
+
unpushedBefore = before.split("\n").map((line) => {
|
|
114
|
+
const hash = line.split(/\s+/)[0];
|
|
115
|
+
return { hash, subject: line.slice(hash.length).trim() };
|
|
116
|
+
});
|
|
105
117
|
}
|
|
106
118
|
}
|
|
107
119
|
const hasPkg = (await $`test -f package.json && echo "yes" || echo "no"`.text()).trim() === "yes";
|
|
@@ -110,9 +122,9 @@ var plugin = async ({ $ }) => {
|
|
|
110
122
|
await $`npm version ${bareVersion} --no-git-tag-version`.quiet();
|
|
111
123
|
await $`git add package.json package-lock.json 2>/dev/null || true`.quiet();
|
|
112
124
|
await $`git commit -m ${`chore(release): bump version to ${newTag}`}`.quiet();
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
125
|
+
}
|
|
126
|
+
if (branch !== "HEAD") {
|
|
127
|
+
await $`git push origin ${branch}`.quiet();
|
|
116
128
|
}
|
|
117
129
|
const message = notes || `Release ${newTag}`;
|
|
118
130
|
await $`git tag -a ${newTag} -m ${message}`.quiet();
|
|
@@ -123,9 +135,27 @@ var plugin = async ({ $ }) => {
|
|
|
123
135
|
await $`gh release create ${newTag} --title ${newTag} --generate-notes`.quiet();
|
|
124
136
|
}
|
|
125
137
|
let result = `Created and published ${newTag} (bumped from ${latestTag})`;
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
138
|
+
if (branch !== "HEAD" && unpushedBefore.length > 0) {
|
|
139
|
+
const remaining = (await $`git log origin/${branch}..HEAD --oneline 2>/dev/null || true`.text()).trim();
|
|
140
|
+
const remainingCount = remaining ? remaining.split("\n").length : 0;
|
|
141
|
+
const pushedCount = unpushedBefore.length - remainingCount;
|
|
142
|
+
if (pushedCount > 0) {
|
|
143
|
+
const plural = pushedCount === 1 ? "" : "s";
|
|
144
|
+
result += `
|
|
145
|
+
Pushed ${pushedCount} commit${plural} to ${branch}:`;
|
|
146
|
+
for (let i = 0; i < pushedCount; i++) {
|
|
147
|
+
result += `
|
|
148
|
+
${unpushedBefore[i].hash} ${unpushedBefore[i].subject}`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (remainingCount > 0) {
|
|
152
|
+
const plural = remainingCount === 1 ? "" : "s";
|
|
153
|
+
const verb = remainingCount === 1 ? "is" : "are";
|
|
154
|
+
result += `
|
|
155
|
+
Note: ${remainingCount} commit${plural} in this release ${verb} not yet pushed to origin/${branch}.`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return { title: newTag, output: result };
|
|
129
159
|
}
|
|
130
160
|
})
|
|
131
161
|
}
|