-
-
Notifications
You must be signed in to change notification settings - Fork 4
Fix repo links in updated changelogs to match auto-changelog
#165
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,20 @@ export { isObject }; | |
*/ | ||
export const debug = createDebug('create-release-branch:impl'); | ||
|
||
/** | ||
* Matches URLs in the formats: | ||
* | ||
* - "https://github.com/OrganizationName/RepoName" | ||
* - "https://github.com/OrganizationName/RepoName.git" | ||
*/ | ||
const HTTPS_GITHUB_URL_REGEX = | ||
/^https:\/\/github\.com\/(.+?)\/(.+?)(?:\.git)?$/u; | ||
|
||
/** | ||
* Matches a URL in the format "git@github.com/OrganizationName/RepoName.git". | ||
*/ | ||
const SSH_GITHUB_URL_REGEX = /^git@github\.com:(.+?)\/(.+?)\.git$/u; | ||
|
||
/** | ||
* Type guard for determining whether the given value is an instance of Error. | ||
* For errors generated via `fs.promises`, `error instanceof Error` won't work, | ||
|
@@ -172,3 +186,28 @@ export async function getLinesFromCommand( | |
const { stdout } = await execa(command, args, options); | ||
return stdout.split('\n').filter((value) => value !== ''); | ||
} | ||
|
||
/** | ||
* Converts the given GitHub repository URL to its HTTPS version. | ||
* | ||
* A "GitHub repository URL" looks like one of: | ||
* | ||
* - https://github.com/OrganizationName/RepositoryName | ||
* - git@github.com:OrganizationName/RepositoryName.git | ||
* | ||
* If the URL does not match either of these patterns, an error is thrown. | ||
* | ||
* @param url - The URL to convert. | ||
* @returns The HTTPS URL of the repository, e.g. | ||
* `https://github.com/OrganizationName/RepositoryName`. | ||
*/ | ||
export function convertToHttpsGitHubRepositoryUrl(url: string): string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic is not in
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, I've simplified the original logic to take a full-on regex approach. It seemed that the code wanted to go there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will probably end up copying this back to |
||
const match = | ||
url.match(HTTPS_GITHUB_URL_REGEX) ?? url.match(SSH_GITHUB_URL_REGEX); | ||
|
||
if (match) { | ||
return `https://github.com/${match[1]}/${match[2]}`; | ||
} | ||
|
||
throw new Error(`Unrecognized repository URL: ${url}`); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,25 @@ | ||
import { WriteStream } from 'fs'; | ||
import { resolve } from 'path'; | ||
import { getWorkspaceLocations } from '@metamask/action-utils'; | ||
import { isPlainObject } from '@metamask/utils'; | ||
import { WriteStreamLike, fileExists } from './fs.js'; | ||
import { | ||
Package, | ||
readMonorepoRootPackage, | ||
readMonorepoWorkspacePackage, | ||
updatePackageChangelog, | ||
} from './package.js'; | ||
import { getRepositoryHttpsUrl, getTagNames, restoreFiles } from './repo.js'; | ||
import { getTagNames, restoreFiles } from './repo.js'; | ||
import { SemVer } from './semver.js'; | ||
import { PackageManifestFieldNames } from './package-manifest.js'; | ||
import { | ||
PackageManifestFieldNames, | ||
UnvalidatedPackageManifest, | ||
} from './package-manifest.js'; | ||
import { ReleaseSpecification } from './release-specification.js'; | ||
import { | ||
convertToHttpsGitHubRepositoryUrl, | ||
getStdoutFromCommand, | ||
} from './misc-utils.js'; | ||
|
||
/** | ||
* The release version of the root package of a monorepo extracted from its | ||
|
@@ -83,13 +91,16 @@ export async function readProject( | |
projectDirectoryPath: string, | ||
{ stderr }: { stderr: WriteStreamLike }, | ||
): Promise<Project> { | ||
const repositoryUrl = await getRepositoryHttpsUrl(projectDirectoryPath); | ||
const tagNames = await getTagNames(projectDirectoryPath); | ||
const rootPackage = await readMonorepoRootPackage({ | ||
packageDirectoryPath: projectDirectoryPath, | ||
projectDirectoryPath, | ||
projectTagNames: tagNames, | ||
}); | ||
const repositoryUrl = await getValidRepositoryUrl( | ||
rootPackage.unvalidatedManifest, | ||
projectDirectoryPath, | ||
); | ||
const releaseVersion = examineReleaseVersion( | ||
rootPackage.validatedManifest.version, | ||
); | ||
|
@@ -132,6 +143,62 @@ export async function readProject( | |
}; | ||
} | ||
|
||
/** | ||
* Returns the https-prefixed GitHub repository URL for the project, so that we | ||
* know how to construct links to releases inside of the changelog. | ||
* | ||
* This URL is obtained by looking at the following sources, in this order: | ||
* | ||
* - `process.env.npm_package_repository_url` (to support MetaMask projects | ||
* which still use NPM or Yarn 1.x) | ||
* - The `repository` field inside of `package.json` (to support most MetaMask | ||
* projects) | ||
* - The URL of the "origin" remote (to support newer projects which for some | ||
* reason do not have a "repository" field) | ||
* | ||
* Note that there is a function in `@metamask/auto-changelog` that offers a | ||
* similar capability, and in fact, this function should match it as closely as | ||
* possible so that when changelogs are updated they also pass | ||
* `@metamask/auto-changelog`'s validation step. | ||
* | ||
* @param packageManifest - The manifest for the package that represents a | ||
* project. | ||
* @param repositoryDirectoryPath - The path to the repository for the project. | ||
* @returns The HTTPS URL of the repository, e.g. | ||
* `https://github.com/OrganizationName/RepositoryName`. | ||
* @throws If the URL obtained via `package.json` or the "origin" remote is in | ||
* in invalid format. | ||
*/ | ||
export async function getValidRepositoryUrl( | ||
packageManifest: UnvalidatedPackageManifest, | ||
repositoryDirectoryPath: string, | ||
): Promise<string> { | ||
// Set automatically by NPM or Yarn 1.x | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although handling NPM or Yarn 1.x projects is not strictly necessary here, because For context the original source for this logic is here: https://github.com/MetaMask/auto-changelog/blob/ef3e86e15b0de7061856a53fd18c4f38e898f5e8/src/repo.ts#L20 |
||
const npmPackageRepositoryUrl = process.env.npm_package_repository_url; | ||
|
||
if (npmPackageRepositoryUrl) { | ||
return convertToHttpsGitHubRepositoryUrl(npmPackageRepositoryUrl); | ||
} | ||
|
||
if (typeof packageManifest.repository === 'string') { | ||
return convertToHttpsGitHubRepositoryUrl(packageManifest.repository); | ||
} | ||
|
||
if ( | ||
isPlainObject(packageManifest.repository) && | ||
typeof packageManifest.repository.url === 'string' | ||
) { | ||
return convertToHttpsGitHubRepositoryUrl(packageManifest.repository.url); | ||
} | ||
|
||
const gitConfigUrl = await getStdoutFromCommand( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that most of our projects ought to have a I tracked down the original source for this logic, and it comes from here: MetaMask/action-monorepo-release-pr@af8d750#diff-b2d6c9ae0590887f3d213032d057be61bd3e628650fb7ba99391bdc84587e454R25 |
||
'git', | ||
['config', '--get', 'remote.origin.url'], | ||
{ cwd: repositoryDirectoryPath }, | ||
); | ||
return convertToHttpsGitHubRepositoryUrl(gitConfigUrl); | ||
} | ||
|
||
/** | ||
* Updates the changelog files of all packages that have changes since latest release to include those changes. | ||
* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests are updated because there's now an extra
repository
field inpackage.json
. That isn't really relevant to these tests, so I've simplified the assertions to only considername
andversion
.