UNPKG

3.26 kBJavaScriptView Raw
1const meta = require('github-action-meta')
2const actionStatus = require('action-status')
3const getContext = require('./context')
4const runDry = require('./run-dry')
5
6module.exports = function publish(options = {}, npmArgs = []) {
7 if (!process.env.NPM_AUTH_TOKEN) {
8 throw new Error(`You must set the NPM_AUTH_TOKEN environment variable`)
9 }
10
11 const run = options.dryRun ? runDry : require('execa')
12 const execOpts = {stdio: 'inherit'}
13
14 return getContext(options).then(context => {
15 const {name, version, tag, packageJson} = context
16 const {sha} = meta.git
17
18 // this is true if we think we're publishing the version that's in git
19 const isLatest = packageJson.version === version
20
21 return (context.status ? publishStatus(context, context.status) : Promise.resolve())
22 .then(() => {
23 if (isLatest) {
24 console.warn(`[publish] skipping "npm version" because "${version}" matches package.json`)
25 // this is a fairly reliable way to determine whether the package@version is published
26 return run('npm', ['view', `${name}@${version}`, 'version'], {stderr: 'inherit'})
27 .then(({stdout}) => stdout === version)
28 .then(published => {
29 if (published) {
30 console.warn(`[publish] ${version} is already published; exiting with neutral status`)
31 // see: <https://developer.github.com/actions/creating-github-actions/accessing-the-runtime-environment/#exit-codes-and-statuses>
32 process.exit(78)
33 }
34 })
35 } else {
36 return publishStatus(context, {
37 state: 'pending',
38 description: `npm version ${version}`
39 }).then(() => run('npm', [...npmArgs, 'version', version], execOpts))
40 }
41 })
42 .then(() =>
43 publishStatus(context, {
44 state: 'pending',
45 description: `npm publish --tag ${tag}`
46 })
47 )
48 .then(() => run('npm', [...npmArgs, 'publish', '--tag', tag, '--access', 'public'], execOpts))
49 .then(() =>
50 publishStatus(context, {
51 state: 'success',
52 description: version,
53 url: `https://unpkg.com/${name}@${version}/`
54 })
55 )
56 .then(() => {
57 if (isLatest) {
58 const context = 'git tag'
59 const tag = `v${version}`
60 return publishStatus(context, {
61 context,
62 state: 'pending',
63 description: `Tagging the release as "${tag}"...`
64 })
65 .then(() => run('git', ['tag', tag], execOpts))
66 .then(() => run('git', ['push', '--tags', 'origin'], execOpts))
67 .then(() =>
68 publishStatus(context, {
69 context,
70 state: 'success',
71 description: `Tagged ${sha.substr(0, 7)} as "${tag}"`
72 })
73 )
74 }
75 })
76 .then(() => context)
77 })
78}
79
80function publishStatus(context, options = {}) {
81 return actionStatus(
82 Object.assign(
83 {
84 context: `publish ${context.name}`,
85 // note: these need to be empty so that action-status
86 // doesn't throw an error w/o "required" env vars
87 description: '',
88 url: ''
89 },
90 options
91 )
92 )
93}