@tarsilla/commit-wizard 1.4.8 → 2.0.3
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 +6 -5
- package/lib/commitizen/index.mjs +1 -1
- package/lib/commitizen/index.mjs.map +1 -1
- package/lib/commitlint/index.mjs +1 -1
- package/lib/commitlint/index.mjs.map +1 -1
- package/lib/semantic-release/brew/index.mjs +1 -1
- package/lib/semantic-release/brew/index.mjs.map +1 -1
- package/lib/semantic-release/npm/index.mjs +1 -1
- package/lib/semantic-release/npm/index.mjs.map +1 -1
- package/package.json +39 -28
- package/src/commitizen/index.ts +1 -1
- package/src/commitizen/prompter.ts +44 -44
- package/src/commitlint/index.ts +1 -1
- package/src/commitlint/userConfig.ts +1 -1
- package/src/config-loader/configLoader.ts +8 -2
- package/src/semantic-release/brew/index.ts +140 -184
- package/src/semantic-release/npm/index.ts +30 -58
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@ A custom configuration library for [commitizen](https://github.com/commitizen/cz
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
**@tarsilla/commit-wizard** provides a unified solution to enforce standardized commit messages and automate releases. It bundles tailored configurations for:
|
|
8
|
+
|
|
8
9
|
- **Commitizen** – interactive commit prompt
|
|
9
10
|
- **Commitlint** – commit message linting
|
|
10
11
|
- **Semantic-release** – automated release management
|
|
@@ -62,7 +63,7 @@ module.exports = {
|
|
|
62
63
|
};
|
|
63
64
|
```
|
|
64
65
|
|
|
65
|
-
The semantic-release configuration automates version management and changelog generation.
|
|
66
|
+
The semantic-release configuration automates version management and changelog generation.
|
|
66
67
|
It is recommended to configure CI/CD to run semantic-release, ex. using github actions (e.g. see [.github/workflows/npm-publish.yml](src/semantic-release/npm-publish.yml)).
|
|
67
68
|
|
|
68
69
|
## Configuration Options
|
|
@@ -70,9 +71,9 @@ It is recommended to configure CI/CD to run semantic-release, ex. using github a
|
|
|
70
71
|
You can override default settings by creating a `commit-wizard.config.json` file in your project root.
|
|
71
72
|
The plugin accepts an object of type `CommitWizardOptions`:
|
|
72
73
|
|
|
73
|
-
| Option
|
|
74
|
-
|
|
75
|
-
| maxLineLength | number | The maximum length of the commit message. If not provided, the plugin will run with the default settings. | 120
|
|
74
|
+
| Option | Type | Description | Default |
|
|
75
|
+
|---------------|--------|-----------------------------------------------------------------------------------------------------------|---------|
|
|
76
|
+
| maxLineLength | number | The maximum length of the commit message. If not provided, the plugin will run with the default settings. | 120 |
|
|
76
77
|
|
|
77
78
|
Example `commit-wizard.config.json`:
|
|
78
79
|
|
|
@@ -88,4 +89,4 @@ Contributions are welcome! Please ensure your pull request adheres to the projec
|
|
|
88
89
|
|
|
89
90
|
## License
|
|
90
91
|
|
|
91
|
-
Released under the [MIT License](LICENSE).
|
|
92
|
+
Released under the [MIT License](LICENSE).
|
package/lib/commitizen/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"fs";import t from"path";function
|
|
1
|
+
import e from"fs";import t from"path";const n={maxLineLength:120};function a({answers:e}){const t=e.scope?`(${e.scope})`:"";if("break"===e.type){return`feat${t}!: ${e.subject}`}return`${e.type}${t}: ${e.subject}`}function s({answers:e,maxLineLength:t}){const n=e.scope?`(${e.scope})`:"";return t-((e.type?e.type.length:0)+n.length+2)}const o=function({maxLineLength:e}){return{prompter:function(t,n){const o=[{choices:[{name:"🚀 feat: A new feature",value:"feat"},{name:"🐛 fix: A bug fix",value:"fix"},{name:"📚 docs: Documentation only changes",value:"docs"},{name:"🎨 style: Changes that do not affect the meaning of the code (white-space, formatting, etc)",value:"style"},{name:"🔨 refactor: A code change that neither fixes a bug nor adds a feature",value:"refactor"},{name:"⚡️ perf: A code change that improves performance",value:"perf"},{name:"🔍 test: Adding missing tests or correcting existing tests",value:"test"},{name:"📦 build: Changes that affect the build system or external dependencies",value:"build"},{name:"🤖 ci: Changes to our CI configuration files and scripts",value:"ci"},{name:"🧹 chore: Other changes that don't modify src or test files",value:"chore"},{name:"💥 break: A change that breaks existing functionality",value:"break"},{name:"⏪ revert: Reverts a previous commit",value:"revert"}],message:"Select the type of change that you're committing:",name:"type",type:"list"},{message:"What is the scope of this change (e.g. component or file name): (press enter to skip)",name:"scope",type:"input"},{message:t=>`Write a short, imperative tense description of the change (max ${s({answers:t,maxLineLength:e})} chars):`,name:"subject",transformer:(t,n)=>s({answers:n,maxLineLength:e})-t.length<0?`\n[31m(${t.length}) ${t}[39m`:`\n[32m(${t.length}) ${t}[39m`,type:"input",validate:(t,n)=>{if(!t.trim())return"[31mSubject is required[39m";const a=s({answers:n,maxLineLength:e});return t.length<=a||`[31mSubject length must be less than or equal to ${a} characters. Current length is ${t.length} characters.[39m`}},{choices:[{name:"Yes",value:"yes"},{name:"Abort commit",value:"no"}],default:0,message(e){const t="--------------------------------------------------------",n=a({answers:e});return console.info(`\n${t}\n\n${n}\n\n${t}\n`),"Are you sure you want to proceed with the commit above?"},name:"confirmCommit",type:"list"}];t.prompt(o).then(e=>{if("no"===e.confirmCommit)console.info("Commit aborted.");else{const t=a({answers:e});n(t)}})}}}(function(){const a=t.resolve(process.cwd(),"commit-wizard.config.json");if(!e.existsSync(a))return n;const s=e.readFileSync(a,"utf8"),o=JSON.parse(s);return o&&"object"==typeof o?{...n,...o}:n}());export{o as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../src/
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/config-loader/configLoader.ts","../../src/commitizen/prompter.ts","../../src/commitizen/index.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport CommitWizardOptions from '../types/CommitWizardOptions.js';\n\nconst config: CommitWizardOptions = {\n maxLineLength: 120,\n};\nconst file = 'commit-wizard.config.json';\n\nfunction configLoader(): CommitWizardOptions {\n const configPath = path.resolve(process.cwd(), file);\n\n if (!fs.existsSync(configPath)) {\n return config;\n }\n\n const rawConfig = fs.readFileSync(configPath, 'utf8');\n const parsedConfig: unknown = JSON.parse(rawConfig);\n\n if (!parsedConfig || typeof parsedConfig !== 'object') {\n return config;\n }\n\n return { ...config, ...parsedConfig };\n}\n\nexport default configLoader;\n","import { Commitizen, Prompter } from 'commitizen';\n\nimport CommitWizardOptions from '../types/CommitWizardOptions.js';\n\nexport type CommitAnswers = {\n confirmCommit: string;\n scope: string;\n subject: string;\n type: string;\n};\n\nfunction getCommitMessage({ answers }: { answers: Partial<CommitAnswers> }) {\n const scopeText = answers.scope ? `(${answers.scope})` : '';\n if (answers.type === 'break') {\n const message = `feat${scopeText}!: ${answers.subject}`;\n return message;\n }\n const message = `${answers.type}${scopeText}: ${answers.subject}`;\n return message;\n}\n\nfunction getMaxSubject({ answers, maxLineLength }: { answers: Partial<CommitAnswers>; maxLineLength: number }) {\n const scopeText = answers.scope ? `(${answers.scope})` : '';\n // +2 accounts for \": \" after type and scope.\n const prefixLength = (answers.type ? answers.type.length : 0) + scopeText.length + 2;\n const maxSubject = maxLineLength - prefixLength;\n return maxSubject;\n}\n\nfunction prompter({ maxLineLength }: CommitWizardOptions): Prompter {\n return {\n prompter: function (cz: Commitizen, commit: (message: string) => void) {\n const questions = [\n {\n choices: [\n { name: '🚀 feat: A new feature', value: 'feat' },\n { name: '🐛 fix: A bug fix', value: 'fix' },\n { name: '📚 docs: Documentation only changes', value: 'docs' },\n {\n name: '🎨 style: Changes that do not affect the meaning of the code (white-space, formatting, etc)',\n value: 'style',\n },\n { name: '🔨 refactor: A code change that neither fixes a bug nor adds a feature', value: 'refactor' },\n { name: '⚡️ perf: A code change that improves performance', value: 'perf' },\n { name: '🔍 test: Adding missing tests or correcting existing tests', value: 'test' },\n { name: '📦 build: Changes that affect the build system or external dependencies', value: 'build' },\n { name: '🤖 ci: Changes to our CI configuration files and scripts', value: 'ci' },\n { name: \"🧹 chore: Other changes that don't modify src or test files\", value: 'chore' },\n { name: '💥 break: A change that breaks existing functionality', value: 'break' },\n { name: '⏪ revert: Reverts a previous commit', value: 'revert' },\n ],\n message: \"Select the type of change that you're committing:\",\n name: 'type',\n type: 'list',\n },\n {\n message: 'What is the scope of this change (e.g. component or file name): (press enter to skip)',\n name: 'scope',\n type: 'input',\n },\n {\n message: (answers: Partial<CommitAnswers>) => {\n const maxSubject = getMaxSubject({ answers, maxLineLength });\n return `Write a short, imperative tense description of the change (max ${maxSubject} chars):`;\n },\n name: 'subject',\n transformer: (input: string, answers: Partial<CommitAnswers>) => {\n const maxSubject = getMaxSubject({ answers, maxLineLength });\n const remaining = maxSubject - input.length;\n if (remaining < 0) {\n // Red if remaining < 0: \\u001b[31m is red, \\u001b[39m resets the color.\n return `\\n\\u001b[31m(${input.length}) ${input}\\u001b[39m`;\n }\n // Green if valid: \\u001b[32m is green, \\u001b[39m resets the color.\n return `\\n\\u001b[32m(${input.length}) ${input}\\u001b[39m`;\n },\n type: 'input',\n validate: (input: string, answers: Partial<CommitAnswers>) => {\n if (!input.trim()) {\n // \\u001b[31m is red\n return `\\u001b[31mSubject is required\\u001b[39m`;\n }\n const maxSubject = getMaxSubject({ answers: answers, maxLineLength });\n if (input.length <= maxSubject) {\n return true;\n }\n // \\u001b[31m is red\n return `\\u001b[31mSubject length must be less than or equal to ${maxSubject} characters. Current length is ${input.length} characters.\\u001b[39m`;\n },\n },\n {\n choices: [\n { name: 'Yes', value: 'yes' },\n { name: 'Abort commit', value: 'no' },\n ],\n default: 0,\n message(answers: Partial<CommitAnswers>) {\n const SEP = '--------------------------------------------------------';\n const message = getCommitMessage({ answers });\n console.info(`\\n${SEP}\\n\\n${message}\\n\\n${SEP}\\n`);\n return 'Are you sure you want to proceed with the commit above?';\n },\n name: 'confirmCommit',\n type: 'list',\n },\n ];\n\n void cz.prompt<Partial<CommitAnswers>>(questions).then((answers) => {\n if (answers.confirmCommit === 'no') {\n console.info('Commit aborted.');\n } else {\n const message = getCommitMessage({ answers });\n commit(message);\n }\n });\n },\n };\n}\n\nexport default prompter;\n","import configLoader from '../config-loader/configLoader.js';\nimport commitizenPrompter from './prompter.js';\nimport CommitWizardOptions from '../types/CommitWizardOptions.js';\n\nconst loadedConfig: CommitWizardOptions = configLoader();\nconst prompter = commitizenPrompter(loadedConfig);\n\nexport default prompter;\n"],"names":["config","maxLineLength","getCommitMessage","answers","scopeText","scope","type","subject","getMaxSubject","length","prompter","cz","commit","questions","choices","name","value","message","transformer","input","validate","trim","maxSubject","default","SEP","console","info","prompt","then","confirmCommit","commitizenPrompter","configPath","path","resolve","process","cwd","fs","existsSync","rawConfig","readFileSync","parsedConfig","JSON","parse","configLoader"],"mappings":"sCAKA,MAAMA,EAA8B,CAClCC,cAAe,KCKjB,SAASC,GAAiBC,QAAEA,IAC1B,MAAMC,EAAYD,EAAQE,MAAQ,IAAIF,EAAQE,SAAW,GACzD,GAAqB,UAAjBF,EAAQG,KAAkB,CAE5B,MADgB,OAAOF,OAAeD,EAAQI,SAEhD,CAEA,MADgB,GAAGJ,EAAQG,OAAOF,MAAcD,EAAQI,SAE1D,CAEA,SAASC,GAAcL,QAAEA,EAAOF,cAAEA,IAChC,MAAMG,EAAYD,EAAQE,MAAQ,IAAIF,EAAQE,SAAW,GAIzD,OADmBJ,IADGE,EAAQG,KAAOH,EAAQG,KAAKG,OAAS,GAAKL,EAAUK,OAAS,EAGrF,CCvBA,MACMC,EDwBN,UAAkBT,cAAEA,IAClB,MAAO,CACLS,SAAU,SAAUC,EAAgBC,GAClC,MAAMC,EAAY,CAChB,CACEC,QAAS,CACP,CAAEC,KAAM,6BAA8BC,MAAO,QAC7C,CAAED,KAAM,yBAA0BC,MAAO,OACzC,CAAED,KAAM,0CAA2CC,MAAO,QAC1D,CACED,KAAM,iGACNC,MAAO,SAET,CAAED,KAAM,yEAA0EC,MAAO,YACzF,CAAED,KAAM,uDAAwDC,MAAO,QACvE,CAAED,KAAM,iEAAkEC,MAAO,QACjF,CAAED,KAAM,6EAA8EC,MAAO,SAC7F,CAAED,KAAM,iEAAkEC,MAAO,MACjF,CAAED,KAAM,iEAAkEC,MAAO,SACjF,CAAED,KAAM,2DAA4DC,MAAO,SAC3E,CAAED,KAAM,wCAAyCC,MAAO,WAE1DC,QAAS,oDACTF,KAAM,OACNT,KAAM,QAER,CACEW,QAAS,wFACTF,KAAM,QACNT,KAAM,SAER,CACEW,QAAUd,GAED,kEADYK,EAAc,CAAEL,UAASF,4BAG9Cc,KAAM,UACNG,YAAa,CAACC,EAAehB,IACRK,EAAc,CAAEL,UAASF,kBACbkB,EAAMV,OACrB,EAEP,WAAgBU,EAAMV,WAAWU,SAGnC,WAAgBA,EAAMV,WAAWU,SAE1Cb,KAAM,QACNc,SAAU,CAACD,EAAehB,KACxB,IAAKgB,EAAME,OAET,MAAO,gCAET,MAAMC,EAAad,EAAc,CAAEL,QAASA,EAASF,kBACrD,OAAIkB,EAAMV,QAAUa,GAIb,qDAA0DA,mCAA4CH,EAAMV,4BAGvH,CACEK,QAAS,CACP,CAAEC,KAAM,MAAOC,MAAO,OACtB,CAAED,KAAM,eAAgBC,MAAO,OAEjCO,QAAS,EACTN,OAAAA,CAAQd,GACN,MAAMqB,EAAM,2DACNP,EAAUf,EAAiB,CAAEC,YAEnC,OADAsB,QAAQC,KAAK,KAAKF,QAAUP,QAAcO,OACnC,yDACT,EACAT,KAAM,gBACNT,KAAM,SAILK,EAAGgB,OAA+Bd,GAAWe,KAAMzB,IACtD,GAA8B,OAA1BA,EAAQ0B,cACVJ,QAAQC,KAAK,uBACR,CACL,MAAMT,EAAUf,EAAiB,CAAEC,YACnCS,EAAOK,EACT,GAEJ,EAEJ,CChHiBa,CFKjB,WACE,MAAMC,EAAaC,EAAKC,QAAQC,QAAQC,MAH7B,6BAKX,IAAKC,EAAGC,WAAWN,GACjB,OAAO/B,EAGT,MAAMsC,EAAYF,EAAGG,aAAaR,EAAY,QACxCS,EAAwBC,KAAKC,MAAMJ,GAEzC,OAAKE,GAAwC,iBAAjBA,EAIrB,IAAKxC,KAAWwC,GAHdxC,CAIX,CErB0C2C"}
|
package/lib/commitlint/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"fs";import t from"path";const n={maxLineLength:120};const o=function({maxLineLength:e}){return{extends:["@commitlint/config-conventional"],parserPreset:{parserOpts:{
|
|
1
|
+
import e from"fs";import t from"path";const n={maxLineLength:120};const o=function({maxLineLength:e}){return{extends:["@commitlint/config-conventional"],parserPreset:{parserOpts:{headerCorrespondence:["type","exclamation1","scope","exclamation2","subject"],headerPattern:/^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/}},rules:{"header-max-length":[2,"always",e]}}}(function(){const o=t.resolve(process.cwd(),"commit-wizard.config.json");if(!e.existsSync(o))return n;const r=e.readFileSync(o,"utf8"),a=JSON.parse(r);return a&&"object"==typeof a?{...n,...a}:n}());export{o as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../src/config-loader/configLoader.ts","../../src/commitlint/index.ts","../../src/commitlint/userConfig.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport CommitWizardOptions from '../types/CommitWizardOptions.js';\n\nconst config: CommitWizardOptions = {\n maxLineLength: 120,\n};\nconst file = 'commit-wizard.config.json';\n\nfunction configLoader(): CommitWizardOptions {\n const configPath = path.resolve(process.cwd(), file);\n\n if (!fs.existsSync(configPath)) {\n return config;\n }\n\n const
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/config-loader/configLoader.ts","../../src/commitlint/index.ts","../../src/commitlint/userConfig.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport CommitWizardOptions from '../types/CommitWizardOptions.js';\n\nconst config: CommitWizardOptions = {\n maxLineLength: 120,\n};\nconst file = 'commit-wizard.config.json';\n\nfunction configLoader(): CommitWizardOptions {\n const configPath = path.resolve(process.cwd(), file);\n\n if (!fs.existsSync(configPath)) {\n return config;\n }\n\n const rawConfig = fs.readFileSync(configPath, 'utf8');\n const parsedConfig: unknown = JSON.parse(rawConfig);\n\n if (!parsedConfig || typeof parsedConfig !== 'object') {\n return config;\n }\n\n return { ...config, ...parsedConfig };\n}\n\nexport default configLoader;\n","import { UserConfig } from '@commitlint/types';\n\nimport configLoader from '../config-loader/configLoader.js';\nimport CommitWizardOptions from '../types/CommitWizardOptions.js';\nimport commitlintUserConfig from './userConfig.js';\n\nconst loadedConfig: CommitWizardOptions = configLoader();\nconst userConfig: UserConfig = commitlintUserConfig(loadedConfig);\n\nexport default userConfig;\n","import { UserConfig } from '@commitlint/types';\n\nimport CommitWizardOptions from '../types/CommitWizardOptions.js';\n\nfunction userConfig({ maxLineLength }: CommitWizardOptions): UserConfig {\n return {\n extends: ['@commitlint/config-conventional'],\n parserPreset: {\n parserOpts: {\n headerCorrespondence: ['type', 'exclamation1', 'scope', 'exclamation2', 'subject'],\n headerPattern: /^(?<type>\\w+)(?<exclamation1>!?)(?:\\((?<scope>[^)]+)\\)(?<exclamation2>!?))?: (?<subject>.+)$/,\n },\n },\n rules: {\n 'header-max-length': [2, 'always', maxLineLength] as [number, 'always' | 'never', number],\n },\n };\n}\n\nexport default userConfig;\n"],"names":["config","maxLineLength","userConfig","extends","parserPreset","parserOpts","headerCorrespondence","headerPattern","rules","commitlintUserConfig","configPath","path","resolve","process","cwd","fs","existsSync","rawConfig","readFileSync","parsedConfig","JSON","parse","configLoader"],"mappings":"sCAKA,MAAMA,EAA8B,CAClCC,cAAe,KCAjB,MACMC,ECHN,UAAoBD,cAAEA,IACpB,MAAO,CACLE,QAAS,CAAC,mCACVC,aAAc,CACZC,WAAY,CACVC,qBAAsB,CAAC,OAAQ,eAAgB,QAAS,eAAgB,WACxEC,cAAe,iGAGnBC,MAAO,CACL,oBAAqB,CAAC,EAAG,SAAUP,IAGzC,CDV+BQ,CDG/B,WACE,MAAMC,EAAaC,EAAKC,QAAQC,QAAQC,MAH7B,6BAKX,IAAKC,EAAGC,WAAWN,GACjB,OAAOV,EAGT,MAAMiB,EAAYF,EAAGG,aAAaR,EAAY,QACxCS,EAAwBC,KAAKC,MAAMJ,GAEzC,OAAKE,GAAwC,iBAAjBA,EAIrB,IAAKnB,KAAWmB,GAHdnB,CAIX,CCnB0CsB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"crypto";import t from"fs";import{
|
|
1
|
+
import{execSync as e}from"child_process";import a from"crypto";import t from"fs";import{analyzeCommits as r}from"@semantic-release/commit-analyzer";import{prepare as s,verifyConditions as n}from"@semantic-release/git";import{addChannel as o,fail as i,publish as c,success as l,verifyConditions as p}from"@semantic-release/github";import{generateNotes as m}from"@semantic-release/release-notes-generator";const y="nextTag-stable.tar.gz",f={parserOpts:{headerCorrespondence:["type","exclamation1","scope","exclamation2","subject"],headerPattern:/^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/},preset:"conventionalcommits",releaseRules:[{exclamation1:"!",release:"major",type:"feat"},{exclamation2:"!",release:"major",type:"feat"},{release:"minor",type:"feat"},{release:"patch",type:"fix"},{release:"patch",type:"docs"},{release:"patch",type:"style"},{release:"patch",type:"refactor"},{release:"patch",type:"perf"},{release:"patch",type:"test"},{release:"patch",type:"build"},{release:"patch",type:"ci"},{release:"patch",type:"chore"},{release:"patch",type:"revert"}]};let u=!1;function h(e,a){const{options:t}=a,r=t.repositoryUrl;if(!r)throw new Error("semantic-release repositoryUrl is required");const s=new URL(r).pathname,n=(s.startsWith("/")?s.slice(1):s).split("/").pop();return e.tap??`${n}.rb`}async function w(e,a){await p(e,a),await n(e,a),u=!0}const d={addChannel:async function(e,a){u||(await w(e,a),u=!0),await o(e,a)},analyzeCommits:async function(e,a){return u||(await w(e,a),u=!0),r(f,a)},fail:async function(e,a){await i(e,a)},generateNotes:async function(e,a){return u||(await w(e,a),u=!0),m({},a)},prepare:async function(r,n){u||(await w(r,n),u=!0);const{nextRelease:o}=n;if(!o.version)throw new Error("Next release version is not available.");const i=h(r,n);!function(a,t){const{nextRelease:r}=t,s=`v${r.version}`,n=y.replace("nextTag",s);e(`git archive --format=tar.gz --output=${n} HEAD`)}(0,n),function(e,r){const{nextRelease:s,options:n}=r,o=`v${s.version}`,i=n.repositoryUrl;if(!i)throw new Error("semantic-release repositoryUrl is required");const c=new URL(i).pathname,l=c.startsWith("/")?c.slice(1):c,p=y.replace("nextTag",o),m=`https://github.com/${l}/releases/download/${o}/${p}`,f=function(e,r){const{nextRelease:s}=r,n=`v${s.version}`,o=y.replace("nextTag",n),i=t.readFileSync(o),c=a.createHash("sha256");return c.update(i),c.digest("hex")}(0,r),u=h(e,r);let w=t.readFileSync(u,"utf8");w=w.replace(/url ".*"/,`url "${m}"`),w=w.replace(/sha256 ".*"/,`sha256 "${f}"`),t.writeFileSync(u,w)}(r,n),await s({assets:[i],message:"chore(release): ${nextRelease.version}"},n)},publish:async function(e,a){u||(await w(e,a),u=!0);const{nextRelease:t}=a,r=`v${t.version}`,s=y.replace("nextTag",r),n={...e,assets:[{label:`Homebrew Tarball (${r})`,path:s}]};return await c(n,a),null},success:async function(e,a){u||(await w(e,a),u=!0),await l(e,a)},verifyConditions:w};export{d as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../src/semantic-release/brew/index.ts"],"sourcesContent":["import crypto from 'crypto';\nimport fs from 'fs';\n\nimport { Octokit } from '@octokit/rest';\n//@ts-ignore\nimport { analyzeCommits as commitAnalyzerAnalyzeCommits } from '@semantic-release/commit-analyzer';\n//@ts-ignore\nimport { generateNotes as notesGeneratorGenerateNotes } from '@semantic-release/release-notes-generator';\nimport {\n AddChannelContext,\n AnalyzeCommitsContext,\n FailContext,\n GenerateNotesContext,\n PrepareContext,\n PublishContext,\n SuccessContext,\n VerifyConditionsContext,\n} from 'semantic-release';\n\nimport { SemanticReleasePlugin } from '../types.js';\n\nconst analyzerConfig = {\n preset: 'conventionalcommits',\n parserOpts: {\n headerPattern: /^(?<type>\\w+)(?<exclamation1>!?)(?:\\((?<scope>[^)]+)\\)(?<exclamation2>!?))?: (?<subject>.+)$/,\n headerCorrespondence: ['type', 'exclamation1', 'scope', 'exclamation2', 'subject'],\n },\n releaseRules: [\n { type: 'feat', exclamation1: '!', release: 'major' },\n { type: 'feat', exclamation2: '!', release: 'major' },\n { type: 'feat', release: 'minor' },\n { type: 'fix', release: 'patch' },\n { type: 'docs', release: 'patch' },\n { type: 'style', release: 'patch' },\n { type: 'refactor', release: 'patch' },\n { type: 'perf', release: 'patch' },\n { type: 'test', release: 'patch' },\n { type: 'build', release: 'patch' },\n { type: 'ci', release: 'patch' },\n { type: 'chore', release: 'patch' },\n { type: 'revert', release: 'patch' },\n ],\n};\n\ntype PluginConfig = { tap?: string };\n\nlet verified = false;\n\nfunction getFormulaFile(pluginConfig: PluginConfig, repositoryUrl: string): string {\n const url = new URL(repositoryUrl);\n const repositoryPath = url.pathname;\n const repository = repositoryPath.startsWith('/') ? repositoryPath.slice(1) : repositoryPath;\n const project = repository.split('/').pop();\n\n return pluginConfig.tap ?? `${project}.rb`;\n}\n\nasync function commitFormulaFile(pluginConfig: PluginConfig, context: PrepareContext): Promise<void> {\n if (!process.env.GITHUB_TOKEN) {\n throw new Error('GITHUB_TOKEN is not set in the environment.');\n }\n\n const { nextRelease, logger, options } = context;\n\n const repositoryUrl = options.repositoryUrl!; // Guaranteed to be defined by semantic-release\n const [owner, repo] = new URL(repositoryUrl).pathname.slice(1).split('/');\n\n const formulaFile = getFormulaFile(pluginConfig, repositoryUrl);\n const branchName = options.branch ?? 'main';\n\n logger.log(`Committing updated formula file ${formulaFile} to branch ${branchName}...`);\n\n const octokit = new Octokit({\n auth: process.env.GITHUB_TOKEN,\n });\n\n try {\n // Get the latest commit SHA and tree SHA from the branch\n const { data: branch } = await octokit.repos.getBranch({\n owner,\n repo,\n branch: branchName,\n });\n\n const latestCommitSha = branch.commit.sha;\n const baseTreeSha = branch.commit.commit.tree.sha;\n\n logger.log(`Latest commit SHA: ${latestCommitSha}`);\n logger.log(`Base tree SHA: ${baseTreeSha}`);\n\n // Read the updated formula file content\n const formulaContent = fs.readFileSync(formulaFile, 'utf8');\n\n // Create a new blob for the updated formula file\n const { data: blob } = await octokit.git.createBlob({\n owner,\n repo,\n content: formulaContent,\n encoding: 'utf-8',\n });\n\n logger.log(`Created blob for ${formulaFile} with SHA: ${blob.sha}`);\n\n // Create a new tree with the updated formula file\n const { data: newTree } = await octokit.git.createTree({\n owner,\n repo,\n base_tree: baseTreeSha,\n tree: [\n {\n path: formulaFile,\n mode: '100644',\n type: 'blob',\n sha: blob.sha,\n },\n ],\n });\n\n logger.log(`Created new tree with SHA: ${newTree.sha}`);\n\n // Create a new commit with the updated tree\n const commitMessage = `chore(release): ${nextRelease.version}`;\n const { data: newCommit } = await octokit.git.createCommit({\n owner,\n repo,\n message: commitMessage,\n tree: newTree.sha,\n parents: [latestCommitSha],\n });\n\n logger.log(`Created new commit with SHA: ${newCommit.sha}`);\n\n // Update the branch reference to point to the new commit\n await octokit.git.updateRef({\n owner,\n repo,\n ref: `heads/${branchName}`,\n sha: newCommit.sha,\n });\n\n logger.log(`Branch ${branchName} updated to commit ${newCommit.sha}`);\n } catch (error) {\n logger.error(`Failed to commit formula file: ${(error as Error).message}`);\n throw error;\n }\n}\n\nasync function calculateSha256(url: string, context: PrepareContext): Promise<string> {\n const { logger } = context;\n\n logger.log(`Calculating SHA256 for URL: ${url}`);\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch file. Status Code: ${response.status}`);\n }\n\n if (!response.body) {\n throw new Error('Response body is null.');\n }\n\n const hash = crypto.createHash('sha256');\n const reader = response.body.getReader();\n\n return new Promise((resolve, reject) => {\n function read() {\n reader\n .read()\n .then(({ done, value }) => {\n if (done) {\n resolve(hash.digest('hex'));\n return;\n }\n if (value) {\n hash.update(value);\n }\n read();\n })\n .catch(reject);\n }\n read();\n });\n}\n\nasync function updateFormulaFile(pluginConfig: PluginConfig, context: PrepareContext): Promise<void> {\n const { nextRelease, logger, options } = context;\n\n if (!nextRelease?.version) {\n throw new Error('Next release version is not available.');\n }\n\n const tagName = `v${nextRelease.version}`;\n\n const repositoryUrl = options.repositoryUrl!; // Guaranteed to be defined by semantic-release\n const url = new URL(repositoryUrl);\n const repositoryPath = url.pathname;\n const repository = repositoryPath.startsWith('/') ? repositoryPath.slice(1) : repositoryPath;\n\n const tarUrl = `https://codeload.github.com/${repository}/tar.gz/refs/tags/${tagName}`;\n const sha256 = await calculateSha256(tarUrl, context);\n const formulaFile = getFormulaFile(pluginConfig, repositoryUrl);\n\n let formulaContent = fs.readFileSync(formulaFile, 'utf8');\n formulaContent = formulaContent.replace(/url \".*\"/, `url \"${tarUrl}\"`);\n formulaContent = formulaContent.replace(/sha256 \".*\"/, `sha256 \"${sha256}\"`);\n fs.writeFileSync(formulaFile, formulaContent);\n\n logger.log(`Updated formula with version ${tagName}, URL ${tarUrl}, and SHA256 ${sha256}`);\n}\n\nasync function addChannel(_pluginConfig: PluginConfig, _context: AddChannelContext): Promise<void> {\n //do nothing\n}\n\nasync function analyzeCommits(pluginConfig: PluginConfig, context: AnalyzeCommitsContext): Promise<string | false> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n return commitAnalyzerAnalyzeCommits(analyzerConfig, context);\n}\n\nasync function fail(_pluginConfig: PluginConfig, _context: FailContext): Promise<void> {\n //do nothing\n}\n\nasync function generateNotes(pluginConfig: PluginConfig, context: GenerateNotesContext): Promise<string> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n return notesGeneratorGenerateNotes({}, context);\n}\n\nasync function prepare(_pluginConfig: PluginConfig, _context: PrepareContext): Promise<void> {\n //do nothing\n}\n\nasync function publish(pluginConfig: PluginConfig, context: PublishContext): Promise<unknown> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n await updateFormulaFile(pluginConfig, context);\n\n await commitFormulaFile(pluginConfig, context);\n\n return null;\n}\n\nasync function success(_pluginConfig: PluginConfig, _context: SuccessContext): Promise<void> {\n //do nothing\n}\n\nasync function verifyConditions(_pluginConfig: PluginConfig, _context: VerifyConditionsContext): Promise<void> {\n verified = true;\n}\n\nconst plugin: SemanticReleasePlugin<{ tap: string }> = {\n addChannel,\n verifyConditions,\n analyzeCommits,\n generateNotes,\n prepare,\n publish,\n success,\n fail,\n};\n\nexport default plugin;\n"],"names":["analyzerConfig","preset","parserOpts","headerPattern","RegExp","headerCorrespondence","releaseRules","type","exclamation1","release","exclamation2","verified","getFormulaFile","pluginConfig","repositoryUrl","repositoryPath","URL","pathname","project","startsWith","slice","split","pop","tap","async","updateFormulaFile","context","nextRelease","logger","options","version","Error","tagName","tarUrl","sha256","url","log","response","fetch","ok","status","body","hash","crypto","createHash","reader","getReader","Promise","resolve","reject","read","then","done","value","digest","update","catch","calculateSha256","formulaFile","formulaContent","fs","readFileSync","replace","writeFileSync","verifyConditions","_pluginConfig","_context","plugin","addChannel","analyzeCommits","commitAnalyzerAnalyzeCommits","generateNotes","notesGeneratorGenerateNotes","prepare","publish","process","env","GITHUB_TOKEN","owner","repo","branchName","branch","octokit","Octokit","auth","data","repos","getBranch","latestCommitSha","commit","sha","baseTreeSha","tree","blob","git","createBlob","content","encoding","newTree","createTree","base_tree","path","mode","commitMessage","newCommit","createCommit","message","parents","updateRef","ref","error","commitFormulaFile","success","fail"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../src/semantic-release/brew/index.ts"],"sourcesContent":["import { execSync } from 'child_process';\nimport crypto from 'crypto';\nimport fs from 'fs';\n\nimport {\n AddChannelContext,\n AnalyzeCommitsContext,\n FailContext,\n GenerateNotesContext,\n PrepareContext,\n PublishContext,\n SuccessContext,\n VerifyConditionsContext,\n} from 'semantic-release';\nimport { analyzeCommits as commitAnalyzerAnalyzeCommits } from '@semantic-release/commit-analyzer';\nimport { prepare as gitPrepare, verifyConditions as gitVerifyConditions } from '@semantic-release/git';\nimport {\n addChannel as gitHubAddChanel,\n fail as gitHubFail,\n publish as gitHubPublish,\n success as gitHubSuccess,\n verifyConditions as gitHubVerifyConditions,\n} from '@semantic-release/github';\nimport { generateNotes as notesGeneratorGenerateNotes } from '@semantic-release/release-notes-generator';\n\nimport { SemanticReleasePlugin } from '../types.js';\n\nconst tarballFile = 'nextTag-stable.tar.gz';\n\nconst analyzerConfig = {\n parserOpts: {\n headerCorrespondence: ['type', 'exclamation1', 'scope', 'exclamation2', 'subject'],\n headerPattern: /^(?<type>\\w+)(?<exclamation1>!?)(?:\\((?<scope>[^)]+)\\)(?<exclamation2>!?))?: (?<subject>.+)$/,\n },\n preset: 'conventionalcommits',\n releaseRules: [\n { exclamation1: '!', release: 'major', type: 'feat' },\n { exclamation2: '!', release: 'major', type: 'feat' },\n { release: 'minor', type: 'feat' },\n { release: 'patch', type: 'fix' },\n { release: 'patch', type: 'docs' },\n { release: 'patch', type: 'style' },\n { release: 'patch', type: 'refactor' },\n { release: 'patch', type: 'perf' },\n { release: 'patch', type: 'test' },\n { release: 'patch', type: 'build' },\n { release: 'patch', type: 'ci' },\n { release: 'patch', type: 'chore' },\n { release: 'patch', type: 'revert' },\n ],\n};\n\ntype PluginConfig = {\n tap?: string;\n};\n\nlet verified = false;\n\nasync function addChannel(pluginConfig: PluginConfig, context: AddChannelContext): Promise<void> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n await gitHubAddChanel(pluginConfig, context);\n}\n\nasync function analyzeCommits(pluginConfig: PluginConfig, context: AnalyzeCommitsContext): Promise<string | false> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n return commitAnalyzerAnalyzeCommits(analyzerConfig, context);\n}\n\nfunction calculateSha256(_pluginConfig: PluginConfig, context: PrepareContext) {\n const { nextRelease } = context;\n\n const nextTag = `v${nextRelease.version}`;\n const tarFilePath = tarballFile.replace('nextTag', nextTag);\n\n const fileBuffer = fs.readFileSync(tarFilePath);\n const hash = crypto.createHash('sha256');\n hash.update(fileBuffer);\n\n return hash.digest('hex');\n}\n\nasync function fail(pluginConfig: PluginConfig, context: FailContext): Promise<void> {\n await gitHubFail(pluginConfig, context);\n}\n\nasync function generateNotes(pluginConfig: PluginConfig, context: GenerateNotesContext): Promise<string> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n return notesGeneratorGenerateNotes({}, context);\n}\n\nfunction generateTarball(_pluginConfig: PluginConfig, context: PrepareContext) {\n const { nextRelease } = context;\n\n const nextTag = `v${nextRelease.version}`;\n const tarFilePath = tarballFile.replace('nextTag', nextTag);\n\n execSync(`git archive --format=tar.gz --output=${tarFilePath} HEAD`);\n}\n\nfunction getFormulaFile(pluginConfig: PluginConfig, context: PrepareContext): string {\n const { options } = context;\n const repositoryUrl = options.repositoryUrl;\n if (!repositoryUrl) {\n throw new Error('semantic-release repositoryUrl is required');\n }\n const url = new URL(repositoryUrl);\n const repositoryPath = url.pathname;\n const repository = repositoryPath.startsWith('/') ? repositoryPath.slice(1) : repositoryPath;\n const project = repository.split('/').pop();\n\n return pluginConfig.tap ?? `${project}.rb`;\n}\n\nasync function prepare(pluginConfig: PluginConfig, context: PrepareContext): Promise<void> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n const { nextRelease } = context;\n if (!nextRelease.version) {\n throw new Error('Next release version is not available.');\n }\n\n const formulaFile = getFormulaFile(pluginConfig, context);\n\n generateTarball(pluginConfig, context);\n updateFormulaFile(pluginConfig, context);\n\n await gitPrepare(\n {\n assets: [formulaFile],\n message: 'chore(release): ${nextRelease.version}',\n },\n context,\n );\n}\n\nasync function publish(pluginConfig: PluginConfig, context: PublishContext): Promise<unknown> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n const { nextRelease } = context;\n const nextTag = `v${nextRelease.version}`;\n const tarFilePath = tarballFile.replace('nextTag', nextTag);\n\n const customPluginConfig = {\n ...pluginConfig,\n assets: [\n {\n label: `Homebrew Tarball (${nextTag})`,\n path: tarFilePath,\n },\n ],\n };\n await gitHubPublish(customPluginConfig, context);\n\n //await updateFormulaFile(pluginConfig, context);\n //await commitFormulaFile(pluginConfig, context);\n\n return null;\n}\n\nasync function success(pluginConfig: PluginConfig, context: SuccessContext): Promise<void> {\n if (!verified) {\n await verifyConditions(pluginConfig, context);\n verified = true;\n }\n\n await gitHubSuccess(pluginConfig, context);\n}\n\nfunction updateFormulaFile(pluginConfig: PluginConfig, context: PrepareContext): void {\n const { nextRelease, options } = context;\n\n const nextTag = `v${nextRelease.version}`;\n\n const repositoryUrl = options.repositoryUrl;\n if (!repositoryUrl) {\n throw new Error('semantic-release repositoryUrl is required');\n }\n const url = new URL(repositoryUrl);\n const repositoryPath = url.pathname;\n const repository = repositoryPath.startsWith('/') ? repositoryPath.slice(1) : repositoryPath;\n const tarFilePath = tarballFile.replace('nextTag', nextTag);\n\n const tarUrl = `https://github.com/${repository}/releases/download/${nextTag}/${tarFilePath}`;\n //const tarUrl = `https://codeload.github.com/${repository}/tar.gz/refs/tags/${tarFilePath}`;\n\n const sha256 = calculateSha256(pluginConfig, context);\n const formulaFile = getFormulaFile(pluginConfig, context);\n\n let formulaContent = fs.readFileSync(formulaFile, 'utf8');\n formulaContent = formulaContent.replace(/url \".*\"/, `url \"${tarUrl}\"`);\n formulaContent = formulaContent.replace(/sha256 \".*\"/, `sha256 \"${sha256}\"`);\n fs.writeFileSync(formulaFile, formulaContent);\n}\n\nasync function verifyConditions(pluginConfig: PluginConfig, context: VerifyConditionsContext): Promise<void> {\n await gitHubVerifyConditions(pluginConfig, context);\n await gitVerifyConditions(pluginConfig, context);\n verified = true;\n}\n\nconst plugin: SemanticReleasePlugin<{ tap: string }> = {\n addChannel,\n analyzeCommits,\n fail,\n generateNotes,\n prepare,\n publish,\n success,\n verifyConditions,\n};\n\nexport default plugin;\n"],"names":["tarballFile","analyzerConfig","parserOpts","headerCorrespondence","headerPattern","preset","releaseRules","exclamation1","release","type","exclamation2","verified","getFormulaFile","pluginConfig","context","options","repositoryUrl","Error","repositoryPath","URL","pathname","project","startsWith","slice","split","pop","tap","async","verifyConditions","gitHubVerifyConditions","gitVerifyConditions","plugin","addChannel","gitHubAddChanel","analyzeCommits","commitAnalyzerAnalyzeCommits","fail","gitHubFail","generateNotes","notesGeneratorGenerateNotes","prepare","nextRelease","version","formulaFile","_pluginConfig","nextTag","tarFilePath","replace","execSync","generateTarball","repository","tarUrl","sha256","fileBuffer","fs","readFileSync","hash","crypto","createHash","update","digest","calculateSha256","formulaContent","writeFileSync","updateFormulaFile","gitPrepare","assets","message","publish","customPluginConfig","label","path","gitHubPublish","success","gitHubSuccess"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{analyzeCommits as e}from"@semantic-release/commit-analyzer";import{
|
|
1
|
+
import{analyzeCommits as e}from"@semantic-release/commit-analyzer";import{verifyConditions as a,prepare as t}from"@semantic-release/git";import{verifyConditions as s,publish as r,prepare as c}from"@semantic-release/npm";import{generateNotes as p}from"@semantic-release/release-notes-generator";const n={parserOpts:{headerCorrespondence:["type","exclamation1","scope","exclamation2","subject"],headerPattern:/^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/},preset:"conventionalcommits",releaseRules:[{exclamation1:"!",release:"major",type:"feat"},{exclamation2:"!",release:"major",type:"feat"},{release:"minor",type:"feat"},{release:"patch",type:"fix"},{release:"patch",type:"docs"},{release:"patch",type:"style"},{release:"patch",type:"refactor"},{release:"patch",type:"perf"},{release:"patch",type:"test"},{release:"patch",type:"build"},{release:"patch",type:"ci"},{release:"patch",type:"chore"},{release:"patch",type:"revert"}]},o={npmPublish:!0},l={assets:["package.json","package-lock.json"],message:"chore(release): ${nextRelease.version}"},i={addChannel:async(e,a)=>{},analyzeCommits:async(a,t)=>e(n,t),fail:async(e,a)=>{},generateNotes:async(e,a)=>p({},a),prepare:async(e,a)=>{await c(o,a),await t(l,a)},publish:async(e,a)=>{await r(o,a)},success:async(e,a)=>{},verifyConditions:async(e,t)=>{await s(o,t),await a(l,t)}};export{i as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../src/semantic-release/npm/index.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../src/semantic-release/npm/index.ts"],"sourcesContent":["import { analyzeCommits } from '@semantic-release/commit-analyzer';\nimport { prepare as gitPrepare, verifyConditions as gitVerifyConditions } from '@semantic-release/git';\nimport {\n prepare as npmPrepare,\n publish as npmPublish,\n verifyConditions as npmVerifyConditions,\n} from '@semantic-release/npm';\nimport { generateNotes } from '@semantic-release/release-notes-generator';\n\nimport { SemanticReleasePlugin } from '../types.js';\n\nconst analyzerConfig = {\n parserOpts: {\n headerCorrespondence: ['type', 'exclamation1', 'scope', 'exclamation2', 'subject'],\n headerPattern: /^(?<type>\\w+)(?<exclamation1>!?)(?:\\((?<scope>[^)]+)\\)(?<exclamation2>!?))?: (?<subject>.+)$/,\n },\n preset: 'conventionalcommits',\n releaseRules: [\n { exclamation1: '!', release: 'major', type: 'feat' },\n { exclamation2: '!', release: 'major', type: 'feat' },\n { release: 'minor', type: 'feat' },\n { release: 'patch', type: 'fix' },\n { release: 'patch', type: 'docs' },\n { release: 'patch', type: 'style' },\n { release: 'patch', type: 'refactor' },\n { release: 'patch', type: 'perf' },\n { release: 'patch', type: 'test' },\n { release: 'patch', type: 'build' },\n { release: 'patch', type: 'ci' },\n { release: 'patch', type: 'chore' },\n { release: 'patch', type: 'revert' },\n ],\n};\n\nconst npmConfig = {\n npmPublish: true,\n};\n\nconst gitConfig = {\n assets: ['package.json', 'package-lock.json'],\n message: 'chore(release): ${nextRelease.version}',\n};\n\nconst plugin: SemanticReleasePlugin = {\n addChannel: async (_pluginConfig, _context) => {\n //await npmAddChannel(npmConfig, context);\n },\n analyzeCommits: async (_pluginConfig, context) => {\n return analyzeCommits(analyzerConfig, context);\n },\n\n fail: async (_pluginConfig, _context) => {\n //await gitFail(gitConfig, context);\n },\n\n generateNotes: async (_pluginConfig, context) => {\n return generateNotes({}, context);\n },\n\n prepare: async (_pluginConfig, context) => {\n await npmPrepare(npmConfig, context);\n await gitPrepare(gitConfig, context);\n },\n\n publish: async (_pluginConfig, context) => {\n await npmPublish(npmConfig, context);\n //await gitPublish(gitConfig, context);\n },\n\n success: async (_pluginConfig, _context) => {\n //await gitSuccess(gitConfig, context);\n },\n\n verifyConditions: async (_pluginConfig, context) => {\n await npmVerifyConditions(npmConfig, context);\n await gitVerifyConditions(gitConfig, context);\n },\n};\n\nexport default plugin;\n"],"names":["analyzerConfig","parserOpts","headerCorrespondence","headerPattern","preset","releaseRules","exclamation1","release","type","exclamation2","npmConfig","npmPublish","gitConfig","assets","message","plugin","addChannel","async","_pluginConfig","_context","analyzeCommits","context","fail","generateNotes","prepare","npmPrepare","gitPrepare","publish","success","verifyConditions","npmVerifyConditions","gitVerifyConditions"],"mappings":"sSAWA,MAAMA,EAAiB,CACrBC,WAAY,CACVC,qBAAsB,CAAC,OAAQ,eAAgB,QAAS,eAAgB,WACxEC,cAAe,gGAEjBC,OAAQ,sBACRC,aAAc,CACZ,CAAEC,aAAc,IAAKC,QAAS,QAASC,KAAM,QAC7C,CAAEC,aAAc,IAAKF,QAAS,QAASC,KAAM,QAC7C,CAAED,QAAS,QAASC,KAAM,QAC1B,CAAED,QAAS,QAASC,KAAM,OAC1B,CAAED,QAAS,QAASC,KAAM,QAC1B,CAAED,QAAS,QAASC,KAAM,SAC1B,CAAED,QAAS,QAASC,KAAM,YAC1B,CAAED,QAAS,QAASC,KAAM,QAC1B,CAAED,QAAS,QAASC,KAAM,QAC1B,CAAED,QAAS,QAASC,KAAM,SAC1B,CAAED,QAAS,QAASC,KAAM,MAC1B,CAAED,QAAS,QAASC,KAAM,SAC1B,CAAED,QAAS,QAASC,KAAM,YAIxBE,EAAY,CAChBC,YAAY,GAGRC,EAAY,CAChBC,OAAQ,CAAC,eAAgB,qBACzBC,QAAS,0CAGLC,EAAgC,CACpCC,WAAYC,MAAOC,EAAeC,OAGlCC,eAAgBH,MAAOC,EAAeG,IAC7BD,EAAepB,EAAgBqB,GAGxCC,KAAML,MAAOC,EAAeC,OAI5BI,cAAeN,MAAOC,EAAeG,IAC5BE,EAAc,CAAA,EAAIF,GAG3BG,QAASP,MAAOC,EAAeG,WACvBI,EAAWf,EAAWW,SACtBK,EAAWd,EAAWS,IAG9BM,QAASV,MAAOC,EAAeG,WACvBV,EAAWD,EAAWW,IAI9BO,QAASX,MAAOC,EAAeC,OAI/BU,iBAAkBZ,MAAOC,EAAeG,WAChCS,EAAoBpB,EAAWW,SAC/BU,EAAoBnB,EAAWS"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tarsilla/commit-wizard",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/tarsilla-app/commit-wizard"
|
|
7
|
+
},
|
|
4
8
|
"publishConfig": {
|
|
5
9
|
"access": "public"
|
|
6
10
|
},
|
|
7
11
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
12
|
+
"node": ">=25"
|
|
9
13
|
},
|
|
10
14
|
"exports": {
|
|
11
15
|
"./commitizen": {
|
|
@@ -49,39 +53,46 @@
|
|
|
49
53
|
"prepare": "husky"
|
|
50
54
|
},
|
|
51
55
|
"peerDependencies": {
|
|
52
|
-
"@commitlint/cli": "^
|
|
53
|
-
"@commitlint/config-conventional": "^19",
|
|
54
|
-
"@semantic-release/commit-analyzer": "^13",
|
|
55
|
-
"@semantic-release/git": "^10",
|
|
56
|
-
"@semantic-release/npm": "^12",
|
|
57
|
-
"@semantic-release/release-notes-generator": "^14",
|
|
56
|
+
"@commitlint/cli": "^20",
|
|
58
57
|
"commitizen": "^4",
|
|
59
|
-
"semantic-release": "^
|
|
58
|
+
"semantic-release": "^25"
|
|
60
59
|
},
|
|
61
60
|
"dependencies": {
|
|
62
|
-
"@
|
|
63
|
-
"
|
|
64
|
-
"
|
|
61
|
+
"@commitlint/config-conventional": "^20.5.0",
|
|
62
|
+
"@octokit/rest": "^22.0.1",
|
|
63
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
64
|
+
"@semantic-release/git": "^10.0.1",
|
|
65
|
+
"@semantic-release/github": "^12.0.6",
|
|
66
|
+
"@semantic-release/npm": "^13.1.5",
|
|
67
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
68
|
+
"chokidar": "^5.0.0"
|
|
65
69
|
},
|
|
66
70
|
"devDependencies": {
|
|
67
|
-
"@eslint/js": "^
|
|
68
|
-
"@rollup/plugin-commonjs": "^
|
|
69
|
-
"@rollup/plugin-node-resolve": "^16.0.
|
|
71
|
+
"@eslint/js": "^10.0.1",
|
|
72
|
+
"@rollup/plugin-commonjs": "^29.0.2",
|
|
73
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
70
74
|
"@rollup/plugin-swc": "^0.4.0",
|
|
71
|
-
"@rollup/plugin-terser": "^0.
|
|
72
|
-
"@types/inquirer": "^
|
|
73
|
-
"eslint": "^
|
|
74
|
-
"eslint-config-prettier": "^10.1.
|
|
75
|
-
"eslint-import-resolver-typescript": "^4.
|
|
76
|
-
"eslint-plugin-
|
|
77
|
-
"eslint-plugin-prettier": "^5.
|
|
78
|
-
"eslint-plugin-unused-imports": "^4.1
|
|
75
|
+
"@rollup/plugin-terser": "^1.0.0",
|
|
76
|
+
"@types/inquirer": "^9.0.9",
|
|
77
|
+
"eslint": "^10.2.0",
|
|
78
|
+
"eslint-config-prettier": "^10.1.8",
|
|
79
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
80
|
+
"eslint-plugin-perfectionist": "^5.8.0",
|
|
81
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
82
|
+
"eslint-plugin-unused-imports": "^4.4.1",
|
|
83
|
+
"globals": "^17.4.0",
|
|
79
84
|
"husky": "^9.1.7",
|
|
80
|
-
"prettier": "^3.
|
|
81
|
-
"rollup": "^4.
|
|
82
|
-
"rollup-plugin-dts": "^6.
|
|
85
|
+
"prettier": "^3.8.2",
|
|
86
|
+
"rollup": "^4.60.1",
|
|
87
|
+
"rollup-plugin-dts": "^6.4.1",
|
|
83
88
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
84
|
-
"typescript": "^5.
|
|
85
|
-
"typescript-eslint": "^8.
|
|
89
|
+
"typescript": "^5.9.3",
|
|
90
|
+
"typescript-eslint": "^8.58.1"
|
|
91
|
+
},
|
|
92
|
+
"overrides": {
|
|
93
|
+
"commitizen": {
|
|
94
|
+
"inquirer": "^8.2.7",
|
|
95
|
+
"lodash": "^4.18.1"
|
|
96
|
+
}
|
|
86
97
|
}
|
|
87
98
|
}
|
package/src/commitizen/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import commitizenPrompter from './prompter.js';
|
|
2
1
|
import configLoader from '../config-loader/configLoader.js';
|
|
2
|
+
import commitizenPrompter from './prompter.js';
|
|
3
3
|
import CommitWizardOptions from '../types/CommitWizardOptions.js';
|
|
4
4
|
|
|
5
5
|
const loadedConfig: CommitWizardOptions = configLoader();
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { Commitizen, Prompter
|
|
1
|
+
import { Commitizen, Prompter } from 'commitizen';
|
|
2
2
|
|
|
3
3
|
import CommitWizardOptions from '../types/CommitWizardOptions.js';
|
|
4
4
|
|
|
5
5
|
export type CommitAnswers = {
|
|
6
|
-
|
|
6
|
+
confirmCommit: string;
|
|
7
7
|
scope: string;
|
|
8
8
|
subject: string;
|
|
9
|
-
|
|
9
|
+
type: string;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
function getCommitMessage({ answers }: { answers: CommitAnswers }) {
|
|
12
|
+
function getCommitMessage({ answers }: { answers: Partial<CommitAnswers> }) {
|
|
13
13
|
const scopeText = answers.scope ? `(${answers.scope})` : '';
|
|
14
14
|
if (answers.type === 'break') {
|
|
15
15
|
const message = `feat${scopeText}!: ${answers.subject}`;
|
|
@@ -19,7 +19,7 @@ function getCommitMessage({ answers }: { answers: CommitAnswers }) {
|
|
|
19
19
|
return message;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function getMaxSubject({ answers, maxLineLength }: { answers: CommitAnswers
|
|
22
|
+
function getMaxSubject({ answers, maxLineLength }: { answers: Partial<CommitAnswers>; maxLineLength: number }) {
|
|
23
23
|
const scopeText = answers.scope ? `(${answers.scope})` : '';
|
|
24
24
|
// +2 accounts for ": " after type and scope.
|
|
25
25
|
const prefixLength = (answers.type ? answers.type.length : 0) + scopeText.length + 2;
|
|
@@ -30,82 +30,82 @@ function getMaxSubject({ answers, maxLineLength }: { answers: CommitAnswers; max
|
|
|
30
30
|
function prompter({ maxLineLength }: CommitWizardOptions): Prompter {
|
|
31
31
|
return {
|
|
32
32
|
prompter: function (cz: Commitizen, commit: (message: string) => void) {
|
|
33
|
-
const questions
|
|
33
|
+
const questions = [
|
|
34
34
|
{
|
|
35
|
-
type: 'list',
|
|
36
|
-
name: 'type',
|
|
37
|
-
message: "Select the type of change that you're committing:",
|
|
38
35
|
choices: [
|
|
39
|
-
{
|
|
40
|
-
{
|
|
41
|
-
{
|
|
36
|
+
{ name: '🚀 feat: A new feature', value: 'feat' },
|
|
37
|
+
{ name: '🐛 fix: A bug fix', value: 'fix' },
|
|
38
|
+
{ name: '📚 docs: Documentation only changes', value: 'docs' },
|
|
42
39
|
{
|
|
43
|
-
value: 'style',
|
|
44
40
|
name: '🎨 style: Changes that do not affect the meaning of the code (white-space, formatting, etc)',
|
|
41
|
+
value: 'style',
|
|
45
42
|
},
|
|
46
|
-
{
|
|
47
|
-
{
|
|
48
|
-
{
|
|
49
|
-
{
|
|
50
|
-
{
|
|
51
|
-
{
|
|
52
|
-
{
|
|
53
|
-
{
|
|
43
|
+
{ name: '🔨 refactor: A code change that neither fixes a bug nor adds a feature', value: 'refactor' },
|
|
44
|
+
{ name: '⚡️ perf: A code change that improves performance', value: 'perf' },
|
|
45
|
+
{ name: '🔍 test: Adding missing tests or correcting existing tests', value: 'test' },
|
|
46
|
+
{ name: '📦 build: Changes that affect the build system or external dependencies', value: 'build' },
|
|
47
|
+
{ name: '🤖 ci: Changes to our CI configuration files and scripts', value: 'ci' },
|
|
48
|
+
{ name: "🧹 chore: Other changes that don't modify src or test files", value: 'chore' },
|
|
49
|
+
{ name: '💥 break: A change that breaks existing functionality', value: 'break' },
|
|
50
|
+
{ name: '⏪ revert: Reverts a previous commit', value: 'revert' },
|
|
54
51
|
],
|
|
52
|
+
message: "Select the type of change that you're committing:",
|
|
53
|
+
name: 'type',
|
|
54
|
+
type: 'list',
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
|
-
type: 'input',
|
|
58
|
-
name: 'scope',
|
|
59
57
|
message: 'What is the scope of this change (e.g. component or file name): (press enter to skip)',
|
|
58
|
+
name: 'scope',
|
|
59
|
+
type: 'input',
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
|
-
|
|
63
|
-
name: 'subject',
|
|
64
|
-
message: (answers) => {
|
|
62
|
+
message: (answers: Partial<CommitAnswers>) => {
|
|
65
63
|
const maxSubject = getMaxSubject({ answers, maxLineLength });
|
|
66
64
|
return `Write a short, imperative tense description of the change (max ${maxSubject} chars):`;
|
|
67
65
|
},
|
|
68
|
-
|
|
66
|
+
name: 'subject',
|
|
67
|
+
transformer: (input: string, answers: Partial<CommitAnswers>) => {
|
|
68
|
+
const maxSubject = getMaxSubject({ answers, maxLineLength });
|
|
69
|
+
const remaining = maxSubject - input.length;
|
|
70
|
+
if (remaining < 0) {
|
|
71
|
+
// Red if remaining < 0: \u001b[31m is red, \u001b[39m resets the color.
|
|
72
|
+
return `\n\u001b[31m(${input.length}) ${input}\u001b[39m`;
|
|
73
|
+
}
|
|
74
|
+
// Green if valid: \u001b[32m is green, \u001b[39m resets the color.
|
|
75
|
+
return `\n\u001b[32m(${input.length}) ${input}\u001b[39m`;
|
|
76
|
+
},
|
|
77
|
+
type: 'input',
|
|
78
|
+
validate: (input: string, answers: Partial<CommitAnswers>) => {
|
|
69
79
|
if (!input.trim()) {
|
|
70
80
|
// \u001b[31m is red
|
|
71
81
|
return `\u001b[31mSubject is required\u001b[39m`;
|
|
72
82
|
}
|
|
73
|
-
const maxSubject = getMaxSubject({ answers: answers
|
|
83
|
+
const maxSubject = getMaxSubject({ answers: answers, maxLineLength });
|
|
74
84
|
if (input.length <= maxSubject) {
|
|
75
85
|
return true;
|
|
76
86
|
}
|
|
77
87
|
// \u001b[31m is red
|
|
78
88
|
return `\u001b[31mSubject length must be less than or equal to ${maxSubject} characters. Current length is ${input.length} characters.\u001b[39m`;
|
|
79
89
|
},
|
|
80
|
-
transformer: (input, answers) => {
|
|
81
|
-
const maxSubject = getMaxSubject({ answers, maxLineLength });
|
|
82
|
-
const remaining = maxSubject - input.length;
|
|
83
|
-
if (remaining < 0) {
|
|
84
|
-
// Red if remaining < 0: \u001b[31m is red, \u001b[39m resets the color.
|
|
85
|
-
return `\n\u001b[31m(${input.length}) ${input}\u001b[39m`;
|
|
86
|
-
}
|
|
87
|
-
// Green if valid: \u001b[32m is green, \u001b[39m resets the color.
|
|
88
|
-
return `\n\u001b[32m(${input.length}) ${input}\u001b[39m`;
|
|
89
|
-
},
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
|
-
type: 'list',
|
|
93
|
-
name: 'confirmCommit',
|
|
94
92
|
choices: [
|
|
95
|
-
{
|
|
96
|
-
{
|
|
93
|
+
{ name: 'Yes', value: 'yes' },
|
|
94
|
+
{ name: 'Abort commit', value: 'no' },
|
|
97
95
|
],
|
|
98
96
|
default: 0,
|
|
99
|
-
message(answers) {
|
|
97
|
+
message(answers: Partial<CommitAnswers>) {
|
|
100
98
|
const SEP = '--------------------------------------------------------';
|
|
101
99
|
const message = getCommitMessage({ answers });
|
|
102
100
|
console.info(`\n${SEP}\n\n${message}\n\n${SEP}\n`);
|
|
103
101
|
return 'Are you sure you want to proceed with the commit above?';
|
|
104
102
|
},
|
|
103
|
+
name: 'confirmCommit',
|
|
104
|
+
type: 'list',
|
|
105
105
|
},
|
|
106
106
|
];
|
|
107
107
|
|
|
108
|
-
cz.prompt(questions).then((answers) => {
|
|
108
|
+
void cz.prompt<Partial<CommitAnswers>>(questions).then((answers) => {
|
|
109
109
|
if (answers.confirmCommit === 'no') {
|
|
110
110
|
console.info('Commit aborted.');
|
|
111
111
|
} else {
|
package/src/commitlint/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { UserConfig } from '@commitlint/types';
|
|
2
2
|
|
|
3
|
-
import commitlintUserConfig from './userConfig.js';
|
|
4
3
|
import configLoader from '../config-loader/configLoader.js';
|
|
5
4
|
import CommitWizardOptions from '../types/CommitWizardOptions.js';
|
|
5
|
+
import commitlintUserConfig from './userConfig.js';
|
|
6
6
|
|
|
7
7
|
const loadedConfig: CommitWizardOptions = configLoader();
|
|
8
8
|
const userConfig: UserConfig = commitlintUserConfig(loadedConfig);
|
|
@@ -7,8 +7,8 @@ function userConfig({ maxLineLength }: CommitWizardOptions): UserConfig {
|
|
|
7
7
|
extends: ['@commitlint/config-conventional'],
|
|
8
8
|
parserPreset: {
|
|
9
9
|
parserOpts: {
|
|
10
|
-
headerPattern: /^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/,
|
|
11
10
|
headerCorrespondence: ['type', 'exclamation1', 'scope', 'exclamation2', 'subject'],
|
|
11
|
+
headerPattern: /^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/,
|
|
12
12
|
},
|
|
13
13
|
},
|
|
14
14
|
rules: {
|
|
@@ -15,8 +15,14 @@ function configLoader(): CommitWizardOptions {
|
|
|
15
15
|
return config;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const
|
|
19
|
-
|
|
18
|
+
const rawConfig = fs.readFileSync(configPath, 'utf8');
|
|
19
|
+
const parsedConfig: unknown = JSON.parse(rawConfig);
|
|
20
|
+
|
|
21
|
+
if (!parsedConfig || typeof parsedConfig !== 'object') {
|
|
22
|
+
return config;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { ...config, ...parsedConfig };
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
export default configLoader;
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
1
2
|
import crypto from 'crypto';
|
|
2
3
|
import fs from 'fs';
|
|
3
4
|
|
|
4
|
-
import { Octokit } from '@octokit/rest';
|
|
5
|
-
//@ts-ignore
|
|
6
|
-
import { analyzeCommits as commitAnalyzerAnalyzeCommits } from '@semantic-release/commit-analyzer';
|
|
7
|
-
//@ts-ignore
|
|
8
|
-
import { generateNotes as notesGeneratorGenerateNotes } from '@semantic-release/release-notes-generator';
|
|
9
5
|
import {
|
|
10
6
|
AddChannelContext,
|
|
11
7
|
AnalyzeCommitsContext,
|
|
@@ -16,259 +12,219 @@ import {
|
|
|
16
12
|
SuccessContext,
|
|
17
13
|
VerifyConditionsContext,
|
|
18
14
|
} from 'semantic-release';
|
|
15
|
+
import { analyzeCommits as commitAnalyzerAnalyzeCommits } from '@semantic-release/commit-analyzer';
|
|
16
|
+
import { prepare as gitPrepare, verifyConditions as gitVerifyConditions } from '@semantic-release/git';
|
|
17
|
+
import {
|
|
18
|
+
addChannel as gitHubAddChanel,
|
|
19
|
+
fail as gitHubFail,
|
|
20
|
+
publish as gitHubPublish,
|
|
21
|
+
success as gitHubSuccess,
|
|
22
|
+
verifyConditions as gitHubVerifyConditions,
|
|
23
|
+
} from '@semantic-release/github';
|
|
24
|
+
import { generateNotes as notesGeneratorGenerateNotes } from '@semantic-release/release-notes-generator';
|
|
19
25
|
|
|
20
26
|
import { SemanticReleasePlugin } from '../types.js';
|
|
21
27
|
|
|
28
|
+
const tarballFile = 'nextTag-stable.tar.gz';
|
|
29
|
+
|
|
22
30
|
const analyzerConfig = {
|
|
23
|
-
preset: 'conventionalcommits',
|
|
24
31
|
parserOpts: {
|
|
25
|
-
headerPattern: /^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/,
|
|
26
32
|
headerCorrespondence: ['type', 'exclamation1', 'scope', 'exclamation2', 'subject'],
|
|
33
|
+
headerPattern: /^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/,
|
|
27
34
|
},
|
|
35
|
+
preset: 'conventionalcommits',
|
|
28
36
|
releaseRules: [
|
|
29
|
-
{
|
|
30
|
-
{
|
|
31
|
-
{
|
|
32
|
-
{
|
|
33
|
-
{
|
|
34
|
-
{
|
|
35
|
-
{
|
|
36
|
-
{
|
|
37
|
-
{
|
|
38
|
-
{
|
|
39
|
-
{
|
|
40
|
-
{
|
|
41
|
-
{
|
|
37
|
+
{ exclamation1: '!', release: 'major', type: 'feat' },
|
|
38
|
+
{ exclamation2: '!', release: 'major', type: 'feat' },
|
|
39
|
+
{ release: 'minor', type: 'feat' },
|
|
40
|
+
{ release: 'patch', type: 'fix' },
|
|
41
|
+
{ release: 'patch', type: 'docs' },
|
|
42
|
+
{ release: 'patch', type: 'style' },
|
|
43
|
+
{ release: 'patch', type: 'refactor' },
|
|
44
|
+
{ release: 'patch', type: 'perf' },
|
|
45
|
+
{ release: 'patch', type: 'test' },
|
|
46
|
+
{ release: 'patch', type: 'build' },
|
|
47
|
+
{ release: 'patch', type: 'ci' },
|
|
48
|
+
{ release: 'patch', type: 'chore' },
|
|
49
|
+
{ release: 'patch', type: 'revert' },
|
|
42
50
|
],
|
|
43
51
|
};
|
|
44
52
|
|
|
45
|
-
type PluginConfig = {
|
|
53
|
+
type PluginConfig = {
|
|
54
|
+
tap?: string;
|
|
55
|
+
};
|
|
46
56
|
|
|
47
57
|
let verified = false;
|
|
48
58
|
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
async function addChannel(pluginConfig: PluginConfig, context: AddChannelContext): Promise<void> {
|
|
60
|
+
if (!verified) {
|
|
61
|
+
await verifyConditions(pluginConfig, context);
|
|
62
|
+
verified = true;
|
|
63
|
+
}
|
|
54
64
|
|
|
55
|
-
|
|
65
|
+
await gitHubAddChanel(pluginConfig, context);
|
|
56
66
|
}
|
|
57
67
|
|
|
58
|
-
async function
|
|
59
|
-
if (!
|
|
60
|
-
|
|
68
|
+
async function analyzeCommits(pluginConfig: PluginConfig, context: AnalyzeCommitsContext): Promise<string | false> {
|
|
69
|
+
if (!verified) {
|
|
70
|
+
await verifyConditions(pluginConfig, context);
|
|
71
|
+
verified = true;
|
|
61
72
|
}
|
|
62
73
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const repositoryUrl = options.repositoryUrl!; // Guaranteed to be defined by semantic-release
|
|
66
|
-
const [owner, repo] = new URL(repositoryUrl).pathname.slice(1).split('/');
|
|
67
|
-
|
|
68
|
-
const formulaFile = getFormulaFile(pluginConfig, repositoryUrl);
|
|
69
|
-
const branchName = options.branch ?? 'main';
|
|
70
|
-
|
|
71
|
-
logger.log(`Committing updated formula file ${formulaFile} to branch ${branchName}...`);
|
|
72
|
-
|
|
73
|
-
const octokit = new Octokit({
|
|
74
|
-
auth: process.env.GITHUB_TOKEN,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
// Get the latest commit SHA and tree SHA from the branch
|
|
79
|
-
const { data: branch } = await octokit.repos.getBranch({
|
|
80
|
-
owner,
|
|
81
|
-
repo,
|
|
82
|
-
branch: branchName,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const latestCommitSha = branch.commit.sha;
|
|
86
|
-
const baseTreeSha = branch.commit.commit.tree.sha;
|
|
87
|
-
|
|
88
|
-
logger.log(`Latest commit SHA: ${latestCommitSha}`);
|
|
89
|
-
logger.log(`Base tree SHA: ${baseTreeSha}`);
|
|
90
|
-
|
|
91
|
-
// Read the updated formula file content
|
|
92
|
-
const formulaContent = fs.readFileSync(formulaFile, 'utf8');
|
|
93
|
-
|
|
94
|
-
// Create a new blob for the updated formula file
|
|
95
|
-
const { data: blob } = await octokit.git.createBlob({
|
|
96
|
-
owner,
|
|
97
|
-
repo,
|
|
98
|
-
content: formulaContent,
|
|
99
|
-
encoding: 'utf-8',
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
logger.log(`Created blob for ${formulaFile} with SHA: ${blob.sha}`);
|
|
103
|
-
|
|
104
|
-
// Create a new tree with the updated formula file
|
|
105
|
-
const { data: newTree } = await octokit.git.createTree({
|
|
106
|
-
owner,
|
|
107
|
-
repo,
|
|
108
|
-
base_tree: baseTreeSha,
|
|
109
|
-
tree: [
|
|
110
|
-
{
|
|
111
|
-
path: formulaFile,
|
|
112
|
-
mode: '100644',
|
|
113
|
-
type: 'blob',
|
|
114
|
-
sha: blob.sha,
|
|
115
|
-
},
|
|
116
|
-
],
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
logger.log(`Created new tree with SHA: ${newTree.sha}`);
|
|
120
|
-
|
|
121
|
-
// Create a new commit with the updated tree
|
|
122
|
-
const commitMessage = `chore(release): ${nextRelease.version}`;
|
|
123
|
-
const { data: newCommit } = await octokit.git.createCommit({
|
|
124
|
-
owner,
|
|
125
|
-
repo,
|
|
126
|
-
message: commitMessage,
|
|
127
|
-
tree: newTree.sha,
|
|
128
|
-
parents: [latestCommitSha],
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
logger.log(`Created new commit with SHA: ${newCommit.sha}`);
|
|
132
|
-
|
|
133
|
-
// Update the branch reference to point to the new commit
|
|
134
|
-
await octokit.git.updateRef({
|
|
135
|
-
owner,
|
|
136
|
-
repo,
|
|
137
|
-
ref: `heads/${branchName}`,
|
|
138
|
-
sha: newCommit.sha,
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
logger.log(`Branch ${branchName} updated to commit ${newCommit.sha}`);
|
|
142
|
-
} catch (error) {
|
|
143
|
-
logger.error(`Failed to commit formula file: ${(error as Error).message}`);
|
|
144
|
-
throw error;
|
|
145
|
-
}
|
|
74
|
+
return commitAnalyzerAnalyzeCommits(analyzerConfig, context);
|
|
146
75
|
}
|
|
147
76
|
|
|
148
|
-
|
|
149
|
-
const {
|
|
77
|
+
function calculateSha256(_pluginConfig: PluginConfig, context: PrepareContext) {
|
|
78
|
+
const { nextRelease } = context;
|
|
150
79
|
|
|
151
|
-
|
|
80
|
+
const nextTag = `v${nextRelease.version}`;
|
|
81
|
+
const tarFilePath = tarballFile.replace('nextTag', nextTag);
|
|
152
82
|
|
|
153
|
-
const
|
|
83
|
+
const fileBuffer = fs.readFileSync(tarFilePath);
|
|
84
|
+
const hash = crypto.createHash('sha256');
|
|
85
|
+
hash.update(fileBuffer);
|
|
154
86
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
87
|
+
return hash.digest('hex');
|
|
88
|
+
}
|
|
158
89
|
|
|
159
|
-
|
|
160
|
-
|
|
90
|
+
async function fail(pluginConfig: PluginConfig, context: FailContext): Promise<void> {
|
|
91
|
+
await gitHubFail(pluginConfig, context);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function generateNotes(pluginConfig: PluginConfig, context: GenerateNotesContext): Promise<string> {
|
|
95
|
+
if (!verified) {
|
|
96
|
+
await verifyConditions(pluginConfig, context);
|
|
97
|
+
verified = true;
|
|
161
98
|
}
|
|
162
99
|
|
|
163
|
-
|
|
164
|
-
const reader = response.body.getReader();
|
|
165
|
-
|
|
166
|
-
return new Promise((resolve, reject) => {
|
|
167
|
-
function read() {
|
|
168
|
-
reader
|
|
169
|
-
.read()
|
|
170
|
-
.then(({ done, value }) => {
|
|
171
|
-
if (done) {
|
|
172
|
-
resolve(hash.digest('hex'));
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
if (value) {
|
|
176
|
-
hash.update(value);
|
|
177
|
-
}
|
|
178
|
-
read();
|
|
179
|
-
})
|
|
180
|
-
.catch(reject);
|
|
181
|
-
}
|
|
182
|
-
read();
|
|
183
|
-
});
|
|
100
|
+
return notesGeneratorGenerateNotes({}, context);
|
|
184
101
|
}
|
|
185
102
|
|
|
186
|
-
|
|
187
|
-
const { nextRelease
|
|
103
|
+
function generateTarball(_pluginConfig: PluginConfig, context: PrepareContext) {
|
|
104
|
+
const { nextRelease } = context;
|
|
188
105
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
106
|
+
const nextTag = `v${nextRelease.version}`;
|
|
107
|
+
const tarFilePath = tarballFile.replace('nextTag', nextTag);
|
|
192
108
|
|
|
193
|
-
|
|
109
|
+
execSync(`git archive --format=tar.gz --output=${tarFilePath} HEAD`);
|
|
110
|
+
}
|
|
194
111
|
|
|
195
|
-
|
|
112
|
+
function getFormulaFile(pluginConfig: PluginConfig, context: PrepareContext): string {
|
|
113
|
+
const { options } = context;
|
|
114
|
+
const repositoryUrl = options.repositoryUrl;
|
|
115
|
+
if (!repositoryUrl) {
|
|
116
|
+
throw new Error('semantic-release repositoryUrl is required');
|
|
117
|
+
}
|
|
196
118
|
const url = new URL(repositoryUrl);
|
|
197
119
|
const repositoryPath = url.pathname;
|
|
198
120
|
const repository = repositoryPath.startsWith('/') ? repositoryPath.slice(1) : repositoryPath;
|
|
121
|
+
const project = repository.split('/').pop();
|
|
199
122
|
|
|
200
|
-
|
|
201
|
-
const sha256 = await calculateSha256(tarUrl, context);
|
|
202
|
-
const formulaFile = getFormulaFile(pluginConfig, repositoryUrl);
|
|
203
|
-
|
|
204
|
-
let formulaContent = fs.readFileSync(formulaFile, 'utf8');
|
|
205
|
-
formulaContent = formulaContent.replace(/url ".*"/, `url "${tarUrl}"`);
|
|
206
|
-
formulaContent = formulaContent.replace(/sha256 ".*"/, `sha256 "${sha256}"`);
|
|
207
|
-
fs.writeFileSync(formulaFile, formulaContent);
|
|
208
|
-
|
|
209
|
-
logger.log(`Updated formula with version ${tagName}, URL ${tarUrl}, and SHA256 ${sha256}`);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
async function addChannel(_pluginConfig: PluginConfig, _context: AddChannelContext): Promise<void> {
|
|
213
|
-
//do nothing
|
|
123
|
+
return pluginConfig.tap ?? `${project}.rb`;
|
|
214
124
|
}
|
|
215
125
|
|
|
216
|
-
async function
|
|
126
|
+
async function prepare(pluginConfig: PluginConfig, context: PrepareContext): Promise<void> {
|
|
217
127
|
if (!verified) {
|
|
218
128
|
await verifyConditions(pluginConfig, context);
|
|
219
129
|
verified = true;
|
|
220
130
|
}
|
|
221
131
|
|
|
222
|
-
|
|
223
|
-
|
|
132
|
+
const { nextRelease } = context;
|
|
133
|
+
if (!nextRelease.version) {
|
|
134
|
+
throw new Error('Next release version is not available.');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const formulaFile = getFormulaFile(pluginConfig, context);
|
|
138
|
+
|
|
139
|
+
generateTarball(pluginConfig, context);
|
|
140
|
+
updateFormulaFile(pluginConfig, context);
|
|
224
141
|
|
|
225
|
-
|
|
226
|
-
|
|
142
|
+
await gitPrepare(
|
|
143
|
+
{
|
|
144
|
+
assets: [formulaFile],
|
|
145
|
+
message: 'chore(release): ${nextRelease.version}',
|
|
146
|
+
},
|
|
147
|
+
context,
|
|
148
|
+
);
|
|
227
149
|
}
|
|
228
150
|
|
|
229
|
-
async function
|
|
151
|
+
async function publish(pluginConfig: PluginConfig, context: PublishContext): Promise<unknown> {
|
|
230
152
|
if (!verified) {
|
|
231
153
|
await verifyConditions(pluginConfig, context);
|
|
232
154
|
verified = true;
|
|
233
155
|
}
|
|
234
156
|
|
|
235
|
-
|
|
236
|
-
}
|
|
157
|
+
const { nextRelease } = context;
|
|
158
|
+
const nextTag = `v${nextRelease.version}`;
|
|
159
|
+
const tarFilePath = tarballFile.replace('nextTag', nextTag);
|
|
160
|
+
|
|
161
|
+
const customPluginConfig = {
|
|
162
|
+
...pluginConfig,
|
|
163
|
+
assets: [
|
|
164
|
+
{
|
|
165
|
+
label: `Homebrew Tarball (${nextTag})`,
|
|
166
|
+
path: tarFilePath,
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
await gitHubPublish(customPluginConfig, context);
|
|
237
171
|
|
|
238
|
-
|
|
239
|
-
//
|
|
172
|
+
//await updateFormulaFile(pluginConfig, context);
|
|
173
|
+
//await commitFormulaFile(pluginConfig, context);
|
|
174
|
+
|
|
175
|
+
return null;
|
|
240
176
|
}
|
|
241
177
|
|
|
242
|
-
async function
|
|
178
|
+
async function success(pluginConfig: PluginConfig, context: SuccessContext): Promise<void> {
|
|
243
179
|
if (!verified) {
|
|
244
180
|
await verifyConditions(pluginConfig, context);
|
|
245
181
|
verified = true;
|
|
246
182
|
}
|
|
247
183
|
|
|
248
|
-
await
|
|
184
|
+
await gitHubSuccess(pluginConfig, context);
|
|
185
|
+
}
|
|
249
186
|
|
|
250
|
-
|
|
187
|
+
function updateFormulaFile(pluginConfig: PluginConfig, context: PrepareContext): void {
|
|
188
|
+
const { nextRelease, options } = context;
|
|
251
189
|
|
|
252
|
-
|
|
253
|
-
|
|
190
|
+
const nextTag = `v${nextRelease.version}`;
|
|
191
|
+
|
|
192
|
+
const repositoryUrl = options.repositoryUrl;
|
|
193
|
+
if (!repositoryUrl) {
|
|
194
|
+
throw new Error('semantic-release repositoryUrl is required');
|
|
195
|
+
}
|
|
196
|
+
const url = new URL(repositoryUrl);
|
|
197
|
+
const repositoryPath = url.pathname;
|
|
198
|
+
const repository = repositoryPath.startsWith('/') ? repositoryPath.slice(1) : repositoryPath;
|
|
199
|
+
const tarFilePath = tarballFile.replace('nextTag', nextTag);
|
|
254
200
|
|
|
255
|
-
|
|
256
|
-
//
|
|
201
|
+
const tarUrl = `https://github.com/${repository}/releases/download/${nextTag}/${tarFilePath}`;
|
|
202
|
+
//const tarUrl = `https://codeload.github.com/${repository}/tar.gz/refs/tags/${tarFilePath}`;
|
|
203
|
+
|
|
204
|
+
const sha256 = calculateSha256(pluginConfig, context);
|
|
205
|
+
const formulaFile = getFormulaFile(pluginConfig, context);
|
|
206
|
+
|
|
207
|
+
let formulaContent = fs.readFileSync(formulaFile, 'utf8');
|
|
208
|
+
formulaContent = formulaContent.replace(/url ".*"/, `url "${tarUrl}"`);
|
|
209
|
+
formulaContent = formulaContent.replace(/sha256 ".*"/, `sha256 "${sha256}"`);
|
|
210
|
+
fs.writeFileSync(formulaFile, formulaContent);
|
|
257
211
|
}
|
|
258
212
|
|
|
259
|
-
async function verifyConditions(
|
|
213
|
+
async function verifyConditions(pluginConfig: PluginConfig, context: VerifyConditionsContext): Promise<void> {
|
|
214
|
+
await gitHubVerifyConditions(pluginConfig, context);
|
|
215
|
+
await gitVerifyConditions(pluginConfig, context);
|
|
260
216
|
verified = true;
|
|
261
217
|
}
|
|
262
218
|
|
|
263
219
|
const plugin: SemanticReleasePlugin<{ tap: string }> = {
|
|
264
220
|
addChannel,
|
|
265
|
-
verifyConditions,
|
|
266
221
|
analyzeCommits,
|
|
222
|
+
fail,
|
|
267
223
|
generateNotes,
|
|
268
224
|
prepare,
|
|
269
225
|
publish,
|
|
270
226
|
success,
|
|
271
|
-
|
|
227
|
+
verifyConditions,
|
|
272
228
|
};
|
|
273
229
|
|
|
274
230
|
export default plugin;
|
|
@@ -1,49 +1,39 @@
|
|
|
1
|
-
//@ts-ignore
|
|
2
1
|
import { analyzeCommits } from '@semantic-release/commit-analyzer';
|
|
2
|
+
import { prepare as gitPrepare, verifyConditions as gitVerifyConditions } from '@semantic-release/git';
|
|
3
3
|
import {
|
|
4
|
-
prepare as gitPrepare,
|
|
5
|
-
verifyConditions as gitVerifyConditions,
|
|
6
|
-
//@ts-ignore
|
|
7
|
-
} from '@semantic-release/git';
|
|
8
|
-
import {
|
|
9
|
-
addChannel as npmAddChannel,
|
|
10
4
|
prepare as npmPrepare,
|
|
11
5
|
publish as npmPublish,
|
|
12
6
|
verifyConditions as npmVerifyConditions,
|
|
13
|
-
//@ts-ignore
|
|
14
7
|
} from '@semantic-release/npm';
|
|
15
|
-
//@ts-ignore
|
|
16
8
|
import { generateNotes } from '@semantic-release/release-notes-generator';
|
|
17
9
|
|
|
18
10
|
import { SemanticReleasePlugin } from '../types.js';
|
|
19
11
|
|
|
20
12
|
const analyzerConfig = {
|
|
21
|
-
preset: 'conventionalcommits',
|
|
22
13
|
parserOpts: {
|
|
23
|
-
headerPattern: /^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/,
|
|
24
14
|
headerCorrespondence: ['type', 'exclamation1', 'scope', 'exclamation2', 'subject'],
|
|
15
|
+
headerPattern: /^(?<type>\w+)(?<exclamation1>!?)(?:\((?<scope>[^)]+)\)(?<exclamation2>!?))?: (?<subject>.+)$/,
|
|
25
16
|
},
|
|
17
|
+
preset: 'conventionalcommits',
|
|
26
18
|
releaseRules: [
|
|
27
|
-
{
|
|
28
|
-
{
|
|
29
|
-
{
|
|
30
|
-
{
|
|
31
|
-
{
|
|
32
|
-
{
|
|
33
|
-
{
|
|
34
|
-
{
|
|
35
|
-
{
|
|
36
|
-
{
|
|
37
|
-
{
|
|
38
|
-
{
|
|
39
|
-
{
|
|
19
|
+
{ exclamation1: '!', release: 'major', type: 'feat' },
|
|
20
|
+
{ exclamation2: '!', release: 'major', type: 'feat' },
|
|
21
|
+
{ release: 'minor', type: 'feat' },
|
|
22
|
+
{ release: 'patch', type: 'fix' },
|
|
23
|
+
{ release: 'patch', type: 'docs' },
|
|
24
|
+
{ release: 'patch', type: 'style' },
|
|
25
|
+
{ release: 'patch', type: 'refactor' },
|
|
26
|
+
{ release: 'patch', type: 'perf' },
|
|
27
|
+
{ release: 'patch', type: 'test' },
|
|
28
|
+
{ release: 'patch', type: 'build' },
|
|
29
|
+
{ release: 'patch', type: 'ci' },
|
|
30
|
+
{ release: 'patch', type: 'chore' },
|
|
31
|
+
{ release: 'patch', type: 'revert' },
|
|
40
32
|
],
|
|
41
33
|
};
|
|
42
34
|
|
|
43
35
|
const npmConfig = {
|
|
44
|
-
tag: 'latest',
|
|
45
36
|
npmPublish: true,
|
|
46
|
-
optional: false,
|
|
47
37
|
};
|
|
48
38
|
|
|
49
39
|
const gitConfig = {
|
|
@@ -52,56 +42,38 @@ const gitConfig = {
|
|
|
52
42
|
};
|
|
53
43
|
|
|
54
44
|
const plugin: SemanticReleasePlugin = {
|
|
55
|
-
addChannel: async (_pluginConfig,
|
|
56
|
-
|
|
57
|
-
await npmAddChannel(npmConfig, context);
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
verifyConditions: async (_pluginConfig, context) => {
|
|
61
|
-
if (npmVerifyConditions) {
|
|
62
|
-
await npmVerifyConditions(npmConfig, context);
|
|
63
|
-
}
|
|
64
|
-
if (gitVerifyConditions) {
|
|
65
|
-
await gitVerifyConditions(gitConfig, context);
|
|
66
|
-
}
|
|
45
|
+
addChannel: async (_pluginConfig, _context) => {
|
|
46
|
+
//await npmAddChannel(npmConfig, context);
|
|
67
47
|
},
|
|
68
|
-
|
|
69
48
|
analyzeCommits: async (_pluginConfig, context) => {
|
|
70
49
|
return analyzeCommits(analyzerConfig, context);
|
|
71
50
|
},
|
|
72
51
|
|
|
52
|
+
fail: async (_pluginConfig, _context) => {
|
|
53
|
+
//await gitFail(gitConfig, context);
|
|
54
|
+
},
|
|
55
|
+
|
|
73
56
|
generateNotes: async (_pluginConfig, context) => {
|
|
74
57
|
return generateNotes({}, context);
|
|
75
58
|
},
|
|
76
59
|
|
|
77
60
|
prepare: async (_pluginConfig, context) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
if (gitPrepare) {
|
|
82
|
-
await gitPrepare(gitConfig, context);
|
|
83
|
-
}
|
|
61
|
+
await npmPrepare(npmConfig, context);
|
|
62
|
+
await gitPrepare(gitConfig, context);
|
|
84
63
|
},
|
|
85
64
|
|
|
86
65
|
publish: async (_pluginConfig, context) => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
/*if (gitPublish) {
|
|
91
|
-
await gitPublish(gitConfig, context);
|
|
92
|
-
}*/
|
|
66
|
+
await npmPublish(npmConfig, context);
|
|
67
|
+
//await gitPublish(gitConfig, context);
|
|
93
68
|
},
|
|
94
69
|
|
|
95
70
|
success: async (_pluginConfig, _context) => {
|
|
96
|
-
|
|
97
|
-
await gitSuccess(gitConfig, context);
|
|
98
|
-
}*/
|
|
71
|
+
//await gitSuccess(gitConfig, context);
|
|
99
72
|
},
|
|
100
73
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}*/
|
|
74
|
+
verifyConditions: async (_pluginConfig, context) => {
|
|
75
|
+
await npmVerifyConditions(npmConfig, context);
|
|
76
|
+
await gitVerifyConditions(gitConfig, context);
|
|
105
77
|
},
|
|
106
78
|
};
|
|
107
79
|
|