Skip to content

Commit 652816f

Browse files
authored
feat: support assets to releases (#68)
1 parent 30e92f0 commit 652816f

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

src/cli.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { blue, bold, cyan, dim, red, yellow } from 'ansis'
66
import cac from 'cac'
77
import { execa } from 'execa'
88
import { version } from '../package.json'
9+
import { uploadAssets } from './github'
910
import { generate, hasTagOnGitHub, isRepoShallow, sendRelease } from './index'
1011

1112
const cli = cac('changelogithub')
@@ -26,6 +27,7 @@ cli
2627
.option('--emoji', 'Use emojis in section titles', { default: true })
2728
.option('--group', 'Nest commit messages under their scopes')
2829
.option('--dry', 'Dry run')
30+
.option('--assets <paths...>', 'Files to upload as assets to the release')
2931
.help()
3032

3133
async function readTokenFromGitHubCli() {
@@ -103,6 +105,10 @@ cli
103105
}
104106

105107
await sendRelease(config, md)
108+
109+
if (args.assets && args.assets.length > 0) {
110+
await uploadAssets(config, args.assets)
111+
}
106112
}
107113
catch (e: any) {
108114
console.error(red(String(e)))

src/github.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import type { AuthorInfo, ChangelogOptions, Commit } from './types'
2-
import { notNullish } from '@antfu/utils'
3-
import { cyan, green } from 'ansis'
2+
import fs from 'node:fs/promises'
3+
import path from 'node:path'
44
/* eslint-disable no-console */
5+
import { notNullish } from '@antfu/utils'
6+
import { cyan, green, red } from 'ansis'
57
import { $fetch } from 'ofetch'
68

79
export async function sendRelease(
@@ -147,3 +149,46 @@ export async function hasTagOnGitHub(tag: string, options: ChangelogOptions) {
147149
return false
148150
}
149151
}
152+
153+
export async function uploadAssets(options: ChangelogOptions, assets: string | string[]) {
154+
const headers = getHeaders(options)
155+
156+
let assetList: string[] = []
157+
if (typeof assets === 'string') {
158+
assetList = assets.split(',').map(s => s.trim()).filter(Boolean)
159+
}
160+
else if (Array.isArray(assets)) {
161+
assetList = assets.flatMap(item =>
162+
typeof item === 'string' ? item.split(',').map(s => s.trim()) : [],
163+
).filter(Boolean)
164+
}
165+
166+
// Get the release by tag to obtain the upload_url
167+
const release = await $fetch(`https://${options.baseUrlApi}/repos/${options.releaseRepo}/releases/tags/${options.to}`, {
168+
headers,
169+
})
170+
171+
for (const asset of assetList) {
172+
const filePath = path.resolve(asset)
173+
const fileData = await fs.readFile(filePath)
174+
const fileName = path.basename(filePath)
175+
const contentType = 'application/octet-stream'
176+
177+
const uploadUrl = release.upload_url.replace('{?name,label}', `?name=${encodeURIComponent(fileName)}`)
178+
console.log(cyan(`Uploading ${fileName}...`))
179+
try {
180+
await $fetch(uploadUrl, {
181+
method: 'POST',
182+
headers: {
183+
...headers,
184+
'Content-Type': contentType,
185+
},
186+
body: fileData,
187+
})
188+
console.log(green(`Uploaded ${fileName} successfully.`))
189+
}
190+
catch (error) {
191+
console.error(red(`Failed to upload ${fileName}: ${error}`))
192+
}
193+
}
194+
}

src/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ export interface ChangelogOptions extends Partial<ChangelogenOptions> {
9494
* @default `v%s`.
9595
*/
9696
tag?: string
97+
98+
/**
99+
* Files to upload as assets to the release
100+
* `--assets path1,path2` or `--assets path1 --assets path2`
101+
*/
102+
assets?: string[] | string
97103
}
98104

99105
export type ResolvedChangelogOptions = Required<ChangelogOptions>

0 commit comments

Comments
 (0)