Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Connecting Unity Cloud Build with HockeyApp (the slightly hackish way)
// The MIT License (MIT)
//
// Copyright (c) 2017 Lavapotion AB
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
'use strict'
var gulp = require('gulp');
var gulpDownload = require('gulp-download');
var rename = require('gulp-rename');
var request = require('request');
var git = require('simple-git');
var hockeyApp = require('gulp-hockeyapp');
var cloudBuildSettings = {
apiKey: "<YOUR_CLOUDBUILD_API_KEY>",
organizationID: "<YOUR_CLOUDBUILD_ORGANIZATION_NAME>",
projectName: "<YOUR_CLOUDBUILD_PROJECT_NAME>"
};
var hockeyAppSettings = {
apiKey: "<YOUR_HOCKEYAPP_API_KEY>",
androidDevKey: "<YOUR_HOCKEYAPP_APPLICATION_ID>",
devTeamID: <YOUR_TEAM_ID>
};
var tasks = {
hockeyApp: 'hockeyapp',
};
var paths = {
dist: 'dist/'
}
gulp.task(tasks.hockeyApp, function (done) {
var notifyByEmail = false;
downloadAndUploadToHockeyApp('android-dev',
hockeyAppSettings.androidDevKey,
done,
notifyByEmail,
[hockeyAppSettings.devTeamID]);
});
function downloadAndUploadToHockeyApp(pBuildTargetId, pHockeyAppID, pOnCompleteCallback, pNotifyAll, pTeams) {
downloadBuildInformation(pBuildTargetId, function (pBuildInfo) {
downloadLatestBuild(pBuildInfo, function (pDownloadFilename) {
createMarkdownReleaseNotes(pBuildInfo, function (pMarkdownChangelog) {
var options = {
id: pHockeyAppID,
apiToken: hockeyAppSettings.apiKey,
inputFile: paths.dist + pDownloadFilename,
notify: pNotifyAll === true ? 2 : 0,
status: 2,
teamList: pTeams,
notes: pMarkdownChangelog,
notes_type: 2
};
console.log('\nUploading to hockeyapp...\n');
hockeyApp.upload(options).then(
function (response) {
console.log("Successfully uploaded build to HockeyApp!");
pOnCompleteCallback();
},
function (err) {
throw err;
}
);
})
});
});
}
function downloadLatestBuild(pBuildInfo, pOnCompleteCallback) {
if (pBuildInfo === null) {
throw 'Cannot download build! Information is null!'
}
var latestDownloadFileName = cloudBuildSettings.projectName + '_' + pBuildInfo.buildtargetid + '.' + pBuildInfo.links.download_primary.meta.type;
gulpDownload(pBuildInfo.links.download_primary.href)
.pipe(rename(latestDownloadFileName))
.pipe(gulp.dest(paths.dist))
.on('end', function () {
console.log('\nFinished Downloading Build\n');
pOnCompleteCallback(latestDownloadFileName);
});
}
function downloadBuildInformation(pBuildTargetID, pOnCompleteCallback) {
var baseURL = 'https://build-api.cloud.unity3d.com/api/v1';
var options = {
url: baseURL + '/orgs/' + cloudBuildSettings.organizationID + '/projects/' + cloudBuildSettings.projectName + '/buildtargets/' + pBuildTargetID + '/builds?buildStatus=success',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic ' + cloudBuildSettings.apiKey
}
};
request(options, function (error, response, body) {
var latestBuild = null;
if (!error) {
var builds = JSON.parse(body);
var latestDate = new Date(-8640000000000000);
for (var i = 0; i < builds.length; ++i) {
var currentBuild = builds[i];
var finishedDate = new Date(currentBuild.finished);
if (latestDate < finishedDate) {
latestBuild = currentBuild;
latestDate = finishedDate;
}
}
}
else {
console.log('Failed to get build information! message: ' + error);
pOnCompleteCallback();
}
if (typeof (pOnCompleteCallback) !== 'undefined' && pOnCompleteCallback != null) {
pOnCompleteCallback(latestBuild);
}
})
}
function createMarkdownReleaseNotes(pBuildInfo, pOnCompleteCallback) {
if (pBuildInfo === null) {
throw 'Cannot get changelog! Information is null!'
}
var markdownChangelog = '#' + cloudBuildSettings.projectName + ' ' + pBuildInfo.buildTargetName + '\n';
markdownChangelog += '**Branch:** ' + pBuildInfo.scmBranch + '\n';
markdownChangelog += '**SHA1:** ' + pBuildInfo.lastBuiltRevision + '\n\n';
var ignoreCommitIds = [];
if (pBuildInfo.changeset.length > 0) {
markdownChangelog += '## Recent Changes \n\n';
markdownChangelog += 'If installed, this build will: \n';
for (var i = 0; i < pBuildInfo.changeset.length; ++i) {
var message = pBuildInfo.changeset[i].message;
markdownChangelog += '* ';
markdownChangelog += message;
markdownChangelog += '\n';
ignoreCommitIds.push(pBuildInfo.changeset[i].commitId);
}
}
var gitLogSettings = [];
var maxHistoryLogs = 50;
gitLogSettings.push(pBuildInfo.lastBuiltRevision);
gitLogSettings.push(pBuildInfo.scmBranch);
getGitLog(gitLogSettings, function (pLogArray) {
markdownChangelog += buildChangelogHistoryFromGitArray(pLogArray, maxHistoryLogs, ignoreCommitIds);
pOnCompleteCallback(markdownChangelog);
});
}
function buildChangelogHistoryFromGitArray(pLogArray, pMaxHistoryLogs, pExcludeShaArray) {
var changeHistory = '';
if (pLogArray.length > 0) {
changeHistory += '\n## Change History \n\n';
for (var i = 0; i < pLogArray.length; ++i) {
var message = pLogArray[i].message;
if (pExcludeShaArray.indexOf(pLogArray[i].hash) === -1) {
changeHistory += '* ';
changeHistory += message;
changeHistory += '\n';
}
if (pMaxHistoryLogs !== -1 && i >= pMaxHistoryLogs) {
break;
}
}
}
return changeHistory;
}
function getGitLog(pGitLogSettings, pOnCompleteCallback) {
git().log(pGitLogSettings, function (err, log) {
var logArray = null;
if (!err) {
logArray = log.all;
}
pOnCompleteCallback(logArray);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.