This code automates Git repository and build workflows using calendar events, triggering builds and tests while also updating existing events with the latest commit information.
npm run import -- "github updates"
var _ = require('lodash');
var {JSDOM} = require('jsdom');
var importer = require('../Core');
var {
gitTree, execCmd, getOauthClient, createNewEvent,
updateEvent, cloneProject, getDaysEvents
} = importer.import("d3.ipynb[format d3 tree]",
"json git tree",
"spawn child process",
"import google calendar api",
"create merge delete event",
"git project directory",
"days events",
"create new calendar event");
var options = {
calendarId: 'aws'
}
// create a calendar event to retest this branch
function installBuildTestEvent(project) {
return createNewEvent('spawn child process', JSON.stringify({
script: `npm install\nnpm run build\nnpm run test`,
options: {cwd: project} // TODO: fix current working directory using project name?
}, null, 4), options)
}
function updateHeartbeatEvent(project, branch, commit) {
return getOauthClient(options)
.then(() => getDaysEvents(new Date(), options))
.then(r => {
const heartbeat = r.filter(r => r.event.summary === 'heartbeat'
|| r.event.summary === 'todays heartbeat items');
try {
var dom = new JSDOM('<body>' + (heartbeat[0].event.description || '').replace(/<br\/?>/igm, '\n') + '</body>');
const desc = dom.window.document.body.textContent.split('\n');
desc.forEach((c, i) => {
if(c.trim().length > 0 && c.includes('github updates')) {
const parameters = JSON.parse(((/[\{].*[\}]|[\[].*[\]]|(['"]).*\1/igm).exec(c) || ['""'])[0]);
if(parameters[0] === project && parameters[1] === branch) {
parameters[2] = commit;
}
desc[i] = 'github updates ' + JSON.stringify(parameters);
}
});
assert(desc.length, 'there is a serious problem with updating the commit');
heartbeat[0].event.description = desc.join('\n');
return updateEvent(heartbeat[0].event, options);
} catch ( e ) {
console.log(e);
}
})
}
function findBranchRemote(project, branch) {
return execCmd(`git branch -r`, {cwd: project}) //
.then(r => {
const remotes = r.join('\n').split(/\s*\n\s*/igm).filter(r => (r.split('/')[1] || '').trim() === branch);
if(remotes.length === 0) {
throw new Error('branch "' + branch + '" not found on any remotes ' + JSON.stringify(r))
}
remote = remotes[0].split('/')[0];
return remote;
})
.then(() => ({remote, branch}))
}
function getUpdate(project, branch, fromCommit) {
var projectCopy, latestCommit;
return cloneProject(project)
.then(p => {
projectCopy = p;
return findBranchRemote(projectCopy, branch);
})
.then(({remote, branch}) => execCmd(`
git fetch ${remote}
git log ${fromCommit || 'HEAD'}..${remote}/${branch}`, {cwd: projectCopy}))
.then(log => {
if(log.join('').trim().length > 0) {
latestCommit = (/commit (.*)/ig).exec(log.join(''))[1];
return cloneProject(projectCopy, true)
} else {
throw new Error('nothing for git to do');
}
})
.then(r => {
projectCopy = r;
if(branch) {
return execCmd(`
git reset --hard
git checkout ${branch}`, {cwd: projectCopy})
}
})
.then(() => execCmd(importer.interpret('git auto rebase').code.trim()
+ ` ${remote} ${branch}`, {cwd: projectCopy}))
.then(() => installBuildTestEvent(projectCopy))
// TODO: update heartbeat event description to pass in the latest commit
.then(() => updateHeartbeatEvent(project, branch, latestCommit))
}
module.exports = getUpdate;
// git log currentbranch@{1}..currentbranch
// where the @{1} notation means "the commit the branch pointed to just before it last got updated".
// git log HEAD..swiftpage/development
if(typeof $ !== 'undefined') {
$.async();
getUpdate('portal')
.then(r => $.sendResult(r))
.catch(e => $.sendError(e))
}
const { JSDOM } = require('jsdom');
const importer = require('../Core');
const {
gitTree, execCmd, getOauthClient, createNewEvent, updateEvent, cloneProject,
getDaysEvents, interpret, spawnChildProcess
} = importer.import([
'd3.ipynb[format d3 tree]',
'json git tree',
'spawn child process',
'import google calendar api',
'create merge delete event',
'git project directory',
'days events',
'create new calendar event'
]);
class UpdateManager {
constructor(calendarId) {
this.calendarId = calendarId;
}
async createCalendarEvent(project, script) {
return createNewEvent('spawn child process', JSON.stringify({
script,
options: { cwd: project }
}), { calendarId: this.calendarId })
}
async updateHeartbeatEvent(project, branch, commit) {
try {
const client = await getOauthClient({ calendarId: this.calendarId });
const events = await getDaysEvents(new Date(), { calendarId: this.calendarId });
const heartbeat = events.filter(event => event.summary === 'heartbeat' || event.summary === 'todays heartbeat items');
if (!heartbeat.length) {
throw new Error('No heartbeat events found');
}
const dom = new JSDOM(`${(heartbeat[0].event.description || '').replace(/
/igm, '\n')}');
const description = dom.window.document.body.textContent.split('\n');
description.forEach((line, index) => {
if (line.trim().length > 0 && line.includes('github updates')) {
const parameters = JSON.parse(((/[\{].*[\}]|[\[].*[\]]|(['"]).*\1/igm).exec(line) || ['""'])[0]);
if (parameters[0] === project && parameters[1] === branch) {
parameters[2] = commit;
}
description[index] = `github updates ${JSON.stringify(parameters)}`;
}
});
heartbeat[0].event.description = description.join('\n');
return updateEvent(heartbeat[0].event, { calendarId: this.calendarId });
} catch (error) {
console.log(error);
}
}
async findBranchRemote(project, branch) {
const remote = await execCmd('git branch -r', { cwd: project });
const remotes = remote.join('\n').split(/\s*\n\s*/igm).filter(remote => (remote.split('/')[1] || '').trim() === branch);
if (!remotes.length) {
throw new Error(`Branch "${branch}" not found on any remotes: ${remote.join('\n')}`);
}
return { remote: remotes[0].split('/')[0], branch };
}
async getUpdate(project, branch, fromCommit) {
const projectCopy = await cloneProject(project);
const { remote, branch: localBranch } = await this.findBranchRemote(projectCopy, branch);
const log = await execCmd(`git fetch ${remote} && git log ${fromCommit || 'HEAD'}..${remote}/${localBranch}`, { cwd: projectCopy });
const latestCommit = log.join('').trim().length > 0? (/commit (.*)/ig).exec(log.join(''))[1] : null;
if (!latestCommit) {
throw new Error('No updates to apply');
}
await execCmd('git reset --hard && git checkout'+ localBranch, { cwd: projectCopy });
await execCmd(importer.interpret('git auto rebase').code.trim() + ` ${remote} ${localBranch}`, { cwd: projectCopy });
await this.createCalendarEvent(projectCopy, `npm install && npm run build && npm run test`);
await this.updateHeartbeatEvent(project, localBranch, latestCommit);
return projectCopy;
}
}
module.exports = (calendarId) => {
return new UpdateManager(calendarId);
}
if (typeof $!== 'undefined') {
$.async();
new UpdateManager('aws')
.getUpdate('portal')
.then(result => $.sendResult(result))
.catch(error => $.sendError(error));
}
This code snippet focuses on managing and updating calendar events related to Git repositories and builds.
Here's a breakdown:
Imports:
Calendar Event Configuration:
options
for calendar events, specifying the calendarId
as 'aws'.installBuildTestEvent
Function:
project
directory.npm install
, npm run build
, and npm run test
commands.updateHeartbeatEvent
Function:
project
and branch
, and updates it with the new commit
hash.Key Concepts:
npm install
, npm run build
, npm run test
) and likely interacts with Git repositories to track changes and trigger actions.In essence, this code snippet demonstrates how to use calendar events to manage and automate workflows involving Git repositories, builds, and testing.