Skip to content

Conversation

@rollyjoel
Copy link
Contributor

@rollyjoel rollyjoel commented Feb 11, 2021

This is a first take at normalizing the configuration options used to
construct GitHub, ReleasePR, and GitHubRelease instances as well as
higher level configuration used by the factory entrypoints to build
them. The principal motivation is to bring the code more inline with
IoC/DI patterns (https://stackoverflow.com/a/3140/13802304)

refactor!: interfaces for constructor options moved to src/index.ts
and signficantly reorganized
refactor!: GitHub constructor: GitHubConstructorOptions
refactor!: GitHubRelease constructor: GitHubReleaseConstructorOptions
refactor!: ReleasePR constructor: ReleasePRConstructorOptions
refactor!: ReleasePR package name handling refactored -
lookupPackageName removed in favor of getPackageName
refactor!: ConventionalCommits constructor takes owner and repo instead
of just repoUrl
refactor!: remove GitHubRelease.labels in favor of ReleasePR.labels

@rollyjoel rollyjoel requested a review from a team as a code owner February 11, 2021 05:22
@google-cla google-cla bot added the cla: yes This human has signed the Contributor License Agreement. label Feb 11, 2021
@codecov
Copy link

codecov bot commented Feb 11, 2021

Codecov Report

Merging #763 (46c7368) into master (c9fbf78) will increase coverage by 0.30%.
The diff coverage is 87.82%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #763      +/-   ##
==========================================
+ Coverage   88.92%   89.22%   +0.30%     
==========================================
  Files          59       60       +1     
  Lines        7690     7753      +63     
  Branches      675      728      +53     
==========================================
+ Hits         6838     6918      +80     
+ Misses        851      834      -17     
  Partials        1        1              
Impacted Files Coverage Δ
src/releasers/index.ts 100.00% <ø> (ø)
src/releasers/ruby-yoshi.ts 26.77% <0.00%> (-0.76%) ⬇️
src/releasers/helm.ts 29.00% <18.75%> (-0.16%) ⬇️
src/releasers/ruby.ts 34.74% <45.45%> (-0.26%) ⬇️
src/releasers/java-yoshi.ts 87.46% <82.35%> (+0.15%) ⬆️
src/bin/release-please.ts 84.86% <86.30%> (+2.96%) ⬆️
src/releasers/php-yoshi.ts 93.10% <91.66%> (+0.10%) ⬆️
src/release-pr.ts 91.77% <97.26%> (+0.34%) ⬆️
src/constants.ts 100.00% <100.00%> (ø)
src/conventional-commits.ts 99.19% <100.00%> (-0.02%) ⬇️
... and 14 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c9fbf78...9a79a64. Read the comment docs.

@rollyjoel rollyjoel marked this pull request as draft February 11, 2021 15:08
@rollyjoel
Copy link
Contributor Author

found some holes in src/factory.ts while manually testing the cli against some example repos I have. Now that the factory has much more responsibility for correctly constructing different pieces it should have much better testing. working on that.

@rollyjoel rollyjoel changed the title Factory overhaul refactor!: IoC/DI to normalize configuration Feb 11, 2021
Copy link

@bcoe bcoe left a comment

Choose a reason for hiding this comment

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

Just a couple initial questions, will give a more thorough review later today.

In general I really like the approach, it seems like you've gone the route that: rather than pulling more functionality into ReleasePR, so that it's available when creating a release, you now have an instance of a ReleasePR in a GithubRelease?

This seems really smart to me.

})
.option('default-branch', {
describe: '',
describe: 'The branch to open release PRs against and tag releases on',
Copy link

Choose a reason for hiding this comment

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

Good catch.

versionFile,
});

return new GitHubRelease({github, releasePR, ...remaining});
Copy link

Choose a reason for hiding this comment

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

I like this approach, this ends up meaning that the GitHub release can use any releaser specific methods on releasePR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

GitHubRelease already relies on a ReleasePR instance for to perform it's one job (run) - this change is simple removing the knowledge of how to construct it (and thus also removing any duplicate constructor options) and centralizing it in case other future classes (aka aggregate) need one too. Same pattern as pulling out the building of a GitHub instance because that was already being duplicated (by ReleasePR)

src/index.ts Outdated
repo: string;
}

// Used by GitHubRelease and ReleasePR Ctor
Copy link

Choose a reason for hiding this comment

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

nit: might spell this out constructor, had to Google the shorthand.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will do. I had to look it up too not that long ago (finally got tired of seeing it everywhere on SO and not really knowing what it mean). I come from python where init is both short and accurate :-)

