Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"presets": ["porch"]
"presets": ["react-app"]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"babel-cli": "^6.6.5",
"babel-polyfill": "^6.13.0",
"babel-preset-porch": "^1.0.1",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the dep on babel-preset-porch now?

"babel-preset-react-app": "^1.0.0",
"babel-register": "^6.11.6",
"bunyan": "^1.8.5",
"bunyan-prettystream": "^0.1.3",
Expand Down
290 changes: 132 additions & 158 deletions src/gitlab.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,193 +61,167 @@ export default class GitLab {
this.org = org;
}

fetchRepo = log(({ repo, logger }) => {
logger.trace(`fetchRepo ${repo}`);

return Q.fcall(() => (
this.fetchRepos({ logger })
)).then(repos => (
repos.find(({ name }) => name === repo)
)).finally(() => {
logger.trace(`fetchRepo ${repo} complete`);
});
fetchRepo = log(async ({ repo, logger }) => {
logger.trace('fetchRepo');
const repos = await this.fetchRepos({ logger });
return repos.find(({ name }) => name === repo);
});

fetchRepos = log(({ logger }) => {
fetchRepos = log(async ({ logger }) => {
logger.trace('fetchRepos');
return Q.fcall(() => (
this.paginate({
cached: true,
uri: '/projects'
})
)).then(repos => (
repos.filter(({ namespace: { name }}) => name === this.org)
)).tap(repos => (
logger.trace(`${repos.length} repos found`)
));
const repos = await this.paginate({
cached: true,
uri: '/projects'
});
return repos.filter(({ namespace: { name }}) => name === this.org);
});

createPackageChangeMarkdown = log(({ base, head, repo, logger }) => {
createPackageChangeMarkdown = log(async ({ base, head, repo, logger }) => {
logger.trace(`createPackageChangeMarkdown ${base} ${head} ${repo}`);

return Q.fcall(() => (
this.fetchRepo({ repo, logger })
)).then(({ id }) => (
this.api({
cached: true,
uri: `/projects/${id}/repository/compare`,
qs: {
from: base,
to: head
}
})
)).then(({ commits }) => ([
const { id: repoId } = await this.fetchRepo({ repo, logger });
const { commits } = await this.api({
cached: true,
uri: `/projects/${repoId}/repository/compare`,
qs: {
from: base,
to: head
}
});
return [
'### Diff',
`[${base}...${head}](https://${this.host}/${this.org}/${repo}/compare/${base}...${head})`,
'### Commits',
commits.map(({
id,
id: commitId,
author_name: authorName,
title
}) => {
const strippedTitle = title.replace(' [ci skip]', '').replace(' [skip ci]', '');
return `- ${authorName} - [${strippedTitle}](https://${this.host}/${this.org}/${repo}/commit/${id})`; // eslint-disable-line camelcase
return `- ${authorName} - [${strippedTitle}](https://${this.host}/${this.org}/${repo}/commit/${commitId})`; // eslint-disable-line camelcase
}).reverse().join('\n')
].join('\n\n')));
].join('\n\n');
});

fetchDependantRepos = log(({ packageName, logger }) => {
fetchDependantRepos = log(async ({ packageName, logger }) => {
logger.trace(`fetchDependantRepos ${packageName}`);

return Q.fcall(() => (
this.fetchRepos({ logger })
)).then(repos => (
filter(repos, ({ id }) => (
Q.fcall(() => (
this.api({
cached: true,
uri: `/projects/${id}/repository/blobs/master`,
qs: {
filepath: 'package.json'
}
})
)).then(({ dependencies = {}, devDependencies = {}, peerDependencies = {} }) => (
const repos = await this.fetchRepos({ logger });
return filter(repos, async ({ id }) => {
try {
const {
dependencies = {},
devDependencies = {},
peerDependencies = {}
} = await this.api({
cached: true,
uri: `/projects/${id}/repository/blobs/master`,
qs: {
filepath: 'package.json'
}
});
return (
dependencies.hasOwnProperty(packageName) ||
devDependencies.hasOwnProperty(packageName) ||
peerDependencies.hasOwnProperty(packageName)
)).catch(() => false)
))
));
);
} catch (err) {
return false;
}
});
});

createMergeRequest = log(({ body, title, head, repo, accept, logger }) => {
createMergeRequest = log(async ({ body, title, head, repo, accept, logger }) => {
logger.trace(`createMergeRequest ${title}, ${head}, ${repo}, ${accept}`);

return Q.fcall(() => (
this.fetchRepo({ repo, logger })
)).then(({ id }) => (
Q.fcall(() => (
this.paginate({
uri: `/projects/${id}/merge_requests`,
qs: {
state: 'opened'
}
})
)).then(mergeRequests => (
mergeRequests.filter(({
target_branch: targetBranch,
source_branch: sourceBranch
}) => (
targetBranch === 'master' &&
sourceBranch === head
))
)).then(mrs => {
if (!!mrs.length) {
assert.equal(mrs.length, 1, `${head} not found`);

const [mr] = mrs;
return this.api({
method: 'PUT',
uri: `/projects/${id}/merge_requests/${mr.id}`,
body: {
title,
description: body
}
});
const { id } = await this.fetchRepo({ repo, logger });
const mergeRequests = await this.paginate({
uri: `/projects/${id}/merge_requests`,
qs: {
state: 'opened'
}
});
const mrs = mergeRequests.filter(({
target_branch: targetBranch,
source_branch: sourceBranch
}) => (
targetBranch === 'master' &&
sourceBranch === head
));

assert(mrs.length === 0 || mrs.length === 1);

const mr = mrs.length === 0 ? (
await this.api({
method: 'POST',
uri: `/projects/${id}/merge_requests`,
body: {
source_branch: head,
target_branch: 'master',
title,
description: body
}
return this.api({
method: 'POST',
uri: `/projects/${id}/merge_requests`,
body: {
source_branch: head,
target_branch: 'master',
title,
description: body
}
});
}).then(mr => {
if (accept) {
logger.trace('accepting merge request');

const isIssueOpen = true; // https://gitlab.com/gitlab-org/gitlab-ce/issues/22740

return Q.fcall(() => {
return isIssueOpen && Q.fcall(() => (
this.paginate({
uri: `/projects/${id}/pipelines`
})
)).then(pipelines => (
pipelines.find(({ sha }) => sha === mr.sha)
)).tap(pipeline => {
assert(pipeline, `pipeline for ${mr.sha} required`);
}).tap(() => (
logger.trace('waiting for pipeline')
)).then(pipeline => (
Q.fcall(() => (
// wait for the pipeline to complete
until(() => (
this.api({
uri: `/projects/${id}/pipelines/${pipeline.id}`
}).then(({ status }) => {
logger.trace(`pipeline status ${status}`);
return status !== 'running' && status !== 'pending';
})
), 60000)
)).then(() => {
logger.trace('pipeline no longer running');
// ensure the pipeline was successful
return this.api({
uri: `/projects/${id}/pipelines/${pipeline.id}`
}).then(({ status }) => {
logger.trace(`pipeline status ${status}`);
assert.equal(status, 'success');
});
}).then(() => (
// ensure that the mr hasn't been updated
this.api({
uri: `/projects/${id}/merge_request/${mr.id}`
}).then(({ sha }) => {
logger.trace(`merge request update check ${mr.sha} ${sha}`);
assert.equal(sha, mr.sha);
})
))
));
}).then(() => (
this.api({
method: 'PUT',
uri: `/projects/${id}/merge_requests/${mr.id}/merge`,
body: {
should_remove_source_branch: true,
merge_when_build_succeeds: true
}
}).then(() => {
logger.trace(`merged merge request ${title} ${head} ${repo}`);
})
));
})
) : (
await this.api({
method: 'PUT',
uri: `/projects/${id}/merge_requests/${mrs[0].id}`,
body: {
title,
description: body
}
logger.trace('not auto merging merge request');
return Q.resolve();
})
));
);
if (!accept) {
logger.trace('not auto merging merge request');
return;
}

logger.trace('accepting merge request');

const isIssueOpen = true; // https://gitlab.com/gitlab-org/gitlab-ce/issues/22740
if (isIssueOpen) {
const pipelines = await this.paginate({
uri: `/projects/${id}/pipelines`
});
const pipeline = pipelines.find(({ sha }) => sha === mr.sha);
assert(pipeline, `pipeline for ${mr.sha} required`);

logger.trace('waiting for pipeline to complete');
// wait for the pipeline to complete
await until(() => (
this.api({
uri: `/projects/${id}/pipelines/${pipeline.id}`
}).then(({ status }) => {
logger.trace(`pipeline status ${status}`);
return status !== 'running' && status !== 'pending';
})
), 60000);

logger.trace('pipeline no longer running');
// ensure the pipeline was successful
const { status } = await this.api({
uri: `/projects/${id}/pipelines/${pipeline.id}`
});
logger.trace(`pipeline status ${status}`);
assert.equal(status, 'success');

// ensure that the mr hasn't been updated
const { sha } = await this.api({
uri: `/projects/${id}/merge_request/${mr.id}`
});
logger.trace(`merge request update check ${mr.sha} ${sha}`);
assert.equal(sha, mr.sha);
}

await this.api({
method: 'PUT',
uri: `/projects/${id}/merge_requests/${mr.id}/merge`,
body: {
should_remove_source_branch: true,
merge_when_build_succeeds: true
}
});
logger.trace(`merged merge request ${title} ${head} ${repo}`);
});
}
Loading