yarn-plugin: add initial version of plugin
Signed-off-by: MT Lewis <mtlewis@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
|
||||
@@ -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.**
|
||||
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user