Skip to content

Commit

Permalink
feat: editRelease and deleteEmptyTag options (#32)
Browse files Browse the repository at this point in the history
* fix: search body inside array for `reuseRelease`

Allow to reuse release in any position instead only the latest one
Resolves #31

* chore(package-lock): inhibits dependency problems

* feat: allow editRelease option #30

* feat: delete empty tag

Compare if it's going from release/prerelease to tag to delete empty unused tag #30

* fix: callback deleteEmptyTag when no editRelease

* docs: include editRelease and deleteEmptyTag

* fix(cli): include editRelease and deleteEmptyTag

* fix: extra semicolon and standard pattern
  • Loading branch information
marceloavf committed Feb 16, 2018
1 parent 99ed244 commit 4ffad99
Show file tree
Hide file tree
Showing 5 changed files with 3,210 additions and 4 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ Options:
--skipDuplicatedAssets Pass this flag if you don't want the plugin to replace assets with the same
name. False by default.
--editRelease Pass this flag if you want to edit release name, notes, type and target_commitish.
It will need reuseRelease or/and reuseDraftOnly true to edit the release.
--deleteEmptyTag Pass this flag if you want to delete an empty tag after editing it. Usually happens
when you edit from `prerelease or release` to `draft`.
--assets [files] Comma-separated list of filenames.
Ex: --assets foo.txt,bar.zip
Expand Down Expand Up @@ -97,6 +103,8 @@ publishRelease({
reuseDraftOnly: true,
skipAssetsCheck: false,
skipDuplicatedAssets: false,
editRelease: false,
deleteEmptyTag: false,
assets: ['/absolute/path/to/file'],
apiUrl: 'https://myGHEserver/api/v3',
target_commitish: 'master'
Expand All @@ -115,6 +123,9 @@ publishRelease({
* `uploaded-asset` - `{name}` - Emits after an asset file is successfully uploaded. Emits the `name` of the file.
* `duplicated-asset` - `{name}` - Emits after found a duplicated asset file. Emits the `name` of the file.
* `duplicated-asset-deleted` - `{name}` - Emits after delete a duplicated asset file. Emits the `name` of the file.
* `edit-release` - `{object}` Emits when will edit a release. Emits the actual release `object`.
* `edited-release` - `{object}` Emits after edit a release. Emits the modified `object`.
* `deleted-tag-release` - `{name}` Emits after editing release from prerelease or release to draft, preventing from leaving an empty tag for a edited release. Emits the deleted tag `name` string.

### Usage with Gulp

Expand Down
6 changes: 6 additions & 0 deletions bin/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ Options:
--skipDuplicatedAssets Pass this flag if you don't want the plugin to replace assets with the same
name. False by default.

--editRelease Pass this flag if you want to edit release name, notes, type and target_commitish.
It will need reuseRelease or/and reuseDraftOnly true to edit the release.

--deleteEmptyTag Pass this flag if you want to delete an empty tag after editing it. Usually happens
when you edit from `prerelease or release` to `draft`.

--assets [files] Comma-separated list of filenames.
Ex: --assets foo.txt,bar.zip

Expand Down
2 changes: 2 additions & 0 deletions bin/publish-release
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ var opts = _.extend({
reuseRelease: false,
skipAssetsCheck: false,
skipDuplicatedAssets: false,
editRelease: false,
deleteEmptyTag: false,
assets: []
}, argv, pkg.publishRelease)

Expand Down
110 changes: 106 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ PublishRelease.prototype.publish = function publish () {
}

if (opts.reuseRelease) {
/**
* https://github.com/remixz/publish-release/issues/31
* We don't use "Get a release by tag name" because "tag name" means existing git tag,
* but we can draft release and don't create git tag
*/
request({
uri: ghReleaseUri,
method: 'GET',
Expand All @@ -107,13 +112,24 @@ PublishRelease.prototype.publish = function publish () {
}, function (err, res, body) {
if (err) return callback(err) // will be handled by asyncAutoCallback

let bodyReturn = null

async.eachSeries(body, function (el, callback) {
if (el.tag_name === opts.tag) {
bodyReturn = el
return
}
callback()
})

var statusOk = res.statusCode >= 200 && res.statusCode < 300
var bodyOk = body[0] && body[0].tag_name === opts.tag
var canReuse = !opts.reuseDraftOnly || (body[0] && body[0].draft)
var bodyOk = bodyReturn && bodyReturn.tag_name === opts.tag
var canReuse = !opts.reuseDraftOnly || (bodyReturn && bodyReturn.draft)

if (statusOk && bodyOk && canReuse) {
self.emit('reuse-release')
callback(null, body[0])
bodyReturn.allowReuse = true // allow to editRelease
callback(null, bodyReturn)
} else {
requestCreateRelease()
}
Expand All @@ -123,7 +139,93 @@ PublishRelease.prototype.publish = function publish () {
}
},

uploadAssets: ['createRelease', function uploadAssets (callback, obj) {
editRelease: ['createRelease', function editRelease (callback, obj) {
if (obj.createRelease.errors || !obj.createRelease.url) return callback()

if (opts.editRelease && obj.createRelease.allowReuse) {
self.emit('edit-release', obj.createRelease)
const editUri = obj.createRelease.url

const reqDetails = {
uri: editUri,
method: 'PATCH',
json: true,
body: {
tag_name: opts.tag,
target_commitish: opts.target_commitish,
name: opts.name,
body: opts.notes,
draft: !!opts.draft,
prerelease: !!opts.prerelease
},
headers: {
'Authorization': 'token ' + opts.token,
'User-Agent': 'publish-release ' + pkg.version + ' (https://github.com/remixz/publish-release)'
}
}
request(reqDetails, function (err, res, body) {
if (err) {
// handle a real error, eg network fail
// will be handled by asyncAutoCallback
return callback(err)
}
var errorStatus = res.statusCode >= 400 && res.statusCode < 600
if (errorStatus) {
// handle an http error status
// will be handled by asyncAutoCallback
var e = new Error('Error status: ' + res.statusCode + ' response body:' + JSON.stringify(body) + '\n request details:' + JSON.stringify(reqDetails, null, 2))
return callback(e)
}

self.emit('edited-release', body)
callback(null, body)
})
} else {
callback()
}
}],

deleteEmptyTag: ['createRelease', 'editRelease', function deleteEmptyTag (callback, obj) {
if (!obj.editRelease) return callback()
/**
* Compare if it's going from release/prerelease to tag
* to delete empty unused tag, checking if it's now draft and was not draft
*/
if (opts.deleteEmptyTag && obj.editRelease.draft && !obj.createRelease.draft) {
var deleteTagUri = util.format((opts.apiUrl || DEFAULT_API_ROOT) + '/repos/%s/%s/git/refs/tags/%s', opts.owner, opts.repo, obj.createRelease.tag_name)

const reqDetails = {
uri: deleteTagUri,
method: 'DELETE',
json: true,
headers: {
'Authorization': 'token ' + opts.token,
'User-Agent': 'publish-release ' + pkg.version + ' (https://github.com/remixz/publish-release)'
}
}
request(reqDetails, function (err, res, body) {
if (err) {
// handle a real error, eg network fail
// will be handled by asyncAutoCallback
return callback(err)
}
var errorStatus = res.statusCode >= 400 && res.statusCode < 600
if (errorStatus) {
// handle an http error status
// will be handled by asyncAutoCallback
var e = new Error('Error status: ' + res.statusCode + ' response body:' + JSON.stringify(body) + '\n request details:' + JSON.stringify(reqDetails, null, 2))
return callback(e)
}

self.emit('deleted-tag-release', obj.createRelease.tag_name)
callback(null, body)
})
} else {
callback()
}
}],

uploadAssets: ['createRelease', 'editRelease', 'deleteEmptyTag', function uploadAssets (callback, obj) {
if (!opts.assets || opts.assets.length === 0) return callback()
if (obj.createRelease.errors || !obj.createRelease.upload_url) return callback(obj.createRelease)

Expand Down

0 comments on commit 4ffad99

Please sign in to comment.