chore(release): create a github release on new version
This commit is contained in:
		
							parent
							
								
									e78b33bee8
								
							
						
					
					
						commit
						fab8629ebf
					
				
							
								
								
									
										43
									
								
								.github/workflows/releases.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								.github/workflows/releases.yml
									
									
									
									
										vendored
									
									
								
							| @ -46,3 +46,46 @@ jobs: | ||||
|             corentinth/it-tools:${{ env.RELEASE_VERSION }} | ||||
|             ghcr.io/corentinth/it-tools:latest | ||||
|             ghcr.io/corentinth/it-tools:${{ env.RELEASE_VERSION}} | ||||
| 
 | ||||
|   github-release: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Get release version | ||||
|         run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV | ||||
| 
 | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
| 
 | ||||
|       - uses: actions/setup-node@v3 | ||||
|         with: | ||||
|           node-version: 16 | ||||
|           cache: 'pnpm' | ||||
| 
 | ||||
|       - name: Install dependencies | ||||
|         run: pnpm i | ||||
| 
 | ||||
|       - name: Build the app | ||||
|         run: pnpm build | ||||
| 
 | ||||
|       - name: Zip the app | ||||
|         run: zip -r it-tools-${{ env.RELEASE_VERSION }}.zip dist/* | ||||
| 
 | ||||
|       - name: Create Release | ||||
|         uses: softprops/action-gh-release@v1 | ||||
|         with: | ||||
|           token: ${{ secrets.GITHUB_TOKEN }} | ||||
|           files: it-tools-${{ env.RELEASE_VERSION }}.zip | ||||
|           tag_name: ${{ env.RELEASE_VERSION }} | ||||
|           draft: true | ||||
|           prerelease: false | ||||
|           body: | | ||||
|             ## Docker images | ||||
| 
 | ||||
|             - `corentinth/it-tools:latest` | ||||
|             - `corentinth/it-tools:${{ env.RELEASE_VERSION }}` | ||||
|             - `ghcr.io/corentinth/it-tools:latest` | ||||
|             - `ghcr.io/corentinth/it-tools:${{ env.RELEASE_VERSION}}` | ||||
| 
 | ||||
|             ## Changelog | ||||
| 
 | ||||
|             $(node ./scripts/getLatestChangelog.mjs) | ||||
|  | ||||
| @ -30,7 +30,7 @@ | ||||
|     "typecheck": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", | ||||
|     "lint": "eslint src --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --ignore-path .gitignore", | ||||
|     "script:create-new-tool": "node scripts/create-tool.mjs", | ||||
|     "release": "standard-version" | ||||
|     "release": "node ./scripts/release.mjs" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@it-tools/bip39": "^0.0.4", | ||||
| @ -101,6 +101,7 @@ | ||||
|     "@vue/test-utils": "^2.3.2", | ||||
|     "@vue/tsconfig": "^0.1.3", | ||||
|     "c8": "^7.13.0", | ||||
|     "consola": "^3.0.2", | ||||
|     "eslint": "^8.38.0", | ||||
|     "eslint-config-prettier": "^8.8.0", | ||||
|     "eslint-import-resolver-typescript": "^3.5.5", | ||||
| @ -109,7 +110,6 @@ | ||||
|     "jsdom": "^19.0.0", | ||||
|     "less": "^4.1.3", | ||||
|     "prettier": "^2.8.7", | ||||
|     "standard-version": "^9.5.0", | ||||
|     "start-server-and-test": "^1.15.4", | ||||
|     "typescript": "~4.5.5", | ||||
|     "unocss": "^0.50.8", | ||||
| @ -121,6 +121,7 @@ | ||||
|     "vite-svg-loader": "^3.6.0", | ||||
|     "vitest": "^0.13.1", | ||||
|     "vue-tsc": "^0.31.4", | ||||
|     "workbox-window": "^6.5.4" | ||||
|     "workbox-window": "^6.5.4", | ||||
|     "zx": "^7.2.1" | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										942
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										942
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										6
									
								
								scripts/getLatestChangelog.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								scripts/getLatestChangelog.mjs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| import { readFile } from 'fs/promises'; | ||||
| 
 | ||||
| const changelogContent = await readFile('./CHANGELOG.md', 'utf-8'); | ||||
| const [, lastChangelog] = changelogContent.split(/^## .*$/gm); | ||||
| 
 | ||||
| console.log(lastChangelog.trim()); | ||||
							
								
								
									
										57
									
								
								scripts/release.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								scripts/release.mjs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| import { $, argv } from 'zx'; | ||||
| import { consola } from 'consola'; | ||||
| import { rawCommitsToMarkdown } from './shared/commits.mjs'; | ||||
| import { addToChangelog } from './shared/changelog.mjs'; | ||||
| 
 | ||||
| $.verbose = false; | ||||
| 
 | ||||
| const isDryRun = argv['dry-run'] ?? false; | ||||
| 
 | ||||
| const now = new Date(); | ||||
| const currentShortSha = (await $`git rev-parse --short HEAD`).stdout.trim(); | ||||
| 
 | ||||
| const calver = now.toISOString().slice(0, 10).replace(/-/g, '.'); | ||||
| const version = `${calver}-${currentShortSha}`; | ||||
| 
 | ||||
| const { stdout: rawCommits } = await $`git log --pretty=oneline $(git describe --tags --abbrev=0)..HEAD`; | ||||
| 
 | ||||
| const markdown = rawCommitsToMarkdown({ rawCommits }); | ||||
| 
 | ||||
| consola.info(`Changelog: \n\n${markdown}\n\n`); | ||||
| 
 | ||||
| if (isDryRun) { | ||||
|   consola.info(`[dry-run] Not creating version nor tag`); | ||||
|   consola.info('Aborting'); | ||||
|   process.exit(0); | ||||
| } | ||||
| 
 | ||||
| const shouldContinue = await consola.prompt( | ||||
|   'This script will create a new version and tag, and update the changelog. Continue?', | ||||
|   { | ||||
|     type: 'confirm', | ||||
|   }, | ||||
| ); | ||||
| 
 | ||||
| if (!shouldContinue) { | ||||
|   consola.info('Aborting'); | ||||
|   process.exit(0); | ||||
| } | ||||
| 
 | ||||
| consola.info('Updating changelog'); | ||||
| await addToChangelog({ changelog: markdown, version }); | ||||
| consola.success('Changelog updated'); | ||||
| 
 | ||||
| try { | ||||
|   consola.info('Committing changelog changes'); | ||||
|   await $`git add CHANGELOG.md`; | ||||
|   await $`git commit -m "docs(changelog): update changelog for ${version}"`; | ||||
|   consola.success('Changelog changes committed'); | ||||
| 
 | ||||
|   consola.info('Creating version and tag'); | ||||
|   await $`npm version ${version} -m "chore(version): release ${version}"`; | ||||
|   consola.info('Npm version released with tag'); | ||||
| } catch (error) { | ||||
|   consola.error(error); | ||||
|   consola.info('Aborting'); | ||||
|   process.exit(1); | ||||
| } | ||||
							
								
								
									
										15
									
								
								scripts/shared/changelog.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								scripts/shared/changelog.mjs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import { readFile, writeFile } from 'fs/promises'; | ||||
| 
 | ||||
| export { addToChangelog }; | ||||
| 
 | ||||
| async function addToChangelog({ changelog, version, changelogPath = './CHANGELOG.md' }) { | ||||
|   const changelogContent = await readFile(changelogPath, 'utf-8'); | ||||
|   const versionTitle = `## Version ${version}`; | ||||
| 
 | ||||
|   if (changelogContent.includes(versionTitle)) { | ||||
|     throw new Error(`Version ${version} already exists in the changelog`); | ||||
|   } | ||||
| 
 | ||||
|   const newChangeLogContent = changelogContent.replace('## ', `${versionTitle}\n\n${changelog}\n\n## `); | ||||
|   await writeFile(changelogPath, newChangeLogContent, 'utf-8'); | ||||
| } | ||||
							
								
								
									
										52
									
								
								scripts/shared/commits.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								scripts/shared/commits.mjs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| import _ from 'lodash'; | ||||
| 
 | ||||
| export { rawCommitsToMarkdown }; | ||||
| 
 | ||||
| const commitScopesToHumanReadable = { | ||||
|   build: 'Build system', | ||||
|   chore: 'Chores', | ||||
|   ci: 'Continuous integration', | ||||
|   docs: 'Documentation', | ||||
|   feat: 'Features', | ||||
|   fix: 'Bug fixes', | ||||
|   infra: 'Infrastucture', | ||||
|   perf: 'Performance', | ||||
|   refactor: 'Refactoring', | ||||
|   test: 'Tests', | ||||
| }; | ||||
| 
 | ||||
| const commitTypesOrder = ['feat', 'fix', 'perf', 'refactor', 'test', 'build', 'ci', 'chore', 'other']; | ||||
| 
 | ||||
| function parseCommitLine(commit) { | ||||
|   const [sha, ...splittedRawMessage] = commit.trim().split(' '); | ||||
|   const rawMessage = splittedRawMessage.join(' '); | ||||
|   const { type, scope, subject } = /^(?<type>.*?)(\((?<scope>.*)\))?: ?(?<subject>.+)$/.exec(rawMessage)?.groups ?? {}; | ||||
| 
 | ||||
|   return { | ||||
|     sha: sha.slice(0, 7), | ||||
|     type: type ?? 'other', | ||||
|     scope, | ||||
|     subject: subject ?? rawMessage, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| function commitSectionsToMarkdown({ type, commits }) { | ||||
|   return [ | ||||
|     `### ${commitScopesToHumanReadable[type] ?? _.capitalize(type)}`, | ||||
|     ...commits.map(({ sha, scope, subject }) => ['-', scope ? `**${scope}**:` : '', subject, `(${sha})`].join(' ')), | ||||
|   ].join('\n'); | ||||
| } | ||||
| 
 | ||||
| function rawCommitsToMarkdown({ rawCommits }) { | ||||
|   return _.chain(rawCommits) | ||||
|     .trim() | ||||
|     .split('\n') | ||||
|     .map(parseCommitLine) | ||||
|     .groupBy('type') | ||||
|     .map((commits, type) => ({ type, commits })) | ||||
|     .sortBy(({ type }) => commitTypesOrder.reverse().indexOf(type)) | ||||
|     .reverse() | ||||
|     .map(commitSectionsToMarkdown) | ||||
|     .join('\n\n') | ||||
|     .value(); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user