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

Update references of pmm to Corepack #59

Merged
merged 4 commits into from
Oct 6, 2021
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
22 changes: 11 additions & 11 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,29 @@ Discussion thread: https://github.com/nodejs/node/issues/15244

2. Node would be distributed slightly differently:

- Pmm would be included by Node out of the box.
- Corepack would be included by Node out of the box.

- The full npm package wouldn't be included out of the box anymore (this might be an incremental move, with first a major version shipping pmm + npm, and the next one discarding npm).
- The full npm package wouldn't be included out of the box anymore (this might be an incremental move, with first a major version shipping Corepack + npm, and the next one discarding npm).

- **However**, the Node distribution would include jump binaries for all three main package managers (`yarn`, `npm`, and `pnpm`) that would simply delegate to `pmm <package manager name>`. Pmm would then handle the install logic by following the logic described in later sections.
- **However**, the Node distribution would include jump binaries for all three main package managers (`yarn`, `npm`, and `pnpm`) that would simply delegate to `corepack <package manager name>`. Corepack would then handle the install logic by following the logic described in later sections.

- Pmm could potentially be distributed as a Node subcommand rather than a standalone binary. In this case, commands in this document (such as `pmm install <name@version>`) would be replaced by `node --pmm install <name@version>` (or any other variant).
- Corepack could potentially be distributed as a Node subcommand rather than a standalone binary. In this case, commands in this document (such as `corepack install <name@version>`) would be replaced by `node --corepack install <name@version>` (or any other variant).

3. Regular users would keep using the `yarn` / `npm` / `pnpm` global binaries just like they are used to. The one difference is that the package manager implementations would be lazily downloaded, without having to be manually installed (because the global jumpers would be included in the Node distribution, cf previous point).

- Projects that don't list the `engines.pm` field would allow any package manager, and Pmm would install them based on predefined versions. Those versions will be frozen in time within Pmm itself to "known good values". For example, the default npm version could be 6.14.5, and the default Yarn one 1.22.4. Users that would want to upgrade to higher versions would just have to update the `engines.pm` field (cf next section).
- Projects that don't list the `engines.pm` field would allow any package manager, and Corepack would install them based on predefined versions. Those versions will be frozen in time within Corepack itself to "known good values". For example, the default npm version could be 6.14.5, and the default Yarn one 1.22.4. Users that would want to upgrade to higher versions would just have to update the `engines.pm` field (cf next section).

4. Project authors would most of the time only have to care about the binaries as well, but they would be able to upgrade package manager versions simply by changing the versions set in the `engines.pm` field.

