-
Notifications
You must be signed in to change notification settings - Fork 140
feat: ES Module #419
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: ES Module #419
Changes from all commits
3ca59cf
a8d754a
dcfce6b
6c04ddf
3044a32
e2ee5e6
0fbc003
088ae45
942ddb2
f2ad2f5
420f745
d9087e1
bbe497d
7c05697
c1d286b
12c5174
d16bd93
2c93202
308530b
e06fa6b
ba73adb
bf717df
673017f
14e1a74
e100d3c
0f12010
3c42e02
c2135f1
9991f21
521f663
e6aa1c4
467dfa0
4e462a8
33342d9
365d9fb
24dec8f
f4f1340
decf761
de0ef0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,101 @@ | ||
/* eslint require-atomic-updates: off */ | ||
|
||
const {defaultTo, castArray} = require('lodash'); | ||
const verifyGitHub = require('./lib/verify'); | ||
const addChannelGitHub = require('./lib/add-channel'); | ||
const publishGitHub = require('./lib/publish'); | ||
const successGitHub = require('./lib/success'); | ||
const failGitHub = require('./lib/fail'); | ||
import { defaultTo, castArray } from "lodash-es"; | ||
|
||
import verifyGitHub from "./lib/verify.js"; | ||
import addChannelGitHub from "./lib/add-channel.js"; | ||
import publishGitHub from "./lib/publish.js"; | ||
import successGitHub from "./lib/success.js"; | ||
import failGitHub from "./lib/fail.js"; | ||
import { SemanticReleaseOctokit } from "./lib/octokit.js"; | ||
|
||
let verified; | ||
|
||
async function verifyConditions(pluginConfig, context) { | ||
const {options} = context; | ||
export async function verifyConditions( | ||
pluginConfig, | ||
context, | ||
{ Octokit = SemanticReleaseOctokit } = {} | ||
) { | ||
const { options } = context; | ||
// If the GitHub publish plugin is used and has `assets`, `successComment`, `failComment`, `failTitle`, `labels` or `assignees` configured, validate it now in order to prevent any release if the configuration is wrong | ||
if (options.publish) { | ||
const publishPlugin = | ||
castArray(options.publish).find((config) => config.path && config.path === '@semantic-release/github') || {}; | ||
castArray(options.publish).find( | ||
(config) => config.path && config.path === "@semantic-release/github" | ||
) || {}; | ||
|
||
pluginConfig.assets = defaultTo(pluginConfig.assets, publishPlugin.assets); | ||
pluginConfig.successComment = defaultTo(pluginConfig.successComment, publishPlugin.successComment); | ||
pluginConfig.failComment = defaultTo(pluginConfig.failComment, publishPlugin.failComment); | ||
pluginConfig.failTitle = defaultTo(pluginConfig.failTitle, publishPlugin.failTitle); | ||
pluginConfig.successComment = defaultTo( | ||
pluginConfig.successComment, | ||
publishPlugin.successComment | ||
); | ||
pluginConfig.failComment = defaultTo( | ||
pluginConfig.failComment, | ||
publishPlugin.failComment | ||
); | ||
pluginConfig.failTitle = defaultTo( | ||
pluginConfig.failTitle, | ||
publishPlugin.failTitle | ||
); | ||
pluginConfig.labels = defaultTo(pluginConfig.labels, publishPlugin.labels); | ||
pluginConfig.assignees = defaultTo(pluginConfig.assignees, publishPlugin.assignees); | ||
pluginConfig.assignees = defaultTo( | ||
pluginConfig.assignees, | ||
publishPlugin.assignees | ||
); | ||
} | ||
|
||
await verifyGitHub(pluginConfig, context); | ||
await verifyGitHub(pluginConfig, context, { Octokit }); | ||
verified = true; | ||
} | ||
|
||
async function publish(pluginConfig, context) { | ||
export async function publish( | ||
pluginConfig, | ||
context, | ||
{ Octokit = SemanticReleaseOctokit } = {} | ||
) { | ||
if (!verified) { | ||
await verifyGitHub(pluginConfig, context); | ||
await verifyGitHub(pluginConfig, context, { Octokit }); | ||
verified = true; | ||
} | ||
|
||
return publishGitHub(pluginConfig, context); | ||
return publishGitHub(pluginConfig, context, { Octokit }); | ||
} | ||
|
||
async function addChannel(pluginConfig, context) { | ||
export async function addChannel( | ||
pluginConfig, | ||
context, | ||
{ Octokit = SemanticReleaseOctokit } = {} | ||
) { | ||
if (!verified) { | ||
await verifyGitHub(pluginConfig, context); | ||
await verifyGitHub(pluginConfig, context, { Octokit }); | ||
verified = true; | ||
} | ||
|
||
return addChannelGitHub(pluginConfig, context); | ||
return addChannelGitHub(pluginConfig, context, { Octokit }); | ||
} | ||
|
||
async function success(pluginConfig, context) { | ||
export async function success( | ||
pluginConfig, | ||
context, | ||
{ Octokit = SemanticReleaseOctokit } = {} | ||
) { | ||
if (!verified) { | ||
await verifyGitHub(pluginConfig, context); | ||
await verifyGitHub(pluginConfig, context, { Octokit }); | ||
verified = true; | ||
} | ||
|
||
await successGitHub(pluginConfig, context); | ||
await successGitHub(pluginConfig, context, { Octokit }); | ||
} | ||
|
||
async function fail(pluginConfig, context) { | ||
export async function fail( | ||
pluginConfig, | ||
context, | ||
{ Octokit = SemanticReleaseOctokit } = {} | ||
) { | ||
if (!verified) { | ||
await verifyGitHub(pluginConfig, context); | ||
await verifyGitHub(pluginConfig, context, { Octokit }); | ||
verified = true; | ||
} | ||
|
||
await failGitHub(pluginConfig, context); | ||
await failGitHub(pluginConfig, context, { Octokit }); | ||
} | ||
|
||
module.exports = {verifyConditions, addChannel, publish, success, fail}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,81 @@ | ||
const debug = require('debug')('semantic-release:github'); | ||
const {RELEASE_NAME} = require('./definitions/constants'); | ||
const parseGithubUrl = require('./parse-github-url'); | ||
const resolveConfig = require('./resolve-config'); | ||
const getClient = require('./get-client'); | ||
const isPrerelease = require('./is-prerelease'); | ||
|
||
module.exports = async (pluginConfig, context) => { | ||
import debugFactory from "debug"; | ||
|
||
import { RELEASE_NAME } from "./definitions/constants.js"; | ||
import parseGithubUrl from "./parse-github-url.js"; | ||
import resolveConfig from "./resolve-config.js"; | ||
import isPrerelease from "./is-prerelease.js"; | ||
import { toOctokitOptions, SemanticReleaseOctokit } from "./octokit.js"; | ||
|
||
const debug = debugFactory("semantic-release:github"); | ||
|
||
export default async function addChannel(pluginConfig, context, { Octokit }) { | ||
const { | ||
options: {repositoryUrl}, | ||
options: { repositoryUrl }, | ||
branch, | ||
nextRelease: {name, gitTag, notes}, | ||
nextRelease: { name, gitTag, notes }, | ||
logger, | ||
} = context; | ||
const {githubToken, githubUrl, githubApiPathPrefix, proxy} = resolveConfig(pluginConfig, context); | ||
const {owner, repo} = parseGithubUrl(repositoryUrl); | ||
const octokit = getClient({githubToken, githubUrl, githubApiPathPrefix, proxy}); | ||
const { githubToken, githubUrl, githubApiPathPrefix, proxy } = resolveConfig( | ||
pluginConfig, | ||
context | ||
); | ||
const { owner, repo } = parseGithubUrl(repositoryUrl); | ||
const octokit = new Octokit( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to build on the injection question above, i'm curious if there would be value in passing an instance through rather than passing the constructor and constructing here and various other places. two potential benefits:
these are just questions for consideration. i'm good with either approach There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had the same thought but didn't want to overburden this pull request. It would be an internal refactoring so shouldn't impact future releases. Main benefit of having a shared We could add a singleton Do you have an idea how we might avoid the side effect for both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
i think this is where my head is too. even if we do think it is a worthwhile change, it feels worthwhile to defer until after merging the rest of this change and releasing to latest. would it be worth capturing an issue for later (optional) consideration? that way we are less likely to lose track of the thoughts you've shared here if we do decide to revisit? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only way I can think of is for semantic-release plugins to have a function that needs to be called, which then in turn returns the lifecycle functions. I guess we could add that functionality to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yes I'll do that. I'll probably send a pull request right away so we can discuss it in isolation, and then do a follow up issue to discuss the new plugin API which would export a single function as default export that works as a factory function for the lifecycle APIs to contain state / avoid side effects |
||
toOctokitOptions({ | ||
githubToken, | ||
githubUrl, | ||
githubApiPathPrefix, | ||
proxy, | ||
}) | ||
); | ||
let releaseId; | ||
|
||
const release = {owner, repo, name, prerelease: isPrerelease(branch), tag_name: gitTag}; | ||
const release = { | ||
owner, | ||
repo, | ||
name, | ||
prerelease: isPrerelease(branch), | ||
tag_name: gitTag, | ||
}; | ||
|
||
debug('release object: %O', release); | ||
debug("release object: %O", release); | ||
|
||
try { | ||
({ | ||
data: {id: releaseId}, | ||
} = await octokit.request('GET /repos/{owner}/{repo}/releases/tags/{tag}', {owner, repo, tag: gitTag})); | ||
data: { id: releaseId }, | ||
} = await octokit.request("GET /repos/{owner}/{repo}/releases/tags/{tag}", { | ||
owner, | ||
repo, | ||
tag: gitTag, | ||
})); | ||
} catch (error) { | ||
if (error.status === 404) { | ||
logger.log('There is no release for tag %s, creating a new one', gitTag); | ||
logger.log("There is no release for tag %s, creating a new one", gitTag); | ||
|
||
const { | ||
data: {html_url: url}, | ||
} = await octokit.request('POST /repos/{owner}/{repo}/releases', {...release, body: notes}); | ||
data: { html_url: url }, | ||
} = await octokit.request("POST /repos/{owner}/{repo}/releases", { | ||
...release, | ||
body: notes, | ||
}); | ||
|
||
logger.log('Published GitHub release: %s', url); | ||
return {url, name: RELEASE_NAME}; | ||
logger.log("Published GitHub release: %s", url); | ||
return { url, name: RELEASE_NAME }; | ||
} | ||
|
||
throw error; | ||
} | ||
|
||
debug('release release_id: %o', releaseId); | ||
debug("release release_id: %o", releaseId); | ||
|
||
const { | ||
data: {html_url: url}, | ||
} = await octokit.request('PATCH /repos/{owner}/{repo}/releases/{release_id}', {...release, release_id: releaseId}); | ||
data: { html_url: url }, | ||
} = await octokit.request( | ||
"PATCH /repos/{owner}/{repo}/releases/{release_id}", | ||
{ ...release, release_id: releaseId } | ||
); | ||
|
||
logger.log('Updated GitHub release: %s', url); | ||
logger.log("Updated GitHub release: %s", url); | ||
|
||
return {url, name: RELEASE_NAME}; | ||
}; | ||
return { url, name: RELEASE_NAME }; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
const ISSUE_ID = '<!-- semantic-release:github -->'; | ||
export const ISSUE_ID = "<!-- semantic-release:github -->"; | ||
|
||
const RELEASE_NAME = 'GitHub release'; | ||
|
||
module.exports = {ISSUE_ID, RELEASE_NAME}; | ||
export const RELEASE_NAME = "GitHub release"; |
Uh oh!
There was an error while loading. Please reload this page.