The Cardshifter web client is coming along! The game client is a web app written mostly in Angular.js and is hosted at at play.cardshifter.com.
@SimonForsberg (who runs the server) is getting tired of the web people always working tirelessly and updating the code, and asked for a script that can do deployment for him.
Requirements
- Upload the contents of
dist/
to/assets/
andwww/
to/
through FTP. - Post a message to the chat bot Duga using a HTTP request when done.
- Can be run automatically on Travis CI.
Background
I'm quite new to JavaScript and Node.js land. I chose to still use it for three reasons:
- Dependency management already set up with Npm
- Project is already JavaScript; easier maintenance
- Fun to learn :)
I chose to pass credentials through environment variables because it looks like Travis CI handles encrypted variables well. A person that has the credentials can also set up a simple script to run the deployment with those specific variables.
@skiwi told me about promises after having written the code originally, but it prompted me to convert the code to use them instead of normal callbacks. I think this lead to a great improvement of the readability of the code.
ftp-deploy
was acting up when uploading dist/
and www/
separately, which is why the script is now first copying everything to a temporary directory with a structure emulating the server. One problem was that if remoteRoot
didn't exist, the upload would fail.
Simon hasn't told me the address of the FTP server yet, which is why I left localhost:2121
in there.
/* Deploy the client to play.cardshifter.com
*
* How to use:
* 1. Build the project and make sure that everything is in order.
* 2. Set up environment variables (see below).
* 3. Run `npm run deploy`.
* 4. Profit!
*
* Environment variables used:
* - DEPLOY_FTP_USERNAME: Username used to log in through FTP.
* - DEPLOY_FTP_PASSWORD: Password used to log in through FTP.
* - DEPLOY_DUGA_KEY: Duga API key. If not set the chat bot post is skipped.
*/
'use strict';
var copy = require('recursive-copy');
var FtpDeploy = require('ftp-deploy');
var path = require('path');
var request = require('request-promise');
var temp = require('temp').track();
function ftpConfig(local, remote) {
return {
username: process.env.DEPLOY_FTP_USERNAME,
password: process.env.DEPLOY_FTP_PASSWORD,
host: "localhost",
port: 2121,
localRoot: local,
remoteRoot: remote
};
};
var chatBotRequest = {
apiKey: process.env.DEPLOY_DUGA_KEY,
roomId: 16134,
text: "New web client version uploaded to http://play.cardshifter.com/."
};
var chatBotConfig = {
url: "http://stats.zomis.net/GithubHookSEChatService/bot/jsonPost",
method: "POST",
headers: {
"Content-Type": "application/json"
}
}
function postToChat(config, botRequest) {
return new Promise(function(resolve, reject) {
var json = JSON.stringify(botRequest, ["apiKey", "roomId", "text"]);
config.headers["Content-Length"] = json.length;
config.body = json;
request(config)
.then(function(body) {
resolve(body);
})
});
}
function setupFiles() {
// ftp-deploy doesn't handle uploading from multiple directories well
return new Promise(function(resolve, reject) {
temp.mkdir("cardshifter-deploy", function (err, tempDir) {
if (err) {
reject(err);
}
Promise.all([
copy(path.join(__dirname, "..", "www"), tempDir),
copy(path.join(__dirname, "..", "dist"), path.join(tempDir, "assets"))
])
.then(function() {
resolve(tempDir);
})
.catch(function(err) {
reject(err);
});
});
});
}
function deployFtp(config) {
return new Promise(function(resolve, reject) {
new FtpDeploy().deploy(config, function(err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
setupFiles()
.then(function(dir) {
var config = ftpConfig(dir, "/");
console.log("Deploying to ftp://" + config.host + ":" + config.port + "...");
return deployFtp(config);
})
.then(function() {
console.log("FTP deployment successful.");
if (chatBotRequest.apiKey) {
console.log("Posting message to " + chatBotConfig.url + "...");
return postToChat(chatBotConfig, chatBotRequest);
}
})
.then(function(responseBody) {
if (responseBody) {
console.log(responseBody);
}
})
.catch(function(err) {
console.error("Error: " + err);
});
gulp
. Particularly as it has modules for ftp, and all of the related stuff there. I'm not familiar with Duga though, so I can't help much there. \$\endgroup\$play.cardshifter.com
;) \$\endgroup\$