Skip to content

Commit 6362cef

Browse files
author
Bryan Smith
committed
Fix App Center Distribution bug where feature branches were being truncated incorrectly.
1 parent 1cb2dc2 commit 6362cef

File tree

7 files changed

+297
-5
lines changed

7 files changed

+297
-5
lines changed

Tasks/AppCenterDistributeV1/Tests/L0.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe('AppCenterDistribute L0 Suite', function () {
2020

2121
after(() => {
2222
delete process.env['BUILD_BUILDID'];
23-
delete process.env['BUILD_SOURCEBRANCHNAME'];
23+
delete process.env['BUILD_SOURCEBRANCH'];
2424
delete process.env['BUILD_SOURCEVERSION'];
2525
delete process.env['LASTCOMMITMESSAGE'];
2626
});
@@ -166,6 +166,26 @@ describe('AppCenterDistribute L0 Suite', function () {
166166
assert(tr.succeeded, 'task should have succeeded');
167167
});
168168

169+
it('Positive path: publish commit info for feature branch', function () {
170+
this.timeout(4000);
171+
172+
let tp = path.join(__dirname, 'L0PublishCommitInfo_3.js');
173+
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
174+
175+
tr.run();
176+
assert(tr.succeeded, 'task should have succeeded');
177+
});
178+
179+
it('Positive path: publish commit info for tfvc branch', function () {
180+
this.timeout(4000);
181+
182+
let tp = path.join(__dirname, 'L0PublishCommitInfo_4.js');
183+
let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);
184+
185+
tr.run();
186+
assert(tr.succeeded, 'task should have succeeded');
187+
});
188+
169189
it('Positive path: publish mandatory update)', function () {
170190
this.timeout(4000);
171191

Tasks/AppCenterDistributeV1/Tests/L0PublishCommitInfo_1.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ tmr.setInput('symbolsType', 'AndroidJava');
2020
tmr.setInput('mappingTxtPath', '/test/path/to/mappings.txt');
2121

2222
process.env['BUILD_BUILDID'] = '2';
23-
process.env['BUILD_SOURCEBRANCHNAME'] = 'master';
23+
process.env['BUILD_SOURCEBRANCH'] = 'refs/heads/master';
2424
process.env['BUILD_SOURCEVERSION'] = 'commitsha';
2525
process.env['LASTCOMMITMESSAGE'] = 'commit message';
2626

Tasks/AppCenterDistributeV1/Tests/L0PublishCommitInfo_2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ tmr.setInput('symbolsType', 'AndroidJava');
2020
tmr.setInput('mappingTxtPath', '/test/path/to/mappings.txt');
2121

2222
process.env['BUILD_BUILDID'] = '2';
23-
process.env['BUILD_SOURCEBRANCHNAME'] = 'master';
23+
process.env['BUILD_SOURCEBRANCH'] = 'refs/heads/master';
2424
process.env['BUILD_SOURCEVERSION'] = 'commitsha';
2525

2626
//prepare upload
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
2+
import ma = require('vsts-task-lib/mock-answer');
3+
import tmrm = require('vsts-task-lib/mock-run');
4+
import path = require('path');
5+
import fs = require('fs');
6+
var Readable = require('stream').Readable
7+
var Stats = require('fs').Stats
8+
9+
var nock = require('nock');
10+
11+
let taskPath = path.join(__dirname, '..', 'appcenterdistribute.js');
12+
let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath);
13+
14+
tmr.setInput('serverEndpoint', 'MyTestEndpoint');
15+
tmr.setInput('appSlug', 'testuser/testapp');
16+
tmr.setInput('app', '/test/path/to/my.ipa');
17+
tmr.setInput('releaseNotesSelection', 'releaseNotesInput');
18+
tmr.setInput('releaseNotesInput', 'my release notes');
19+
tmr.setInput('symbolsType', 'AndroidJava');
20+
tmr.setInput('mappingTxtPath', '/test/path/to/mappings.txt');
21+
22+
process.env['BUILD_BUILDID'] = '2';
23+
process.env['BUILD_SOURCEBRANCH'] = 'refs/heads/feature/foobar';
24+
process.env['BUILD_SOURCEVERSION'] = 'commitsha';
25+
26+
//prepare upload
27+
nock('https://example.test')
28+
.post('/v0.1/apps/testuser/testapp/release_uploads')
29+
.reply(201, {
30+
upload_id: 1,
31+
upload_url: 'https://example.upload.test/release_upload'
32+
});
33+
34+
//upload
35+
nock('https://example.upload.test')
36+
.post('/release_upload')
37+
.reply(201, {
38+
status: 'success'
39+
});
40+
41+
//finishing upload, commit the package
42+
nock('https://example.test')
43+
.patch("/v0.1/apps/testuser/testapp/release_uploads/1", {
44+
status: 'committed'
45+
})
46+
.reply(200, {
47+
release_url: 'my_release_location'
48+
});
49+
50+
//make it available
51+
//JSON.stringify to verify exact match of request body: https://github.com/node-nock/nock/issues/571
52+
nock('https://example.test')
53+
.patch("/my_release_location", JSON.stringify({
54+
status: "available",
55+
release_notes: "my release notes",
56+
mandatory_update: false,
57+
destinations: [{ id: "00000000-0000-0000-0000-000000000000" }],
58+
build: {
59+
id: '2',
60+
branch: 'feature/foobar',
61+
commit_hash: 'commitsha'
62+
}
63+
}))
64+
.reply(200);
65+
66+
//begin symbol upload
67+
nock('https://example.test')
68+
.post('/v0.1/apps/testuser/testapp/symbol_uploads', {
69+
symbol_type: "AndroidJava"
70+
})
71+
.reply(201, {
72+
symbol_upload_id: 100,
73+
upload_url: 'https://example.upload.test/symbol_upload',
74+
expiration_date: 1234567
75+
});
76+
77+
//upload symbols
78+
nock('https://example.upload.test')
79+
.put('/symbol_upload')
80+
.reply(201, {
81+
status: 'success'
82+
});
83+
84+
//finishing symbol upload, commit the symbol
85+
nock('https://example.test')
86+
.patch("/v0.1/apps/testuser/testapp/symbol_uploads/100", {
87+
status: 'committed'
88+
})
89+
.reply(200);
90+
91+
// provide answers for task mock
92+
let a: ma.TaskLibAnswers = <ma.TaskLibAnswers>{
93+
"checkPath" : {
94+
"/test/path/to/my.ipa": true,
95+
"/test/path/to/mappings.txt": true
96+
},
97+
"findMatch" : {
98+
"/test/path/to/mappings.txt": [
99+
"/test/path/to/mappings.txt"
100+
],
101+
"/test/path/to/my.ipa": [
102+
"/test/path/to/my.ipa"
103+
]
104+
}
105+
};
106+
tmr.setAnswers(a);
107+
108+
fs.createReadStream = (s: string) => {
109+
let stream = new Readable;
110+
stream.push(s);
111+
stream.push(null);
112+
113+
return stream;
114+
};
115+
116+
fs.statSync = (s: string) => {
117+
let stat = new Stats;
118+
119+
stat.isFile = () => {
120+
return !s.toLowerCase().endsWith(".dsym");
121+
}
122+
stat.isDirectory = () => {
123+
return s.toLowerCase().endsWith(".dsym");
124+
}
125+
stat.size = 100;
126+
127+
return stat;
128+
}
129+
tmr.registerMock('fs', fs);
130+
131+
tmr.run();
132+
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
2+
import ma = require('vsts-task-lib/mock-answer');
3+
import tmrm = require('vsts-task-lib/mock-run');
4+
import path = require('path');
5+
import fs = require('fs');
6+
var Readable = require('stream').Readable
7+
var Stats = require('fs').Stats
8+
9+
var nock = require('nock');
10+
11+
let taskPath = path.join(__dirname, '..', 'appcenterdistribute.js');
12+
let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath);
13+
14+
tmr.setInput('serverEndpoint', 'MyTestEndpoint');
15+
tmr.setInput('appSlug', 'testuser/testapp');
16+
tmr.setInput('app', '/test/path/to/my.ipa');
17+
tmr.setInput('releaseNotesSelection', 'releaseNotesInput');
18+
tmr.setInput('releaseNotesInput', 'my release notes');
19+
tmr.setInput('symbolsType', 'AndroidJava');
20+
tmr.setInput('mappingTxtPath', '/test/path/to/mappings.txt');
21+
22+
process.env['BUILD_BUILDID'] = '2';
23+
process.env['BUILD_SOURCEBRANCH'] = '$/teamproject/main';
24+
process.env['BUILD_SOURCEVERSION'] = 'commitsha';
25+
26+
//prepare upload
27+
nock('https://example.test')
28+
.post('/v0.1/apps/testuser/testapp/release_uploads')
29+
.reply(201, {
30+
upload_id: 1,
31+
upload_url: 'https://example.upload.test/release_upload'
32+
});
33+
34+
//upload
35+
nock('https://example.upload.test')
36+
.post('/release_upload')
37+
.reply(201, {
38+
status: 'success'
39+
});
40+
41+
//finishing upload, commit the package
42+
nock('https://example.test')
43+
.patch("/v0.1/apps/testuser/testapp/release_uploads/1", {
44+
status: 'committed'
45+
})
46+
.reply(200, {
47+
release_url: 'my_release_location'
48+
});
49+
50+
//make it available
51+
//JSON.stringify to verify exact match of request body: https://github.com/node-nock/nock/issues/571
52+
nock('https://example.test')
53+
.patch("/my_release_location", JSON.stringify({
54+
status: "available",
55+
release_notes: "my release notes",
56+
mandatory_update: false,
57+
destinations: [{ id: "00000000-0000-0000-0000-000000000000" }],
58+
build: {
59+
id: '2',
60+
branch: '$/teamproject/main',
61+
commit_hash: 'commitsha'
62+
}
63+
}))
64+
.reply(200);
65+
66+
//begin symbol upload
67+
nock('https://example.test')
68+
.post('/v0.1/apps/testuser/testapp/symbol_uploads', {
69+
symbol_type: "AndroidJava"
70+
})
71+
.reply(201, {
72+
symbol_upload_id: 100,
73+
upload_url: 'https://example.upload.test/symbol_upload',
74+
expiration_date: 1234567
75+
});
76+
77+
//upload symbols
78+
nock('https://example.upload.test')
79+
.put('/symbol_upload')
80+
.reply(201, {
81+
status: 'success'
82+
});
83+
84+
//finishing symbol upload, commit the symbol
85+
nock('https://example.test')
86+
.patch("/v0.1/apps/testuser/testapp/symbol_uploads/100", {
87+
status: 'committed'
88+
})
89+
.reply(200);
90+
91+
// provide answers for task mock
92+
let a: ma.TaskLibAnswers = <ma.TaskLibAnswers>{
93+
"checkPath" : {
94+
"/test/path/to/my.ipa": true,
95+
"/test/path/to/mappings.txt": true
96+
},
97+
"findMatch" : {
98+
"/test/path/to/mappings.txt": [
99+
"/test/path/to/mappings.txt"
100+
],
101+
"/test/path/to/my.ipa": [
102+
"/test/path/to/my.ipa"
103+
]
104+
}
105+
};
106+
tmr.setAnswers(a);
107+
108+
fs.createReadStream = (s: string) => {
109+
let stream = new Readable;
110+
stream.push(s);
111+
stream.push(null);
112+
113+
return stream;
114+
};
115+
116+
fs.statSync = (s: string) => {
117+
let stat = new Stats;
118+
119+
stat.isFile = () => {
120+
return !s.toLowerCase().endsWith(".dsym");
121+
}
122+
stat.isDirectory = () => {
123+
return s.toLowerCase().endsWith(".dsym");
124+
}
125+
stat.size = 100;
126+
127+
return stat;
128+
}
129+
tmr.registerMock('fs', fs);
130+
131+
tmr.run();
132+

Tasks/AppCenterDistributeV1/Tests/L0PublishMandatoryUpdate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ tmr.setInput('symbolsType', 'AndroidJava');
2121
tmr.setInput('mappingTxtPath', '/test/path/to/mappings.txt');
2222

2323
process.env['BUILD_BUILDID'] = '2';
24-
process.env['BUILD_SOURCEBRANCHNAME'] = 'master';
24+
process.env['BUILD_SOURCEBRANCH'] = 'master';
2525
process.env['BUILD_SOURCEVERSION'] = 'commitsha';
2626

2727
//prepare upload

Tasks/AppCenterDistributeV1/appcenterdistribute.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ function publishRelease(apiServer: string, releaseUrl: string, isMandatory: bool
168168
]
169169
};
170170

171-
const branchName = process.env['BUILD_SOURCEBRANCHNAME'];
171+
let branchName = process.env['BUILD_SOURCEBRANCH'];
172+
branchName = getBranchName(branchName);
172173
const sourceVersion = process.env['BUILD_SOURCEVERSION'];
173174
const buildId = process.env['BUILD_BUILDID'];
174175

@@ -204,6 +205,13 @@ function publishRelease(apiServer: string, releaseUrl: string, isMandatory: bool
204205
return defer.promise;
205206
}
206207

208+
function getBranchName(ref: string): string {
209+
const gitRefsHeadsPrefix = 'refs/heads/';
210+
if (ref) {
211+
return ref.indexOf(gitRefsHeadsPrefix) === 0 ? ref.substr(gitRefsHeadsPrefix.length) : ref;
212+
}
213+
}
214+
207215
/**
208216
* If the input is a single file, upload this file without any processing.
209217
* If the input is a single folder, zip it's content. The archive name is the folder's name

0 commit comments

Comments
 (0)