yarn-plugin: add initial version of plugin

Signed-off-by: MT Lewis <mtlewis@users.noreply.github.com>
This commit is contained in:
MT Lewis
2024-04-09 21:12:35 +01:00
parent 3b086b0020
commit eaa7500130
7 changed files with 1289 additions and 47 deletions
+1
View File
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
+12
View File
@@ -0,0 +1,12 @@
# yarn-plugin-backstage
This yarn plugin adds a `backstage:` version protocol to yarn, which replaces
specific version ranges for `@backstage/` packages. The recommended mode of use
is to set all versions strings to `backstage:*` in package.json, which causes
all versions to be resolved based on the version of Backstage specified in
`backstage.json`. This ensures that all `@backstage/` packages always correspond
to a single release, and removes the need for `package.json` files
to change when upgrading to a new release.
**This plugin is still under active development, and requires some further
testing before we recommend it for general use.**
+10
View File
@@ -0,0 +1,10 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: yarn-plugin-backstage
title: yarn-plugin-backstage
description: Yarn plugin for working with Backstage monorepos
spec:
lifecycle: experimental
type: backstage-node-library
owner: maintainers
+42
View File
@@ -0,0 +1,42 @@
{
"name": "yarn-plugin-backstage",
"description": "Yarn plugin for working with Backstage monorepos",
"version": "0.0.0",
"private": true,
"backstage": {
"role": "node-library"
},
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/yarn-plugin"
},
"keywords": [
"backstage"
],
"license": "Apache-2.0",
"main": "./src/index.ts",
"scripts": {
"build": "builder build plugin",
"lint": "backstage-cli package lint",
"test": "backstage-cli package test",
"clean": "backstage-cli package clean",
"start": "nodemon --"
},
"dependencies": {
"@backstage/release-manifests": "workspace:^",
"@yarnpkg/core": "^4.0.3",
"@yarnpkg/fslib": "^3.0.2"
},
"devDependencies": {
"@backstage/cli": "workspace:^",
"@yarnpkg/builder": "^4.0.0",
"nodemon": "^3.0.1"
},
"nodemonConfig": {
"watch": "./src",
"exec": "builder build plugin",
"ext": "ts"
}
}
+23
View File
@@ -0,0 +1,23 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Plugin } from '@yarnpkg/core';
import { BackstageResolver } from './resolver/BackstageResolver';
const plugin: Plugin = {
resolvers: [BackstageResolver],
};
export default plugin;
@@ -0,0 +1,86 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
structUtils,
Descriptor,
Locator,
Package,
Resolver,
} from '@yarnpkg/core';
import { xfs, npath } from '@yarnpkg/fslib';
import { getManifestByVersion } from '@backstage/release-manifests';
export class BackstageResolver implements Resolver {
static protocol = `backstage:`;
supportsDescriptor = (descriptor: Descriptor) =>
descriptor.range.startsWith(BackstageResolver.protocol);
shouldPersistResolution = () => true;
bindDescriptor(descriptor: Descriptor): Descriptor {
if (descriptor.range === `${BackstageResolver.protocol}*`) {
const backstageJson = xfs.readJsonSync(
npath.toPortablePath('./backstage.json'),
);
return structUtils.makeDescriptor(
descriptor,
`backstage:${backstageJson.version}`,
);
}
return descriptor;
}
async getCandidates(descriptor: Descriptor): Promise<Locator[]> {
const backstageVersion = descriptor.range.replace(
BackstageResolver.protocol,
'',
);
const manifest = await getManifestByVersion({ version: backstageVersion });
const ident = structUtils.stringifyIdent(descriptor);
const manifestEntry = manifest.packages.find(
candidate => candidate.name === ident,
);
if (!manifestEntry) {
throw new Error(`Package ${ident} not found in manifest`);
}
return [
structUtils.makeLocator(descriptor, `npm:${manifestEntry.version}`),
];
}
supportsLocator = () => false;
getResolutionDependencies = () => ({});
async getSatisfying(): Promise<{ locators: Locator[]; sorted: boolean }> {
// Candidate versions produced by this resolver always use the `npm:`
// protocol, so this function will never be called.
throw new Error('Unreachable');
}
async resolve(): Promise<Package> {
// Once transformed into locators (through getCandidates), the versions are
// resolved by the NpmSemverResolver
throw new Error(`Unreachable`);
}
}
+1115 -47
View File
File diff suppressed because it is too large Load Diff