Skip to content

Commit

Permalink
feat: add support for Github Enterprise, fix #45 (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
eliamartani authored Mar 21, 2024
1 parent c25a7d1 commit d478844
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ cli
console.log(dim(`changelo${bold('github')} `) + dim(`v${version}`))

const { config, md, commits } = await generate(args as any)
webUrl = `https://github.com/${config.repo}/releases/new?title=${encodeURIComponent(String(config.name || config.to))}&body=${encodeURIComponent(String(md))}&tag=${encodeURIComponent(String(config.to))}&prerelease=${config.prerelease}`
webUrl = `https://${config.baseUrl}/${config.repo}/releases/new?title=${encodeURIComponent(String(config.name || config.to))}&body=${encodeURIComponent(String(md))}&tag=${encodeURIComponent(String(config.to))}&prerelease=${config.prerelease}`

console.log(cyan(config.from) + dim(' -> ') + blue(config.to) + dim(` (${commits.length} commits)`))
console.log(dim('--------------'))
Expand Down
4 changes: 3 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ export async function resolveConfig(options: ChangelogOptions) {
packageJson: 'changelogithub',
}).then(r => r.config || defaultConfig)

config.baseUrl = config.baseUrl ?? 'github.com'
config.baseUrlApi = config.baseUrlApi ?? 'api.github.com'
config.to = config.to || await getCurrentGitBranch()
config.from = config.from || await getLastMatchingTag(config.to) || await getFirstGitCommit()
// @ts-expect-error backward compatibility
config.repo = config.repo || config.github || await getGitHubRepo()
config.repo = config.repo || config.github || await getGitHubRepo(config.baseUrl)
config.prerelease = config.prerelease ?? isPrerelease(config.to)

if (typeof config.repo !== 'string')
Expand Down
6 changes: 4 additions & 2 deletions src/git.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export async function getGitHubRepo() {
export async function getGitHubRepo(baseUrl: string) {
const url = await execCommand('git', ['config', '--get', 'remote.origin.url'])
const match = url.match(/github\.com[\/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i)
const escapedBaseUrl = baseUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
const regex = new RegExp(`${escapedBaseUrl}[\/:]([\\w\\d._-]+?)\\/([\\w\\d._-]+?)(\\.git)?$`, 'i')
const match = regex.exec(url)
if (!match)
throw new Error(`Can not parse GitHub repo from url ${url}`)
return `${match[1]}/${match[2]}`
Expand Down
10 changes: 5 additions & 5 deletions src/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ export async function sendRelease(
content: string,
) {
const headers = getHeaders(options)
let url = `https://api.github.com/repos/${options.repo}/releases`
let url = `https://${options.baseUrlApi}/repos/${options.repo}/releases`
let method = 'POST'

try {
const exists = await $fetch(`https://api.github.com/repos/${options.repo}/releases/tags/${options.to}`, {
const exists = await $fetch(`https://${options.baseUrlApi}/repos/${options.repo}/releases/tags/${options.to}`, {
headers,
})
if (exists.url) {
Expand Down Expand Up @@ -59,7 +59,7 @@ export async function resolveAuthorInfo(options: ChangelogOptions, info: AuthorI
return info

try {
const data = await $fetch(`https://api.github.com/search/users?q=${encodeURIComponent(info.email)}`, {
const data = await $fetch(`https://${options.baseUrlApi}/search/users?q=${encodeURIComponent(info.email)}`, {
headers: getHeaders(options),
})
info.login = data.items[0].login
Expand All @@ -71,7 +71,7 @@ export async function resolveAuthorInfo(options: ChangelogOptions, info: AuthorI

if (info.commits.length) {
try {
const data = await $fetch(`https://api.github.com/repos/${options.repo}/commits/${info.commits[0]}`, {
const data = await $fetch(`https://${options.baseUrlApi}/repos/${options.repo}/commits/${info.commits[0]}`, {
headers: getHeaders(options),
})
info.login = data.author.login
Expand Down Expand Up @@ -128,7 +128,7 @@ export async function resolveAuthors(commits: Commit[], options: ChangelogOption

export async function hasTagOnGitHub(tag: string, options: ChangelogOptions) {
try {
await $fetch(`https://api.github.com/repos/${options.repo}/git/ref/tags/${tag}`, {
await $fetch(`https://${options.baseUrlApi}/repos/${options.repo}/git/ref/tags/${tag}`, {
headers: getHeaders(options),
})
return true
Expand Down
12 changes: 6 additions & 6 deletions src/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { Commit, ResolvedChangelogOptions } from './types'

const emojisRE = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g

function formatReferences(references: Reference[], github: string, type: 'issues' | 'hash'): string {
function formatReferences(references: Reference[], baseUrl: string, github: string, type: 'issues' | 'hash'): string {
const refs = references
.filter((i) => {
if (type === 'issues')
Expand All @@ -16,8 +16,8 @@ function formatReferences(references: Reference[], github: string, type: 'issues
if (!github)
return ref.value
if (ref.type === 'pull-request' || ref.type === 'issue')
return `https://github.com/${github}/issues/${ref.value.slice(1)}`
return `[<samp>(${ref.value.slice(0, 5)})</samp>](https://github.com/${github}/commit/${ref.value})`
return `https://${baseUrl}/${github}/issues/${ref.value.slice(1)}`
return `[<samp>(${ref.value.slice(0, 5)})</samp>](https://${baseUrl}/${github}/commit/${ref.value})`
})

const referencesString = join(refs).trim()
Expand All @@ -28,8 +28,8 @@ function formatReferences(references: Reference[], github: string, type: 'issues
}

function formatLine(commit: Commit, options: ResolvedChangelogOptions) {
const prRefs = formatReferences(commit.references, options.repo as string, 'issues')
const hashRefs = formatReferences(commit.references, options.repo as string, 'hash')
const prRefs = formatReferences(commit.references, options.baseUrl, options.repo as string, 'issues')
const hashRefs = formatReferences(commit.references, options.baseUrl, options.repo as string, 'hash')

let authors = join([...new Set(commit.resolvedAuthors?.map(i => i.login ? `@${i.login}` : `**${i.name}**`))])?.trim()
if (authors)
Expand Down Expand Up @@ -111,7 +111,7 @@ export function generateMarkdown(commits: Commit[], options: ResolvedChangelogOp
if (!lines.length)
lines.push('*No significant changes*')

const url = `https://github.com/${options.repo}/compare/${options.from}...${options.to}`
const url = `https://${options.baseUrl}/${options.repo}/compare/${options.from}...${options.to}`

lines.push('', `##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](${url})`)

Expand Down
10 changes: 10 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ export interface ChangelogOptions extends Partial<ChangelogenOptions> {
* @default true
*/
emoji?: boolean
/**
* Github base url
* @default github.com
*/
baseUrl?: string
/**
* Github base API url
* @default api.github.com
*/
baseUrlApi?: string
}

export type ResolvedChangelogOptions = Required<ChangelogOptions>
Expand Down
46 changes: 42 additions & 4 deletions test/git.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { expect, it } from 'vitest'
import { generate } from '../src'
import { generate, getGitHubRepo } from '../src'

it('parse', async () => {
const COMMIT_FROM = '19cf4f84f16f1a8e1e7032bbef550c382938649d'
const COMMIT_TO = '49b0222e8d60b7f299941def7511cee0460a8149'
const COMMIT_FROM = '19cf4f84f16f1a8e1e7032bbef550c382938649d'
const COMMIT_TO = '49b0222e8d60b7f299941def7511cee0460a8149'
const regexToFindAllUrls = /https:\/\/[^\s]*/g

it('parse', async () => {
const { config, md } = await generate({
from: COMMIT_FROM,
to: COMMIT_TO,
})

expect(config).toMatchInlineSnapshot(`
{
"baseUrl": "github.com",
"baseUrlApi": "api.github.com",
"capitalize": true,
"contributors": true,
"from": "19cf4f84f16f1a8e1e7032bbef550c382938649d",
Expand Down Expand Up @@ -65,3 +68,38 @@ it('parse', async () => {
##### [View changes on GitHub](https://github.com/antfu/changelogithub/compare/19cf4f84f16f1a8e1e7032bbef550c382938649d...49b0222e8d60b7f299941def7511cee0460a8149)"
`)
})

it.each([
{ baseUrl: undefined, baseUrlApi: undefined, repo: undefined },
{ baseUrl: 'test.github.com', baseUrlApi: 'api.test.github.com', repo: 'user/changelogithub' },
])('should generate config while baseUrl is set to $baseUrl', async (proposedConfig) => {
const { config, md } = await generate({
...proposedConfig,
from: COMMIT_FROM,
to: COMMIT_TO,
})

if (proposedConfig.baseUrl) {
expect(config).toEqual(expect.objectContaining(proposedConfig))
}
else {
expect(config).toEqual(expect.objectContaining({
baseUrl: 'github.com',
baseUrlApi: 'api.github.com',
}))
}

const urlsToGithub = md.match(regexToFindAllUrls)
expect(urlsToGithub?.every(url => url.startsWith(`https://${config.baseUrl}`))).toBe(true)
})

it('should match with current github repo', async () => {
const repo = await getGitHubRepo('github.com')
expect(repo).toContain('/changelogithub')
})

it('should throw error when baseUrl is different from git repository', () => {
expect(async () => {
await getGitHubRepo('custom.git.com')
}).rejects.toThrow('Can not parse GitHub repo from url')
})

0 comments on commit d478844

Please sign in to comment.