Skip to content

Instantly share code, notes, and snippets.

@dannycoates dannycoates/circleci.js
Last active Apr 3, 2019

What would you like to do?
const parseDiff = require('diffparser');
const fetch = require('node-fetch');
const { moduleDependencies } = require('../package.json').fxa;
function moduleName(path) {
const parts = path.split('/');
return parts.length > 1 ? parts[0] : 'root';
async function getModules(org, repo, branch) {
try {
const response = await fetch(`${org}/${repo}/${branch}.diff`);
const diff = parseDiff(await response.text());
const modules = new Set()
for (const { to, from } of diff) {
[to, from]
.filter(n => n !== '/dev/null')
.forEach(n => modules.add(moduleName(n)))
return modules;
} catch (e) {
return new Set(['all']);
function modulesToTest(changed) {
const toTest = new Set(changed);
let size;
do {
size = toTest.size;
for (const [mod, deps] of Object.entries(moduleDependencies)) {
for (const m of toTest) {
if (deps.includes(m)) {
} while (size < toTest.size)
return toTest;
async function main() {
const branch = process.env.CIRCLE_BRANCH;
const org = process.env.CIRCLE_PROJECT_USERNAME;
const repo = process.env.CIRCLE_PROJECT_REPONAME;
if (branch.startsWith('pull/')) {
const toTest = modulesToTest(await getModules(org, repo, branch));
for (const mod of toTest) {
else {
#!/usr/bin/env bash -ex
MODULES=('fxa-monorepo-prep' 'fxa-basket-proxy' '123done' 'browserid-verifier' 'fxa-auth-db-mysql' 'fxa-auth-server' 'fxa-content-server' 'fxa-customs-server' 'fxa-email-service' 'fxa-js-client' 'fxa-oauth-console' 'fxa-profile-server' 'fxa-shared' 'fxa-geodb' 'fxa-email-event-proxy')
mkdir fxa
cd fxa
git init
git commit --allow-empty --date '1980-08-23T20:15:12' -m 'this is the fxa monorepo'
git tag -a first-commit -m 'first commit'
FIRST=$(git rev-parse HEAD)
rewrite_module() {
local module=$1
git remote add $module${module}.git
git fetch $module
if [[ "${module}" == '123done' ]]; then
git checkout --no-track -b $module ${module}/oauth
git checkout --no-track -b $module ${module}/master
if [[ "${module}" == 'fxa-monorepo-prep' ]]; then
# put fxa-monorepo-prep at the root
git filter-branch -f --parent-filter "sed 's/^\$/-p ${FIRST}/'" --tag-name-filter "sed 's/^/${module}-/'" --msg-filter "sed -E 's/[\^\( ]+#([0-9]+)/ mozilla\/fxa-local-dev#\1/g'" --prune-empty HEAD
# put other modules in subdirectories
git filter-branch -f --parent-filter "sed 's/^\$/-p ${FIRST}/'" --tag-name-filter "sed 's/^/${module}-/'" --msg-filter "sed -E 's/[\^\( ]+#([0-9]+)/ mozilla\/${module}#\1/g'" --index-filter "git ls-files -s | sed '/${TAB}${module}\//! s/${TAB}/${TAB}packages\/${module}\//' | GIT_INDEX_FILE=\$ git update-index --index-info && if test -f \"\$\"; then mv \"\$\" \"\$GIT_INDEX_FILE\"; fi" --prune-empty HEAD
git tag -a ${module}-master -m "last commit of ${module} before monorepo"
git remote remove $module
git checkout master
for module in "${MODULES[@]}"; do
rewrite_module $module
git merge -m "merged all repos" ${MODULES[@]}
git tag -a monorepo-merge -m 'monorepo merge point'
git tag --list --no-merged HEAD | xargs git tag -d
git branch -d ${MODULES[@]}
"fxa": {
"moduleDependencies": {
"fxa-content-server": [
"fxa-auth-server": [
"fxa-js-client": [
"fxa-profile-server": [
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.