Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

Commit

Permalink
Move nht rebuild into n-ui
Browse files Browse the repository at this point in the history
 🐿 v2.11.0
  • Loading branch information
kitkat119 committed Dec 4, 2018
1 parent 000746c commit 95ee7be
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,5 @@ ifneq (,$(findstring beta,$(CIRCLE_TAG)))
else
# only autodeploy all apps in office hours
HOUR=$$(date +%H); DAY=$$(date +%u); if [ $$HOUR -ge 8 ] && [ $$HOUR -lt 16 ] && [ $$DAY -ge 0 ] && [ $$DAY -lt 6 ]; then \
echo "REBUILDING ALL APPS" && nht rebuild --all --serves user-page; fi
echo "REBUILDING ALL APPS" && ./bin/nui.js rebuild --all --serves user-page; fi
endif
30 changes: 30 additions & 0 deletions build/app/circle-fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const fetch = require('node-fetch');
const keys = require('../lib/rebuild-keys');

const getCircleToken = () =>
process.env.CIRCLECI_REBUILD_KEY
? Promise.resolve(process.env.CIRCLECI_REBUILD_KEY)
: keys().then(env => env.CIRCLECI_REBUILD_KEY);

module.exports = async function circleFetch (path, opts) {
const defaultOptions = {
timeout: 3000,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
};

const circleToken = await getCircleToken();
const options = Object.assign(defaultOptions, opts);
const url = `https://circleci.com/api/v1.1/project/github/Financial-Times${path}?circle-token=${circleToken}`;

const res = await fetch(url, options);

if (res.ok) {
return await res.json();
} else {
console.log(`Response not OK for ${path}, got: ${res.status}`); // eslint-disable-line no-console
throw new Error(res.status);
}
};
83 changes: 78 additions & 5 deletions build/app/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const shellpromise = require('shellpromise');
const shellpipe = require('./shellpipe');
const grabNUiAssets = require('./grab-n-ui-assets');
const assetHashes = require('../lib/generate-asset-hashes');
const fetchres = require('fetchres');
const circleFetch = require('./circle-fetch');

const exit = err => {
logger.error(err);
Expand Down Expand Up @@ -50,15 +52,60 @@ const aboutJson = () => {
.then(about => fs.writeFileSync(path.join(process.cwd(), '/public/__about.json'), JSON.stringify(about, null, 2)));
};

const buildConfig = require(path.join(process.cwd(), 'n-ui-build.config.js'));
const cssEntryPoints = Object.keys(buildConfig.entry)
.map(target => [target, buildConfig.entry[target]])
.filter(([target]) => target.includes('.css'));

program.version(nUiVersion);

const webpackConfPath = path.join(__dirname, 'webpack.config.js');

const DEFAULT_REGISTRY_URI = 'https://next-registry.ft.com/v2/services.json';

const triggerMasterBuild = (project) => circleFetch(`/${project}/build`, { method: 'POST', body: JSON.stringify({ branch: 'master' }) });

const lastMasterBuild = (project) => circleFetch(`/${project}/tree/master`);

const getRepoName = ({ repository }) => {
if (/https?:\/\/github\.com\/Financial-Times\//.test(repository)) {
return repository
.replace(/https?:\/\/github\.com\/Financial-Times\//, '')
.replace(/\/$/, ''); // trim trailing "/"
}
};

const serves = type => app => type ? app.types && app.types.includes(type) : true;

async function rebuild (options) {
const apps = options.apps;
const allApps = options.all;
const registry = options.registry || DEFAULT_REGISTRY_URI;
let appsToRebuild = [];

const areAppsToRebuild = (apps.length) || allApps;
if (!areAppsToRebuild) {
console.log('Use the --all flag to rebuild all apps or supply a specific app name.'); // eslint-disable-line no-console
process.exit(1);
}

if (apps.length) {
appsToRebuild = apps;
} else if (allApps) {
const registryData = await fetch(registry).then(fetchres.json);
appsToRebuild = registryData
.filter(serves(options.serves))
.map(getRepoName)
.filter(repo => repo);
}

return Promise.all(appsToRebuild.map(async app => {
console.log(`Considering whether to rebuild ${app}`); // eslint-disable-line no-console
try {
const [lastBuild] = await lastMasterBuild(app);
console.log(`Triggering master build for ${app} (git commit: ${lastBuild.vcs_revision})`); // eslint-disable-line no-console
await triggerMasterBuild(app);
} catch (error) {
console.log(`Skipped rebuild of ${app}, probably because Circle CI not set up for this repo`); // eslint-disable-line no-console
}
}));
};

program
.command('build')
.description('Builds n-ui apps, ready to be deployed to your favourite s3 bucket or heroku host')
Expand All @@ -70,6 +117,11 @@ program
devAdvice();
let concurrentCommands = [];

const buildConfig = require(path.join(process.cwd(), 'n-ui-build.config.js'));
const cssEntryPoints = Object.keys(buildConfig.entry)
.map(target => [target, buildConfig.entry[target]])
.filter(([target]) => target.includes('.css'));

const script = './node_modules/@financial-times/n-ui/scripts/build-sass.sh';
const commands = {
jsOnly: `'webpack ${options.production ? '--mode=production' : ''} --config ${webpackConfPath}'`,
Expand Down Expand Up @@ -106,6 +158,11 @@ program
.action(() => {

devAdvice();
const buildConfig = require(path.join(process.cwd(), 'n-ui-build.config.js'));
const cssEntryPoints = Object.keys(buildConfig.entry)
.map(target => [target, buildConfig.entry[target]])
.filter(([target]) => target.includes('.css'));

const cssBuildWatchCommands = cssEntryPoints.map(([target, entry]) => {
const script = './node_modules/@financial-times/n-ui/scripts/build-sass.sh';
const entryDirectory = path.dirname(entry);
Expand All @@ -118,6 +175,22 @@ program
.catch(exit);
});

program
.command('rebuild [apps...]')
.description('Trigger a rebuild of the latest master on Circle')
.option('--all', 'Trigger rebuilds of all apps.')
.option('--registry [registry-uri]', `use this registry, instead of the default: ${DEFAULT_REGISTRY_URI}`, DEFAULT_REGISTRY_URI)
.option('--serves <type>', 'Trigger rebuilds of apps where type is served.')
.action((apps, opts) => {
devAdvice();
return rebuild({
apps: apps,
serves: opts.serves,
registry: opts.registry,
all: opts.all
}).catch(exit);
});

program
.command('*')
.description('')
Expand Down
4 changes: 4 additions & 0 deletions build/lib/development-keys-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use strict';

const join = require('path').join;
module.exports = join(process.cwd(), '.env');
13 changes: 13 additions & 0 deletions build/lib/rebuild-keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

const { promisify } = require('util');
const readFile = promisify(require('fs').readFile);
const developmentKeysPath = require('./development-keys-path');
const dotenv = require('dotenv');

module.exports = function () {
return readFile(developmentKeysPath, { encoding: 'utf8' })
.then(function (env) {
return dotenv.parse(env);
});
};
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
"chai": "^4.1.2",
"chalk": "^2.4.1",
"coveralls": "^3.0.1",
"dotenv": "^6.1.0",
"fetch-mock": "^6.4.4",
"fetchres": "^1.7.2",
"karma": "^2.0.4",
"karma-browserstack-launcher": "^1.3.0",
"karma-chai": "^0.1.0",
Expand Down

0 comments on commit 95ee7be

Please sign in to comment.