- Pmm could reasonably provide some kind of basic CLI interface to select a version to upgrade to in a few keystrokes (similar to what `emsdk` does for the [emscripten toolchain](https://github.com/emscripten-core/emsdk#how-do-i-check-for-updates-to-the-emscripten-sdk), or what [nvm](https://github.com/nvm-sh/nvm) does for Node releases).
- Corepack could reasonably provide some kind of basic CLI interface to select a version to upgrade to in a few keystrokes (similar to what `emsdk` does for the [emscripten toolchain](https://github.com/emscripten-core/emsdk#how-do-i-check-for-updates-to-the-emscripten-sdk), or what [nvm](https://github.com/nvm-sh/nvm) does for Node releases).

5. Docker users would follow a similar workflow to other users; the default image would run network queries to install the right package manager for the project being installed.

- However, users with strong offline requirements would be able to run the `pmm install <name@version>` command when preparing their images. It would ensure that the requested package manager is made available for later use.
- However, users with strong offline requirements would be able to run the `corepack install <name@version>` command when preparing their images. It would ensure that the requested package manager is made available for later use.

- Network access could be disabled entirely by setting `PMM_ENABLE_NETWORK=0` in the environmen - Pmm would then only use the package managers that got installed by prior `pmm install` calls.
- Network access could be disabled entirely by setting `COREPACK_ENABLE_NETWORK=0` in the environment - Corepack would then only use the package managers that got installed by prior `corepack install` calls.

6. Package manager maintainers would submit a PR to the Node repository each time they wish for a new version to be made available through Pmm (can be easily automated using a GitHub Action on each of our repositories). Merging the PR would instantly make the new version available to Node users (once they upgrade).
6. Package manager maintainers would submit a PR to the Node repository each time they wish for a new version to be made available through Corepack (can be easily automated using a GitHub Action on each of our repositories). Merging the PR would instantly make the new version available to Node users (once they upgrade).

## How does it work?

Expand Down Expand Up @@ -70,8 +70,8 @@ Nothing would change in the context of this particular proposal. Npm would keep

While npm is favored by the majority of the ecosystem, a significant portion decided to use different tools. Their use cases deserve to be heard rather than be discarded simply because a slightly higher percentage of users happens not to directly benefit from it. Additionally, keeping powers balanced is important - even more so given that npm is a corporate entity with little oversight.

From the npm perspective, a project such as Pmm would also have its benefits: projects regularly break when upgrading from one Node version to another because of npm being upgraded as well. By pinning the package manager version, they would ensure that their users only upgrade when they are ready to, decreasing accidental frustration.
From the npm perspective, a project such as Corepack would also have its benefits: projects regularly break when upgrading from one Node version to another because of npm being upgraded as well. By pinning the package manager version, they would ensure that their users only upgrade when they are ready to, decreasing accidental frustration.

## Known issues

- The `pnpx` and `npx` binaries can only be called from within pnpm and npm projects, respectively. This is because otherwise we cannot infer the package manager version from the local manifest, as it would list another package manager instead. Fixing that is possible if we include "global installs" features inside pmm (so that we would fallback to the global `npx` in those circumstances). It seemed out of scope for the initial prototype, but we certainly can discuss it in an issue.
- The `pnpx` and `npx` binaries can only be called from within pnpm and npm projects, respectively. This is because otherwise we cannot infer the package manager version from the local manifest, as it would list another package manager instead. Fixing that is possible if we include "global installs" features inside corepack (so that we would fallback to the global `npx` in those circumstances). It seemed out of scope for the initial prototype, but we certainly can discuss it in an issue.
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ RUN rm -rf /opt/node/lib /opt/node/bin/npm /opt/node/bin/npx
ENV PATH="/opt/node/bin:$PATH"
RUN which node && node --version

RUN wget https://github.com/arcanis/pmm/archive/master.tar.gz -O - | tar -xz --strip-components=1 -C /opt/corepack && cd /opt/corepack && node ./.yarn/releases/yarn-*.js build
RUN wget https://github.com/nodejs/corepack/archive/master.tar.gz -O - | tar -xz --strip-components=1 -C /opt/corepack && cd /opt/corepack && node ./.yarn/releases/yarn-*.js build

ENV PATH="/opt/corepack/shims:$PATH"
10 changes: 5 additions & 5 deletions sources/Engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import semver from 'semver';
import defaultConfig from '../config.json';

import * as folderUtils from './folderUtils';
import * as pmmUtils from './pmmUtils';
import * as corepackUtils from './corepackUtils';
import * as semverUtils from './semverUtils';
import {SupportedPackageManagers, SupportedPackageManagerSet} from './types';
import {Config, Descriptor, Locator} from './types';
Expand Down Expand Up @@ -111,7 +111,7 @@ export class Engine {
if (typeof range === `undefined`)
throw new Error(`Assertion failed: Specified resolution (${locator.reference}) isn't supported by any of ${ranges.join(`, `)}`);

const installedLocation = await pmmUtils.installVersion(folderUtils.getInstallFolder(), locator, {
const installedLocation = await corepackUtils.installVersion(folderUtils.getInstallFolder(), locator, {
spec: definition.ranges[range],
});

Expand All @@ -135,7 +135,7 @@ export class Engine {
const ranges = Object.keys(definition.ranges);
const tagRange = ranges[ranges.length - 1];

const tags = await pmmUtils.fetchAvailableTags(definition.ranges[tagRange].registry);
const tags = await corepackUtils.fetchAvailableTags(definition.ranges[tagRange].registry);
if (!Object.prototype.hasOwnProperty.call(tags, descriptor.range))
throw new UsageError(`Tag not found (${descriptor.range})`);

Expand All @@ -147,7 +147,7 @@ export class Engine {

// If a compatible version is already installed, no need to query one
// from the remote listings
const cachedVersion = await pmmUtils.findInstalledVersion(folderUtils.getInstallFolder(), finalDescriptor);
const cachedVersion = await corepackUtils.findInstalledVersion(folderUtils.getInstallFolder(), finalDescriptor);
if (cachedVersion !== null && useCache)
return {name: finalDescriptor.name, reference: cachedVersion};

Expand All @@ -156,7 +156,7 @@ export class Engine {
});

const tagResolutions = await Promise.all(candidateRangeDefinitions.map(async range => {
return [range, await pmmUtils.fetchAvailableVersions(definition.ranges[range].registry)] as const;
return [range, await corepackUtils.fetchAvailableVersions(definition.ranges[range].registry)] as const;
}));

// If a version is available under multiple strategies (for example if
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions sources/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {EnableCommand} from './command
import {HydrateCommand} from './commands/Hydrate';
import {PrepareCommand} from './commands/Prepare';
import * as miscUtils from './miscUtils';
import * as pmmUtils from './pmmUtils';
import * as corepackUtils from './corepackUtils';
import * as specUtils from './specUtils';
import {Locator, SupportedPackageManagers, Descriptor} from './types';

Expand Down Expand Up @@ -82,7 +82,7 @@ async function executePackageManagerRequest({packageManager, binaryName, binaryV
throw new UsageError(`Failed to successfully resolve '${descriptor.range}' to a valid ${descriptor.name} release`);

const installSpec = await context.engine.ensurePackageManager(resolved);
const exitCode = await pmmUtils.runVersion(installSpec, resolved, binaryName, args, context);
const exitCode = await corepackUtils.runVersion(installSpec, resolved, binaryName, args, context);

return exitCode;
}
Expand Down