Lots of little improvements
This commit is contained in:
Родитель
2d3437fad6
Коммит
a6e0f241e2
241
app.js
241
app.js
|
@ -1,18 +1,21 @@
|
|||
const express = require('express');
|
||||
const app = express();
|
||||
const bodyParser = require('body-parser');
|
||||
const sleep = require('sleep');
|
||||
var cookieParser = require('cookie-parser')
|
||||
const cookieParser = require('cookie-parser');
|
||||
const oauth2 = require('salesforce-oauth2');
|
||||
const jsforce = require('jsforce');
|
||||
const commands = require('./lib/commands.js');
|
||||
|
||||
const {
|
||||
exec
|
||||
} = require('child_process');
|
||||
const oauth2 = require('salesforce-oauth2');
|
||||
|
||||
const app = express();
|
||||
|
||||
const callbackUrl = process.env.CALLBACKURL;
|
||||
const consumerKey = process.env.CONSUMERKEY;
|
||||
const consumerSecret = process.env.CONSUMERSECRET;
|
||||
|
||||
app.use('/scripts', express.static(__dirname + '/scripts'));
|
||||
app.use('/scripts', express.static(`${__dirname}/scripts`));
|
||||
|
||||
app.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
|
@ -22,15 +25,27 @@ app.set('view engine', 'ejs');
|
|||
|
||||
app.use(cookieParser());
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
app.get('/', (req, res) => {
|
||||
res.render('pages/index', {});
|
||||
});
|
||||
|
||||
app.get('/about', function (req, res) {
|
||||
app.get('/about', (req, res) => {
|
||||
res.render('pages/about');
|
||||
});
|
||||
|
||||
app.get('/deploy', function (req, res) {
|
||||
app.get('/notdevhub', (req, res) => {
|
||||
const template = req.query.template;
|
||||
res.cookie('template', template);
|
||||
|
||||
const user_name = req.cookies.user_name;
|
||||
|
||||
res.render('pages/notdevhub', {
|
||||
template: template,
|
||||
user_name: user_name
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/deploy', (req, res) => {
|
||||
const template = req.query.template;
|
||||
|
||||
res.cookie('template', template);
|
||||
|
@ -51,145 +66,207 @@ app.get('/deploy', function (req, res) {
|
|||
}
|
||||
});
|
||||
|
||||
app.get('/deploying', function (req, res) {
|
||||
app.get('/deploying', (req, res) => {
|
||||
const template = req.query.template;
|
||||
res.render('pages/deploying', {
|
||||
template: template
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/login", function (req, res) {
|
||||
var uri = oauth2.getAuthorizationUrl({
|
||||
app.get("/login", (req, res) => {
|
||||
const uri = oauth2.getAuthorizationUrl({
|
||||
redirect_uri: callbackUrl,
|
||||
client_id: consumerKey,
|
||||
scope: 'id api refresh_token openid',
|
||||
state: 'test123'
|
||||
// You can change loginUrl to connect to sandbox or prerelease env.
|
||||
//base_url: 'https://test.my.salesforce.com'
|
||||
});
|
||||
return res.redirect(uri);
|
||||
});
|
||||
|
||||
app.get('/logout', function (req, res) {
|
||||
res.clearCookie('access_token');
|
||||
res.clearCookie('instance_url');
|
||||
app.get('/logout', (req, res) => {
|
||||
|
||||
return res.redirect('/');
|
||||
const access_token = req.cookies.access_token;
|
||||
const instance_url = req.cookies.instance_url;
|
||||
|
||||
const conn = new jsforce.Connection({
|
||||
instanceUrl: instance_url,
|
||||
accessToken: access_token
|
||||
});
|
||||
|
||||
conn.logout((err) => {
|
||||
if (err) {
|
||||
return console.error(err);
|
||||
}
|
||||
res.clearCookie('access_token');
|
||||
res.clearCookie('instance_url');
|
||||
|
||||
return res.redirect('/');
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/oauth/callback', function (req, res) {
|
||||
app.get('/oauth/callback', (req, res) => {
|
||||
const authorizationCode = req.param('code');
|
||||
const state = req.param('state');
|
||||
console.log('state', state);
|
||||
// const state = req.param('state'); // TODO: use state and query instead of cookies
|
||||
|
||||
oauth2.authenticate({
|
||||
redirect_uri: callbackUrl,
|
||||
client_id: consumerKey,
|
||||
client_secret: consumerSecret,
|
||||
code: authorizationCode
|
||||
}, function (error, payload) {
|
||||
}, (error, payload) => {
|
||||
|
||||
res.cookie('access_token', payload.access_token);
|
||||
res.cookie('instance_url', payload.instance_url);
|
||||
res.cookie('refresh_token', payload.refresh_token);
|
||||
res.cookie('user_name', payload.id);
|
||||
|
||||
console.log(payload);
|
||||
|
||||
const template = req.cookies.template;
|
||||
return res.redirect(`/deploy?template=${template}`);
|
||||
// check to see if org is a dev hub
|
||||
const conn = new jsforce.Connection({
|
||||
instanceUrl: payload.instance_url,
|
||||
accessToken: payload.access_token
|
||||
});
|
||||
|
||||
conn.identity((err, identity) => {
|
||||
if (err) {
|
||||
return console.error(err);
|
||||
}
|
||||
|
||||
res.cookie('user_name', identity.username);
|
||||
|
||||
conn.tooling.query("SELECT DurableId, SettingValue FROM OrganizationSettingsDetail WHERE SettingName = 'ScratchOrgManagementPref'", (err, result) => {
|
||||
if (err) {
|
||||
return console.error(err);
|
||||
}
|
||||
|
||||
const template = req.cookies.template;
|
||||
|
||||
if (result.size > 0) {
|
||||
const devHubEnabled = result.records[0].SettingValue;
|
||||
|
||||
if (devHubEnabled === true) {
|
||||
return res.redirect(`/deploy?template=${template}`);
|
||||
} else {
|
||||
return res.redirect(`/notdevhub?template=${template}`);
|
||||
}
|
||||
} else {
|
||||
return res.redirect(`/notdevhub?template=${template}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var router = express.Router();
|
||||
const router = express.Router();
|
||||
|
||||
router.post('/deploying', function (req, res) {
|
||||
|
||||
var command = req.body.command;
|
||||
var param = req.body.param;
|
||||
router.post('/deploying', (req, res) => {
|
||||
|
||||
const command = req.body.command;
|
||||
const timestamp = req.body.timestamp;
|
||||
const param = req.body.param;
|
||||
const access_token = req.cookies.access_token;
|
||||
const instance_url = req.cookies.instance_url;
|
||||
const refresh_token = req.cookies.refresh_token;
|
||||
|
||||
if (command === 'clone') {
|
||||
const tokenName = access_token.replace(/\W/g, '');
|
||||
const startingDirectory = process.env.STARTINGDIRECTORY;
|
||||
const directory = `${tokenName}-${timestamp}`;
|
||||
|
||||
exec(`cd /tmp;mkdir test;cd test;git clone ${param} repo`, (err, stdout, stderr) => {
|
||||
res.json({
|
||||
message: `Successfully cloned ${param}`
|
||||
let script;
|
||||
let sfdxurl;
|
||||
|
||||
switch (command) {
|
||||
|
||||
case 'clone':
|
||||
|
||||
script = `${startingDirectory}mkdir ${directory};cd ${directory};git clone ${param} .`;
|
||||
|
||||
commands.run(command, script, () => {
|
||||
res.json({
|
||||
message: `Successfully cloned ${param}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
if (command === 'auth') {
|
||||
case 'auth':
|
||||
|
||||
const sfdxurl = `echo "force://${consumerKey}:${consumerSecret}:${refresh_token}@${instance_url}" > sfdx.key`;
|
||||
const commandScript = `cd /tmp/test/repo;export FORCE_SHOW_SPINNER=;${sfdxurl};sfdx force:auth:sfdxurl:store -f sfdx.key -d`;
|
||||
console.log('auth', commandScript);
|
||||
sfdxurl = `echo "force://${consumerKey}:${consumerSecret}:${refresh_token}@${instance_url}" > sfdx.key`;
|
||||
script = `${startingDirectory}cd ${directory};export FORCE_SHOW_SPINNER=;${sfdxurl};sfdx force:auth:sfdxurl:store -f sfdx.key -d`;
|
||||
|
||||
exec(commandScript, (err, stdout, stderr) => {
|
||||
console.log('create:stderr', stderr);
|
||||
res.json({
|
||||
message: `Authenticated to dev hub: ${stdout}`
|
||||
commands.run(command, script, (result) => {
|
||||
res.json({
|
||||
message: `Authenticated to dev hub: ${result}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (command === 'create') {
|
||||
break;
|
||||
|
||||
const commandScript = `cd /tmp/test/repo;export FORCE_SHOW_SPINNER=;sfdx force:org:create -s -f ${param}`;
|
||||
console.log('create', commandScript);
|
||||
case 'create':
|
||||
|
||||
exec(commandScript, (err, stdout, stderr) => {
|
||||
console.log('create:stderr', stderr);
|
||||
res.json({
|
||||
message: `Created scratch org: ${stdout}`
|
||||
script = `${startingDirectory}cd ${directory};export FORCE_SHOW_SPINNER=;sfdx force:config:set instanceUrl=${instance_url};sfdx force:org:create -v '${access_token}' -s -f ${param}`;
|
||||
|
||||
commands.run(command, script, (result) => {
|
||||
res.json({
|
||||
message: `Created scratch org: ${result}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (command === 'push') {
|
||||
exec(`cd /tmp/test/repo;export FORCE_SHOW_SPINNER=;sfdx force:source:push`, (err, stdout, stderr) => {
|
||||
res.json({
|
||||
message: `Pushed source:\n\t${stdout}`
|
||||
break;
|
||||
|
||||
case 'push':
|
||||
|
||||
script = `${startingDirectory}cd ${directory};export FORCE_SHOW_SPINNER=;sfdx force:source:push`;
|
||||
|
||||
commands.run(command, script, (result) => {
|
||||
res.json({
|
||||
message: `Pushed source:\n\t${result}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (command === 'test') {
|
||||
exec(`cd /tmp/test/repo;export FORCE_SHOW_SPINNER=;sfdx force:apex:test:run -r human --json | jq -r .result | jq -r .summary | jq -r .outcome`, (err, stdout, stderr) => {
|
||||
res.json({
|
||||
message: `Apex tests: ${stdout}`
|
||||
break;
|
||||
|
||||
case 'test':
|
||||
|
||||
script = `${startingDirectory}cd ${directory};export FORCE_SHOW_SPINNER=;sfdx force:apex:test:run -r human --json | jq -r .result | jq -r .summary | jq -r .outcome`;
|
||||
|
||||
commands.run(command, script, (result) => {
|
||||
res.json({
|
||||
message: `Apex tests: ${result}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (command === 'url') {
|
||||
const commandScript = 'cd /tmp/test/repo;export FORCE_SHOW_SPINNER=;echo $(sfdx force:org:display --json | jq -r .result | jq -r .instanceUrl)"/secur/frontdoor.jsp?sid="$(sfdx force:org:display --json | jq -r .result | jq -r .accessToken)';
|
||||
break;
|
||||
|
||||
exec(commandScript, (err, stdout, stderr) => {
|
||||
res.json({
|
||||
message: `${stdout}`
|
||||
case 'url':
|
||||
|
||||
script = `${startingDirectory}cd ${directory};export FORCE_SHOW_SPINNER=;echo $(sfdx force:org:display --json | jq -r .result | jq -r .instanceUrl)"/secur/frontdoor.jsp?sid="$(sfdx force:org:display --json | jq -r .result | jq -r .accessToken)`;
|
||||
|
||||
commands.run(command, script, (result) => {
|
||||
res.json({
|
||||
message: `${result}`
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (command === 'clean') {
|
||||
break;
|
||||
|
||||
const commandScript = 'rm -rf /tmp/test';
|
||||
exec(commandScript, (err, stdout, stderr) => {
|
||||
res.json({
|
||||
message: 'Removed temp files and cleaned up'
|
||||
case 'clean':
|
||||
|
||||
script = `${startingDirectory}rm -rf ${directory}`;
|
||||
|
||||
commands.run(command, script, () => {
|
||||
res.json({
|
||||
message: 'Removed temp files and cleaned up'
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
app.use('/api', router);
|
||||
|
||||
var port = process.env.PORT || 8080;
|
||||
app.listen(port, function () {
|
||||
const port = process.env.PORT || 8080;
|
||||
app.listen(port, () => {
|
||||
console.log(`Example app listening on port ${port}!`);
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
const {
|
||||
exec
|
||||
} = require('child_process');
|
||||
|
||||
module.exports = {
|
||||
run: (command, commandScript, result) => {
|
||||
exec(commandScript, (err, stdout, stderr) => {
|
||||
if (stderr || err) {
|
||||
console.log(`${command}:err`, err);
|
||||
console.log(`${command}:stderr`, stderr);
|
||||
}
|
||||
result(stdout);
|
||||
});
|
||||
}
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
$(document).ready(function () {
|
||||
$(document).ready(() => {
|
||||
|
||||
let actionCount = 0;
|
||||
let message = '';
|
||||
|
@ -10,13 +10,14 @@ $(document).ready(function () {
|
|||
$('textarea#status').val(message);
|
||||
}
|
||||
|
||||
async function deployingApi(command, param) {
|
||||
function deployingApi(command, timestamp, param) {
|
||||
|
||||
commandData = {};
|
||||
const commandData = {};
|
||||
commandData.command = command;
|
||||
commandData.timestamp = timestamp;
|
||||
commandData.param = param;
|
||||
|
||||
await $.ajax({
|
||||
return $.ajax({
|
||||
type: 'POST',
|
||||
url: '/api/deploying',
|
||||
data: JSON.stringify(commandData),
|
||||
|
@ -28,8 +29,7 @@ $(document).ready(function () {
|
|||
});
|
||||
}
|
||||
|
||||
let githubRepo = $('input#template').val();
|
||||
|
||||
const githubRepo = $('input#template').val();
|
||||
let yamlFile = githubRepo.replace('github.com', 'raw.githubusercontent.com');
|
||||
yamlFile += '/master/.salesforcedx.yaml';
|
||||
|
||||
|
@ -42,7 +42,9 @@ $(document).ready(function () {
|
|||
|
||||
update_status(`Discovered ${yamlFile}`);
|
||||
|
||||
var doc = jsyaml.load(yamlFileDataResponse);
|
||||
const doc = jsyaml.load(yamlFileDataResponse);
|
||||
|
||||
const timestamp = new Date().getTime().toString();
|
||||
|
||||
const assignPermset = doc['assign-permset'];
|
||||
const deleteScratchOrg = doc['delete-scratch-org'];
|
||||
|
@ -57,27 +59,25 @@ $(document).ready(function () {
|
|||
\tscratch-org-def: ${scratchOrgDef}
|
||||
\tshow-scratch-org-url: ${showScratchOrgUrl}`);
|
||||
|
||||
return deployingApi('clone', githubRepo)
|
||||
return deployingApi('clone', timestamp, githubRepo)
|
||||
.then(() => {
|
||||
return deployingApi('auth');
|
||||
return deployingApi('auth', timestamp);
|
||||
})
|
||||
.then(() => {
|
||||
return deployingApi('create', scratchOrgDef);
|
||||
return deployingApi('create', timestamp, scratchOrgDef);
|
||||
})
|
||||
.then(() => {
|
||||
return deployingApi('push');
|
||||
return deployingApi('push', timestamp);
|
||||
})
|
||||
.then(() => {
|
||||
return deployingApi('auth');
|
||||
})
|
||||
.then(() => {
|
||||
return deployingApi('test');
|
||||
return deployingApi('test', timestamp);
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
// generate url
|
||||
commandData = {};
|
||||
let commandData = {};
|
||||
commandData.command = 'url';
|
||||
commandData.timestamp = timestamp;
|
||||
|
||||
return $.ajax({
|
||||
type: 'POST',
|
||||
|
@ -86,23 +86,33 @@ $(document).ready(function () {
|
|||
contentType: 'application/json; charset=utf-8',
|
||||
dataType: 'json',
|
||||
success: (commandDataResponse) => {
|
||||
update_status(`${commandDataResponse.message}`);
|
||||
update_status(`Generated a login url: ${commandDataResponse.message}`);
|
||||
|
||||
const url = commandDataResponse.message;
|
||||
|
||||
$("#loginUrl").attr("href", url);
|
||||
$("#loginUrl").text(`${url.substring(0, 80)}...`);
|
||||
$('#loginUrl').attr('href', url);
|
||||
$('#loginUrl').text(`${url.substring(0, 80)}...`);
|
||||
$('#loginBlock').show();
|
||||
|
||||
// clean up
|
||||
commandData = {};
|
||||
commandData.command = 'clean';
|
||||
commandData.timestamp = timestamp;
|
||||
|
||||
// return deployingApi('clean', timestamp).then(() => {
|
||||
|
||||
// };
|
||||
|
||||
deployingApi(commandData);
|
||||
|
||||
message = `DONE!\n\n${message}`;
|
||||
$('textarea#status').val(message);
|
||||
}
|
||||
}).then(() => {
|
||||
return deployingApi('clean', timestamp)
|
||||
.then(() => {
|
||||
|
||||
message = `Finished. You have deploy the app to Salesforce DX!\n\n${message}`;
|
||||
$('textarea#status').val(message);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<main>
|
||||
<div class="jumbotron">
|
||||
<h1>Deploy</h1>
|
||||
<p>Hello, <%= user_name %>! You've indicated you'd like to deploy: <strong><%= template %></strong>. Is that correct?</p>
|
||||
<p>Hello, <strong><%= user_name %></strong>! You've indicated you'd like to deploy: <strong><%= template %></strong>. Is that correct?</p>
|
||||
<button type="button" class="btn btn-primary" id="yes">Yes</button>
|
||||
<button type="button" class="btn btn-default" id="no">No</button>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<% include ../partials/head %>
|
||||
</head>
|
||||
|
||||
<body class="container">
|
||||
|
||||
<header>
|
||||
<% include ../partials/header %>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="jumbotron">
|
||||
<h1>Not DevHub</h1><small>
|
||||
|
||||
<p>
|
||||
Sorry, but it looks like the org you've logged into is not a <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth.htm" target="_blank">dev hub</a>.
|
||||
Consequently, you cannot currently use <strong>Deploy to Salesforce DX</strong> to create a stratch org from a Github repo.
|
||||
</p>
|
||||
<p>To try this out, you have two options:</p>
|
||||
<div>
|
||||
<ol class="list-group">
|
||||
<li class="list-group-item">Enable dev hub in a Production or Business Org (i.e. not a DE org). Search on “Dev Hub” from Setup and then click Enabled.</li>
|
||||
<li class="list-group-item">Get a <a href="https://sfdc.co/DX-Trial-Org">30-day free trial.</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
<p>Please try again once you've gotten this resolved.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<% include ../partials/footer %>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче