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

Fix parsing error when retrieving workspace members #114

Merged
merged 2 commits into from
May 2, 2024
Merged
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
83 changes: 26 additions & 57 deletions dist/index.js

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

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "release-pr",
"publish": false,
"version": "2.1.0",
"version": "2.1.1",
"description": "",
"main": "lib/main.js",
"scripts": {
Expand Down
111 changes: 42 additions & 69 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,27 +175,27 @@ async function findCrates({
}
}

async function runCargoRelease(
crates: CrateDetails[],
version: string,
branchName: string
): Promise<string> {
debug('checking for presence of cargo-release');
if (!(await toolExists('cargo-release'))) {
warning('cargo-release is not available, attempting to install it');
async function installToolIfNotExists(tool: string): Promise<void> {
debug(`checking for presence of ${tool}`);
if (!(await toolExists(tool))) {
warning(`${tool} is not available, attempting to install it`);

if (await toolExists('cargo-binstall')) {
info('trying to install cargo-release with cargo-binstall');
await execAndSucceed('cargo', [
'binstall',
'--no-confirm',
'cargo-release'
]);
info(`trying to install ${tool} with cargo-binstall`);
await execAndSucceed('cargo', ['binstall', '--no-confirm', tool]);
} else {
info('trying to install cargo-release with cargo-install');
await execAndSucceed('cargo', ['install', 'cargo-release']);
info(`trying to install ${tool} with cargo-install`);
await execAndSucceed('cargo', ['install', tool]);
}
}
}

async function runCargoRelease(
crates: CrateDetails[],
version: string,
branchName: string
): Promise<string> {
await installToolIfNotExists('cargo-release');

debug('running cargo release');
const workspaceRoot: string = JSON.parse(
Expand Down Expand Up @@ -488,16 +488,21 @@ function realpath(path: string): string {
return resolve(workdir, normalize(path));
}

type WorkspaceMemberString = `${string} ${string} (${string})`;
interface WorkspaceMember {
name: string;
version: string;
location: string;
private: boolean;
}

async function pkgid(crate: CrateArgs): Promise<CrateDetails[]> {
// we actually use cargo-metadata so it works without a Cargo.lock
// and equally well for single crates and workspace crates, but the
// API is unchanged from original, like if this was pkgid.
await installToolIfNotExists('cargo-workspaces');

const pkgs: WorkspaceMemberString[] = JSON.parse(
await execWithOutput('cargo', ['metadata', '--format-version=1'])
)?.workspace_members;
const pkgs: CrateDetails[] = (
JSON.parse(
await execWithOutput('cargo', ['workspaces', 'list', '--json'])
) as WorkspaceMember[]
).map(({name, version, location}) => ({name, version, path: location}));
debug(`got workspace members: ${JSON.stringify(pkgs)}`);

// only bother looping if we're searching for something
Expand All @@ -510,20 +515,15 @@ async function pkgid(crate: CrateArgs): Promise<CrateDetails[]> {
debug(`realpath of crate.path: ${cratePath}`);

for (const pkg of pkgs) {
const parsed = parseWorkspacePkg(pkg);
if (!parsed) continue;

if (
(crate.name && crate.name === parsed.name) ||
(cratePath && cratePath === parsed.path)
(crate.name && crate.name === pkg.name) ||
(cratePath && cratePath === pkg.path)
)
return [parsed];
return [pkg];
}
} else if (pkgs.length === 1) {
info('only one crate in workspace, assuming that is it');
const parsed = parseWorkspacePkg(pkgs[0]);
if (!parsed) throw new Error('no good crate found');
return [parsed];
return pkgs;
} else {
if (!crate.releaseAll) {
throw new Error(
Expand All @@ -537,21 +537,18 @@ async function pkgid(crate: CrateArgs): Promise<CrateDetails[]> {
let previousVersion = null;

for (const pkg of pkgs) {
const p = parseWorkspacePkg(pkg);
if (p) {
// ensure that all packages in the workspace have the same version
if (!previousVersion) {
previousVersion = p.version;
} else {
if (p.version !== previousVersion) {
throw new Error(
`multiple crates with different versions: crate=${p.name} version=${p.version} expected=${previousVersion}`
);
}
// ensure that all packages in the workspace have the same version
if (!previousVersion) {
previousVersion = pkg.version;
} else {
if (pkg.version !== previousVersion) {
throw new Error(
`multiple crates with different versions: crate=${pkg.name} version=${pkg.version} expected=${previousVersion}`
);
}

parsed.push(p);
}

parsed.push(pkg);
}

if (!parsed.length) throw new Error('no good crates found');
Expand All @@ -560,27 +557,3 @@ async function pkgid(crate: CrateArgs): Promise<CrateDetails[]> {

throw new Error('no matching crate found');
}

function parseWorkspacePkg(pkg: string): CrateDetails | null {
debug(`parsing workspace package: "${pkg}"`);
const split = pkg.match(/^(\S+) (\S+) \(path\+(file:[/]{2}.+)\)$/);
if (!split) {
warning(`could not parse package format: "${pkg}", skipping`);
return null;
}

const [, name, version, url] = split;

const {protocol, pathname} = new URL(url);
if (protocol !== 'file:')
throw new Error('pkgid is returning a non-local crate');

debug(`got pathname: ${pathname}`);
const path = realpath(pathname);
debug(`got realpath: ${path}`);

debug(`got crate name: ${name}`);
debug(`got crate version: ${version}`);

return {name, path, version};
}
Loading