Skip to content

Commit fe41cef

Browse files
committed
Add "binary.tag" option to specify the tag name separate from the remote path
Fixes #18
1 parent c239d3f commit fe41cef

File tree

3 files changed

+65
-48
lines changed

3 files changed

+65
-48
lines changed

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,18 @@ npm install -g node-pre-gyp-github
1919
```
2020

2121
## Configuration
22-
This module is intended to be used with node-pre-gyp. Therefore, be sure to configure and install node-pre-gyp first. After having done that, within **```package.json```** update the ```binary``` properties ```host``` and ```remote_path``` so it matches the following format:
22+
This module is intended to be used with node-pre-gyp. Therefore, be sure to configure and install node-pre-gyp first. After having done that, within **```package.json```** update the `binary` section properties so they match the following format:
2323

2424
```
25-
"host": "https://github.com/[owner]/[repo]/releases/download/",
26-
"remote_path": "{version}"
25+
"host": "https://github.com",
26+
"remote_path": "/[owner]/[repo]/releases/download/",
27+
"tag": "{version}"
2728
```
2829

29-
Be sure to replace ```[owner]```, ```[repo]```, with actual values,
30-
but DO NOT replace ```{version}``` with actual version.
30+
Be sure to replace `[owner]`, `[repo]`, with actual values,
31+
but DO NOT replace `{version}` with actual version.
3132

32-
***WARNING: Variable substitutions are not supported on the ```host``` property and on the ```remote_path``` only ```{version}``` placeholder is supported. The value of ```remote_path``` after substitution will become a release tag name. Do not use [forbidden git tag characters](https://git-scm.com/docs/git-check-ref-format) for ```version``` and ```remote_path``` properties.***
33+
***WARNING: Variable substitutions are not supported on the `host` or `remote_path` property. Only `{version}` placeholder is supported for the `tag` property. The value of `tag` after substitution will become a release tag name. Do not use [forbidden git tag characters](https://git-scm.com/docs/git-check-ref-format) in your `package.version` or `package.binary.tag` properties.***
3334

3435
Within GitHub, create a new authorization:
3536

index.js

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ NodePreGypGithub.prototype.release = {};
3131
NodePreGypGithub.prototype.stage_dir = path.join(cwd,"build","stage");
3232

3333
NodePreGypGithub.prototype.init = function() {
34-
var ownerRepo, hostPrefix;
35-
34+
var ownerRepo, hostPrefix, pathPrefix;
35+
3636
this.package_json = JSON.parse(fs.readFileSync(path.join(cwd,'package.json')));
37-
37+
3838
if(!this.package_json.repository || !this.package_json.repository.url){
3939
throw new Error('Missing repository.url in package.json');
4040
}
@@ -47,17 +47,26 @@ NodePreGypGithub.prototype.init = function() {
4747
}
4848
else throw new Error('A correctly formatted GitHub repository.url was not found within package.json');
4949
}
50-
51-
hostPrefix = 'https://github.com/' + this.owner + '/' + this.repo + '/releases/download/';
50+
51+
hostPrefix = 'https://github.com'
52+
pathPrefix = '/' + this.owner + '/' + this.repo + '/releases/download/';
5253
if(!this.package_json.binary || 'object' !== typeof this.package_json.binary || 'string' !== typeof this.package_json.binary.host){
5354
throw new Error('Missing binary.host in package.json');
5455
}
5556
else if (this.package_json.binary.host.substr(0, hostPrefix.length) !== hostPrefix){
5657
throw new Error('binary.host in package.json should begin with: "' + hostPrefix + '"');
5758
}
58-
59+
else if('string' == typeof this.package_json.binary.tag ) {
60+
if (this.package_json.binary.remote_path.substr(0, pathPrefix.length) !== pathPrefix){
61+
throw new Error('binary.remote_path in package.json should begin with: "' + pathPrefix + '" when using binary.tag');
62+
}
63+
}
64+
else if(! this.package_json.binary.host.match(pathPrefix)) {
65+
throw new Error('binary.host in package.json should contain: "' + pathPrefix + '"');
66+
}
67+
5968
this.github.headers = {"user-agent": (this.package_json.name) ? this.package_json.name : "node-pre-gyp-github"}; // GitHub is happy with a unique user agent
60-
69+
6170
};
6271

6372
NodePreGypGithub.prototype.authenticate_settings = function(){
@@ -80,13 +89,13 @@ NodePreGypGithub.prototype.createRelease = function(args, callback) {
8089
'draft': true,
8190
'prerelease': false
8291
};
83-
92+
8493
Object.keys(args).forEach(function(key) {
8594
if(args.hasOwnProperty(key) && options.hasOwnProperty(key)) {
8695
options[key] = args[key];
8796
}
8897
});
89-
98+
9099
this.github.authenticate(this.authenticate_settings());
91100
this.github.releases.createRelease(options, callback);
92101
};
@@ -110,9 +119,9 @@ NodePreGypGithub.prototype.uploadAssets = function(){
110119
consoleLog("Stage directory path: " + path.join(this.stage_dir));
111120
fs.readdir(path.join(this.stage_dir), function(err, files){
112121
if(err) throw err;
113-
122+
114123
if(!files.length) throw new Error('No files found within the stage directory: ' + this.stage_dir);
115-
124+
116125
files.forEach(function(file){
117126
asset = this.release.assets.filter(function(element, index, array){
118127
return element.name === file;
@@ -141,18 +150,25 @@ NodePreGypGithub.prototype.publish = function(options) {
141150
'repo': this.repo
142151
}, function(err, data){
143152
var release;
144-
153+
145154
if(err) throw err;
146-
155+
156+
// prefer `binary.tag` if present, before remote_path - see https://github.com/bchr02/node-pre-gyp-github/issues/18
157+
if (this.package_json.binary.tag) {
158+
options.tag_name = this.package_json.binary.tag.replace(/\{version\}/g, this.package_json.version);
159+
// stage_dir is still based on remote_path, not tag:
160+
this.stage_dir = path.join(this.stage_dir, (this.package_json.binary.remote_path || ''));
161+
}
147162
// when remote_path is set expect files to be in stage_dir / remote_path after substitution
148-
if (this.package_json.binary.remote_path) {
163+
// {version} substitution only takes place in `remote_path` if `package_json.binary.tag` is not present:
164+
else if (this.package_json.binary.remote_path) {
149165
options.tag_name = this.package_json.binary.remote_path.replace(/\{version\}/g, this.package_json.version);
150166
this.stage_dir = path.join(this.stage_dir, options.tag_name);
151167
} else {
152168
// This is here for backwards compatibility for before binary.remote_path support was added in version 1.2.0.
153169
options.tag_name = this.package_json.version;
154170
}
155-
171+
156172
release = (function(){ // create a new array containing only those who have a matching version.
157173
if(data) {
158174
data = data.filter(function(element, index, array){
@@ -162,13 +178,13 @@ NodePreGypGithub.prototype.publish = function(options) {
162178
}
163179
else return [];
164180
}.bind(this))();
165-
181+
166182
this.release = release[0];
167-
183+
168184
if(!release.length) {
169185
this.createRelease(options, function(err, release) {
170186
if(err) throw err;
171-
187+
172188
this.release = release;
173189
if (release.draft) {
174190
consoleLog('Release ' + release.tag_name + " not found, so a draft release was created. YOU MUST MANUALLY PUBLISH THIS DRAFT WITHIN GITHUB FOR IT TO BE ACCESSIBLE.");
@@ -185,4 +201,4 @@ NodePreGypGithub.prototype.publish = function(options) {
185201
}.bind(this));
186202
};
187203

188-
module.exports = NodePreGypGithub;
204+
module.exports = NodePreGypGithub;

test/test.js

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ var reset_index = function(index_string_ref) {
1212
var reset_mocks = function() {
1313
process.env.NODE_PRE_GYP_GITHUB_TOKEN = "secret";
1414
fs = reset_index('fs');
15-
fs.readFileSync = function(){return '{"name":"test","version":"0.0.1","repository": {"url":"git+https://github.com/test/test.git"},"binary":{"host":"https://github.com/test/test/releases/download/","remote_path":"{version}"}}';};
15+
fs.readFileSync = function(){return '{"name":"test","version":"0.0.1","repository": {"url":"git+https://github.com/test/test.git"},"binary":{"host":"https://github.com","remote_path":"/test/test/releases/download/","tag":"{version}"}}';};
1616
index.stage_dir = stage_dir;
1717
index.github.authenticate = function(){};
1818
index.github.releases.listReleases = function(options, cb){
@@ -28,9 +28,9 @@ if(!process.env.COVERALLS_SERVICE_NAME) console.log('To post to coveralls.io, be
2828
if(!process.env.COVERALLS_REPO_TOKEN) console.log('To post to coveralls.io, be sure to set COVERALLS_REPO_TOKEN environment variable');
2929

3030
describe("Publishes packages to GitHub Releases", function() {
31-
31+
3232
describe("Publishes without an error under all options", function() {
33-
33+
3434
it("should publish a non-draft release without an error", function() {
3535
var options = {'draft': false, 'verbose': false};
3636
reset_mocks();
@@ -42,7 +42,7 @@ describe("Publishes packages to GitHub Releases", function() {
4242
};
4343
expect(function(){ index.publish(options); }).to.not.throw();
4444
});
45-
45+
4646
it("should publish a draft release without an error", function() {
4747
var options = {'draft': true, 'verbose': false};
4848
reset_mocks();
@@ -51,46 +51,46 @@ describe("Publishes packages to GitHub Releases", function() {
5151
};
5252
expect(function(){ index.publish(options); }).to.not.throw();
5353
});
54-
54+
5555
});
56-
56+
5757
describe("Throws an error when node-pre-gyp-github is not configured properly", function() {
58-
58+
5959
it("should throw an error when missing repository.url in package.json", function() {
6060
var options = {'draft': true, 'verbose': false};
6161
reset_mocks();
6262
fs.readFileSync = function(){return '{}';};
6363
expect(function(){ index.publish(options); }).to.throw("Missing repository.url in package.json");
6464
});
65-
65+
6666
it("should throw an error when a correctly formatted GitHub repository.url is not found in package.json", function() {
6767
var options = {'draft': true, 'verbose': false};
6868
reset_mocks();
6969
fs.readFileSync = function(){return '{"repository": {"url":"bad_format_url"}}';};
7070
expect(function(){ index.publish(options); }).to.throw("A correctly formatted GitHub repository.url was not found within package.json");
7171
});
72-
72+
7373
it("should throw an error when missing binary.host in package.json", function() {
7474
var options = {'draft': true, 'verbose': false};
7575
reset_mocks();
7676
fs.readFileSync = function(){return '{"repository": {"url":"git+https://github.com/test/test.git"}}';};
7777
expect(function(){ index.publish(options); }).to.throw("Missing binary.host in package.json");
7878
});
79-
79+
8080
it("should throw an error when binary.host does not begin with the correct url", function() {
8181
var options = {'draft': true, 'verbose': false};
8282
reset_mocks();
8383
fs.readFileSync = function(){return '{"repository": {"url":"git+https://github.com/test/test.git"},"binary":{"host":"bad_format_binary"}}';};
8484
expect(function(){ index.publish(options); }).to.throw(/^binary.host in package.json should begin with:/i);
8585
});
86-
86+
8787
it("should throw an error when the NODE_PRE_GYP_GITHUB_TOKEN environment variable is not found", function() {
8888
var options = {'draft': true, 'verbose': false};
8989
reset_mocks();
9090
process.env.NODE_PRE_GYP_GITHUB_TOKEN = "";
9191
expect(function(){ index.publish(options); }).to.throw("NODE_PRE_GYP_GITHUB_TOKEN environment variable not found");
9292
});
93-
93+
9494
it("should throw an error when github.releases.listReleases returns an error", function() {
9595
var options = {'draft': true, 'verbose': false};
9696
reset_mocks();
@@ -99,7 +99,7 @@ describe("Publishes packages to GitHub Releases", function() {
9999
};
100100
expect(function(){ index.publish(options); }).to.throw('listReleases error');
101101
});
102-
102+
103103
it("should throw an error when github.releases.createRelease returns an error", function() {
104104
var options = {'draft': true, 'verbose': false};
105105
reset_mocks();
@@ -111,7 +111,7 @@ describe("Publishes packages to GitHub Releases", function() {
111111
};
112112
expect(function(){ index.publish(options); }).to.throw('createRelease error');
113113
});
114-
114+
115115
it("should throw an error when the stage directory structure is missing", function() {
116116
var options = {'draft': true, 'verbose': false};
117117
reset_mocks();
@@ -120,7 +120,7 @@ describe("Publishes packages to GitHub Releases", function() {
120120
};
121121
expect(function(){ index.publish(options); }).to.throw('readdir Error');
122122
});
123-
123+
124124
it("should throw an error when there are no files found within the stage directory", function() {
125125
var options = {'draft': true, 'verbose': false};
126126
reset_mocks();
@@ -129,7 +129,7 @@ describe("Publishes packages to GitHub Releases", function() {
129129
};
130130
expect(function(){ index.publish(options); }).to.throw(/^No files found within the stage directory:/i);
131131
});
132-
132+
133133
it("should throw an error when a staged file already exists in the current release", function() {
134134
var options = {'draft': true, 'verbose': false};
135135
reset_mocks();
@@ -141,23 +141,23 @@ describe("Publishes packages to GitHub Releases", function() {
141141
};
142142
expect(function(){ index.publish(options); }).to.throw(/^Staged file .* found but it already exists in release .*. If you would like to replace it, you must first manually delete it within GitHub./i);
143143
});
144-
144+
145145
it("should throw an error when github.releases.uploadAsset returns an error", function() {
146146
var options = {'draft': true, 'verbose': false};
147147
reset_mocks();
148148
fs.readdir = function(filename, cb) {
149149
cb(null,["filename"]);
150150
};
151151
index.github.releases.uploadAsset = function(cfg,cb){
152-
cb(new Error('uploadAsset error'));
152+
cb(new Error('uploadAsset error'));
153153
};
154154
expect(function(){ index.publish(options); }).to.throw("uploadAsset error");
155155
});
156-
156+
157157
});
158-
158+
159159
describe("Verify backwords compatible with any breaking changes made within the same MINOR version.", function() {
160-
160+
161161
it("should publish even when package.json's binary.remote_path property is not provided and instead the version is hard coded within binary.host", function() {
162162
var options = {'draft': false, 'verbose': false};
163163
reset_mocks();
@@ -170,6 +170,6 @@ describe("Publishes packages to GitHub Releases", function() {
170170
};
171171
expect(function(){ index.publish(options); }).to.not.throw();
172172
});
173-
173+
174174
});
175-
});
175+
});

0 commit comments

Comments
 (0)