const cc = new ConventionalCommits({
commits: commits,
githubRepoUrl: this.repoUrl,
owner: this.gh.owner,
Copy link

Choose a reason for hiding this comment

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

Just standardizing on splitting own owner and repo in more places?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the idea is to consider repoUrl as denormalized shorthand user input for factory.ts and that it should be normalized only once into {owner, repo} and everything else inside the release-please codebase should rely on those directly rather than either carry around this copy of the short hand that everyone then has to convert. It would be a different story if different actors converted it differently but they all just use parse-github-repo-url to get the owner and repo.

}
return {
name: this.packageName,
refSafeName: () =>
Copy link

Choose a reason for hiding this comment

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

If I'm understanding refSafeName properly, it codifies dropping the @pkg/ prefix from a branch name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, but I think I'll change it to getComponent() per a discussion with @chingor13

In this refactor I tried to steer away as much as possible from functionality refactoring or re-naming. The one exception is that darned quagmire of (packagePrefix vs packageName) x (set via configuration vs releaser knows how to get it): there was a nasty tangle of responsibility leaking that I needed to cleanup to normalize the configuration. Maybe PackageName.refSafeName() is better named PackageName.getComponent() - that's more inline with the domain vocabulary we've chosen and being safe to use as/in a git ref is just a requirement of a component rather than the name

@bcoe bcoe mentioned this pull request Feb 11, 2021
4 tasks
@rollyjoel rollyjoel force-pushed the factory-overhaul branch 2 times, most recently from 2cb9f20 to e19dc1c Compare February 11, 2021 21:20
Copy link

@bcoe bcoe left a comment

Choose a reason for hiding this comment

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

One question for you, was scratching my head trying to figure out where remaining is assigned (maybe I'm misunderstanding something magic about spread operators).

It also jumped out at me that perhaps label should only be a string during parsing.

choices: getReleaserTypes(),
};
if (defaultType) {
relTypeOptions['default'] = defaultType;
Copy link

Choose a reason for hiding this comment

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

nit: relTypeOptions.default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ug, brain frazzle (when I get tired the python slips back in)

changelogSections,
lastPackageVersion,
versionFile,
...remaining
Copy link

Choose a reason for hiding this comment

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

I seem to be missing where remaining is defined?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't hyperlink to the exact location but search for the string "Rest in Object Destructuring " in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

in this case remaining is whatever is left of the options parameter that wasn't pulled out in the destructuring.

Copy link

Choose a reason for hiding this comment

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

neat, haven't used that pattern.

this.bumpMinorPreMajor = options.bumpMinorPreMajor || false;
this.defaultBranch = options.defaultBranch;
this.fork = !!options.fork;
this.labels = options.label
Copy link

Choose a reason for hiding this comment

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

Feels a bit weird that label starts as a string, that's split, and then we pass it around as an array of strings to the GitHub instance.

We could coerce labels into an array in the CLI, using .coerce and in the GitHub action, and perhaps make labels an array from the factory onwards?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like it. Do you want me to do that in this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm doing it in this PR - and it's leading to another GitHubRelease option culling: that class doesn't need this.labels now that it has a releasePR instance. I hadn't looked closely but it turns out ReleasePR.labels is supposed be the same as GitHubRelease.labels. Back before GitHubRelease had a releaser instance that duplication was necessary, but not anymore


export class Node extends ReleasePR {
async getOpenPROptions(
private pkgJsonContents?: GitHubFileContents;
Copy link

Choose a reason for hiding this comment

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

Is this just an optimization so that we only load once?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah - the original _run code loads the contents at the beginning only once and passes it to the PackageJson Updater as well as sets self.packageName - but now that I've tried to make getPackageName() available potentially prior to any "run" I thought I'd cache it here. But maybe potential caching bugs aren't worth the small cost of an extra API call or two?

const repoUrls = [
`${owner}/${repo}`,
`${owner}/${repo}`,
`https://github.com/${owner}/${repo}.git`,
Copy link

Choose a reason for hiding this comment

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

I appreciate these tests, and that we're so forgiving with the input.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops, I have the same input listed twice. I was just trying to copy some examples from https://github.com/repo-utils/parse-github-repo-url#features

@rollyjoel rollyjoel marked this pull request as ready for review February 12, 2021 00:52
octokitAPIs,
});

const labels = getLabels(label);
Copy link

Choose a reason for hiding this comment

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

Nice, I like this approach.

This is a first take at normalizing the configuration options used to
construct GitHub, ReleasePR, and GitHubRelease instances as well as
higher level configuration used by the factory entrypoints to build
them. The principal motivation is to bring the code more inline with
IoC/DI patterns (https://stackoverflow.com/a/3140/13802304)

refactor!: interfaces for constructor options moved to src/index.ts
and signficantly reorganized
refactor!: GitHub constructor: GitHubConstructorOptions
refactor!: GitHubRelease constructor: GitHubReleaseConstructorOptions
refactor!: ReleasePR constructor: ReleasePRConstructorOptions
refactor!: ReleasePR package name handling refactored -
lookupPackageName removed in favor of getPackageName
refactor!: ConventionalCommits constructor takes owner and repo instead
of just repoUrl
refactor!: remove GitHubRelease.labels in favor of ReleasePR.labels
@rollyjoel rollyjoel changed the title refactor!: IoC/DI to normalize configuration refactor!: normalize configuration across classes Feb 12, 2021
@bcoe bcoe merged commit 44a3fd2 into googleapis:master Feb 12, 2021
@release-please release-please bot mentioned this pull request Feb 12, 2021
@rollyjoel rollyjoel deleted the factory-overhaul branch February 18, 2021 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: yes This human has signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants