Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor mergify APIs #1766

Closed
wants to merge 4 commits into from
Closed
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 .gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .projenrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ project.vscode.launchConfiguration.addConfiguration({
outFiles: ["${workspaceFolder}/lib/**/*.js"],
});

project.github.mergify.addRule({
project.autoMerge.mergify.addRule({
name: "Label core contributions",
actions: {
label: {
Expand Down
227 changes: 93 additions & 134 deletions docs/api/API.md

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions docs/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ const project = new javascript.NodeProject({
});
```

## Automatic Merging
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like this doc is missing a code snippet or two. I feel like there should be an example for configuring automatic merging as well as what to do if you want to configure Mergify in your project for something else.


Automatic merging can be configured through the `autoMerge` and
`autoMergeOptions` fields on most default projects, or by directly creating an
`AutoMerge` component in your project. Currently this uses
[Mergify](https://mergify.com/), and expects it to be installed on your GitHub
repository for it to work. (Stay tuned for more ways of supporting auto
merging!)

To access the underlying `Mergify` configuration, you can use
`project.autoMerge.mergify`. See `AutoMerge` and `Mergify` in the API reference
for a full list of available options and methods.

## Workflows

TODO
Expand Down
20 changes: 9 additions & 11 deletions src/github/auto-merge.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component } from "../component";
import { GitHub } from "./github";
import { Mergify } from "./mergify";

export interface AutoMergeOptions {
/**
Expand All @@ -18,22 +19,21 @@ export interface AutoMergeOptions {
/**
* Sets up mergify to merging approved pull requests.
*
* If `buildJob` is specified, the specified GitHub workflow job ID is required
* to succeed in order for the PR to be merged.
*
* `approvedReviews` specified the number of code review approvals required for
* the PR to be merged.
*/
export class AutoMerge extends Component {
/**
* Mergify configuration for this project.
*/
public readonly mergify: Mergify;

private readonly lazyConditions = new Array<IAddConditionsLater>();

constructor(github: GitHub, options: AutoMergeOptions = {}) {
super(github.project);

const mergify = github.mergify;
if (!mergify) {
throw new Error("auto merging requires mergify to be enabled");
}
this.mergify = new Mergify(github);

const blockingLabels = options.blockingLabels ?? ["do-not-merge"];
const blockingCondition = blockingLabels?.length
Expand Down Expand Up @@ -63,18 +63,16 @@ export class AutoMerge extends Component {
this.addConditions(`#approved-reviews-by>=${approvedReviews}`);
this.addConditions(...blockingCondition);

mergify.addRule({
this.mergify.addRule({
name: "Automatic merge on approval and successful build",
actions: mergeAction,
conditions: (() => this.renderConditions()) as any,
});

mergify.addQueue({
this.mergify.addQueue({
name: "default",
conditions: (() => this.renderConditions()) as any,
});

this.project.addPackageIgnore("/.mergify.yml");
}

/**
Expand Down
44 changes: 22 additions & 22 deletions src/github/github-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import { Project, ProjectOptions, ProjectType } from "../project";
import { SampleReadme, SampleReadmeProps } from "../readme";
import { DevContainer, VsCode } from "../vscode";
import { AutoApprove, AutoApproveOptions } from "./auto-approve";
import { AutoMergeOptions } from "./auto-merge";
import { AutoMerge, AutoMergeOptions } from "./auto-merge";
import { GitHub, GitHubOptions } from "./github";
import { GithubCredentials } from "./github-credentials";
import { MergifyOptions } from "./mergify";
import { Stale, StaleOptions } from "./stale";

/**
Expand Down Expand Up @@ -46,22 +45,6 @@ export interface GitHubProjectOptions extends ProjectOptions {
*/
readonly githubOptions?: GitHubOptions;

/**
* Whether mergify should be enabled on this repository or not.
*
* @default true
* @deprecated use `githubOptions.mergify` instead
*/
readonly mergify?: boolean;

/**
* Options for mergify
*
* @default - default options
* @deprecated use `githubOptions.mergifyOptions` instead
*/
readonly mergifyOptions?: MergifyOptions;

/**
* Add a VSCode development environment (used for GitHub Codespaces)
*
Expand Down Expand Up @@ -97,8 +80,17 @@ export interface GitHubProjectOptions extends ProjectOptions {
readonly autoApproveOptions?: AutoApproveOptions;

/**
* Configure options for automatic merging on GitHub. Has no effect if
* `github.mergify` is set to false.
* Enable automatic merging pull requests on GitHub. Currently, this only
* supports using Mergify to merge pull requests. Has no effect if `github` is
* set to false.
*
* @default true
*/
readonly autoMerge?: boolean;

/**
* Configure options for automatic merging pull requests on GitHub. Has no
* effect if `autoMerge` is set to false or `github` is set to false.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not too familiar with projen customs, but should we simply error out if autoMergeOptions is set and autoMerge or github is set to false? Seems odd to just ignore this property. Same goes for autoMerge

*
* @default - see defaults in `AutoMergeOptions`
*/
Expand Down Expand Up @@ -181,6 +173,11 @@ export class GitHubProject extends Project {
*/
public readonly projectType: ProjectType;

/**
* Auto merging pull requests for this project.
*/
public readonly autoMerge?: AutoMerge;

/**
* Auto approve set up for this project.
*/
Expand All @@ -196,8 +193,6 @@ export class GitHubProject extends Project {
? new GitHub(this, {
projenTokenSecret: options.projenTokenSecret,
projenCredentials: options.projenCredentials,
mergify: options.mergify,
mergifyOptions: options.mergifyOptions,
...options.githubOptions,
})
: undefined;
Expand All @@ -223,6 +218,11 @@ export class GitHubProject extends Project {
);
}

const autoMerge = options.autoMerge ?? true;
if (autoMerge && this.github) {
this.autoMerge = new AutoMerge(this.github, options.autoMergeOptions);
}

const stale = options.stale ?? false;
if (stale && this.github) {
new Stale(this.github, options.staleOptions);
Expand Down
25 changes: 0 additions & 25 deletions src/github/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,11 @@ import { Component } from "../component";
import { Project } from "../project";
import { Dependabot, DependabotOptions } from "./dependabot";
import { GithubCredentials } from "./github-credentials";
import { Mergify, MergifyOptions } from "./mergify";
import { PullRequestTemplate } from "./pr-template";
import { PullRequestLint, PullRequestLintOptions } from "./pull-request-lint";
import { GithubWorkflow } from "./workflows";

export interface GitHubOptions {
/**
* Whether mergify should be enabled on this repository or not.
*
* @default true
*/
readonly mergify?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is a fairly big API transition and we're removing a few properties (esp the non-deprecated ones like these), I feel like we need to have strong migration docs between projen versions for users who are broken.

I think I understand the vision of projen where we have lots of major versions and you don't really need to upgrade projen in your project. But if I'm a die-hard projen user with some ideas on how to set up mergify in an old project (in projen v0.34 for example) and it now doesn't exist when I'm trying to set up a new project (in projen v0.59 or something), I'm going to want to have some docs that tell me what to do now. I don't really know if there's a right way to achieve this though.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess the BREAKING CHANGE comments go into the changelog? but do people actually rely on the changelog for help?

Copy link
Contributor Author

@Chriscbr Chriscbr Apr 18, 2022

Choose a reason for hiding this comment

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

I think putting all breaking changes / migration suggestions in the changelog is probably okay since it's a single source of truth for high-level API changes and it's easy to ctrl+f for some API name. But I agree it's a good idea to link to detailed docs as well. It could also be nice if the docs of any component listed the latest changes / versions of projen it was changed in etc.

We don't generate a single changelog file anywhere right now, so maybe that should be addressed first...


/**
* Options for Mergify.
*
* @default - default options
*/
readonly mergifyOptions?: MergifyOptions;

/**
* Enables GitHub workflows. If this is set to `false`, workflows will not be created.
*
Expand Down Expand Up @@ -72,12 +57,6 @@ export class GitHub extends Component {
return project.components.find(isGitHub);
}

/**
* The `Mergify` configured on this repository. This is `undefined` if Mergify
* was not enabled when creating the repository.
*/
public readonly mergify?: Mergify;

/**
* Are workflows enabled?
*/
Expand Down Expand Up @@ -111,10 +90,6 @@ export class GitHub extends Component {
});
}

if (options.mergify ?? true) {
this.mergify = new Mergify(this, options.mergifyOptions);
}

if (options.pullRequestLint ?? true) {
new PullRequestLint(this, options.pullRequestLintOptions);
}
Expand Down
18 changes: 11 additions & 7 deletions src/javascript/node-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -603,13 +603,17 @@ export class NodeProject extends GitHubProject {
}
}

if (this.github?.mergify && this.buildWorkflow?.buildJobIds) {
this.autoMerge = new AutoMerge(this.github, options.autoMergeOptions);
this.autoMerge.addConditionsLater({
render: () =>
this.buildWorkflow?.buildJobIds.map((id) => `status-success=${id}`) ??
[],
});
if (this.autoMerge) {
this.addPackageIgnore("/.mergify.yml");

if (this.buildWorkflow?.buildJobIds) {
this.autoMerge.addConditionsLater({
render: () =>
this.buildWorkflow?.buildJobIds.map(
(id) => `status-success=${id}`
) ?? [],
});
}
}

const dependabot = options.dependabot ?? false;
Expand Down
3 changes: 3 additions & 0 deletions test/__snapshots__/cleanup.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading