From 476bb9411595cda8337353d0dbd6ffd17a95190a Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 19 Jan 2022 10:30:12 +0100 Subject: [PATCH] Initial release manifest package Signed-off-by: Johan Haals --- .changeset/config.json | 4 +- packages/cli/src/commands/index.ts | 5 + packages/cli/src/commands/versions/bump.ts | 27 ++-- packages/cli/src/lib/versioning/packages.ts | 2 +- packages/release-manifest/.eslintrc.js | 5 + packages/release-manifest/CHANGELOG.md | 1 + packages/release-manifest/README.md | 3 + packages/release-manifest/api-report.md | 12 ++ packages/release-manifest/package.json | 41 +++++++ packages/release-manifest/releases/1.0.0 | 115 ++++++++++++++++++ packages/release-manifest/src/index.ts | 21 ++++ .../release-manifest/src/manifest.test.ts | 9 ++ packages/release-manifest/src/manifest.ts | 57 +++++++++ 13 files changed, 293 insertions(+), 9 deletions(-) create mode 100644 packages/release-manifest/.eslintrc.js create mode 100644 packages/release-manifest/CHANGELOG.md create mode 100644 packages/release-manifest/README.md create mode 100644 packages/release-manifest/api-report.md create mode 100644 packages/release-manifest/package.json create mode 100644 packages/release-manifest/releases/1.0.0 create mode 100644 packages/release-manifest/src/index.ts create mode 100644 packages/release-manifest/src/manifest.test.ts create mode 100644 packages/release-manifest/src/manifest.ts diff --git a/.changeset/config.json b/.changeset/config.json index 283caa6ac4..33b69f3f1e 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -6,7 +6,9 @@ "access": "public", "baseBranch": "master", "updateInternalDependencies": "patch", - "ignore": [], + "ignore": [ + "@backstage/release-manifest" + ], "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { "onlyUpdatePeerDependentsWhenOutOfRange": true } diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 2211af1dda..280c90ece8 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -341,6 +341,11 @@ export function registerCommands(program: CommanderStatic) { '--pattern ', 'Override glob for matching packages to upgrade', ) + .option( + '--release-line ', + 'Bump to the latest version of a specific release line', + 'main', + ) .description('Bump Backstage packages to the latest versions') .action(lazy(() => import('./versions/bump').then(m => m.default))); diff --git a/packages/cli/src/commands/versions/bump.ts b/packages/cli/src/commands/versions/bump.ts index 0d7c1cdfae..bb719e7e48 100644 --- a/packages/cli/src/commands/versions/bump.ts +++ b/packages/cli/src/commands/versions/bump.ts @@ -60,7 +60,7 @@ export default async (cmd: Command) => { console.log(`Using custom pattern glob ${pattern}`); } - const findTargetVersion = createVersionFinder(); + const findTargetVersion = createVersionFinder(cmd.releaseLine); // First we discover all Backstage dependencies within our own repo const dependencyMap = await mapDependencies(paths.targetDir, pattern); @@ -284,7 +284,9 @@ export default async (cmd: Command) => { } }; -function createVersionFinder() { +function createVersionFinder(releaseLine = 'latest') { + // The main release line is just an alias for latest + const distTag = releaseLine === 'main' ? 'latest' : releaseLine; const found = new Map(); return async function findTargetVersion(name: string) { @@ -295,12 +297,23 @@ function createVersionFinder() { console.log(`Checking for updates of ${name}`); const info = await fetchPackageInfo(name); - const latest = info['dist-tags'].latest; - if (!latest) { - throw new Error(`No latest version found for ${name}`); + const latestVersion = info['dist-tags'].latest; + if (!latestVersion) { + throw new Error(`No target 'latest' version found for ${name}`); } - found.set(name, latest); - return latest; + if (distTag === 'latest') { + found.set(name, latestVersion); + return latestVersion; + } + const taggedVersion = info['dist-tags'][distTag]; + if (!taggedVersion) { + found.set(name, latestVersion); + return latestVersion; + } + + // Take release from latest of next release is older + found.set(name, targetVersion); + return targetVersion; }; } diff --git a/packages/cli/src/lib/versioning/packages.ts b/packages/cli/src/lib/versioning/packages.ts index 1dabec6032..9f2f2bdc65 100644 --- a/packages/cli/src/lib/versioning/packages.ts +++ b/packages/cli/src/lib/versioning/packages.ts @@ -28,7 +28,7 @@ const DEP_TYPES = [ // Package data as returned by `yarn info` export type YarnInfoInspectData = { name: string; - 'dist-tags': { latest: string }; + 'dist-tags': Record; versions: string[]; time: { [version: string]: string }; }; diff --git a/packages/release-manifest/.eslintrc.js b/packages/release-manifest/.eslintrc.js new file mode 100644 index 0000000000..a86d9806ad --- /dev/null +++ b/packages/release-manifest/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + extends: [ + require.resolve('@backstage/release-manifest/config/eslint.backend'), + ], +}; diff --git a/packages/release-manifest/CHANGELOG.md b/packages/release-manifest/CHANGELOG.md new file mode 100644 index 0000000000..28f83c41cd --- /dev/null +++ b/packages/release-manifest/CHANGELOG.md @@ -0,0 +1 @@ +# @backstage/release-manifest diff --git a/packages/release-manifest/README.md b/packages/release-manifest/README.md new file mode 100644 index 0000000000..ddbeed7dd0 --- /dev/null +++ b/packages/release-manifest/README.md @@ -0,0 +1,3 @@ +# @backstage/release-manifest + +This package provides a mapping between a Backstage release and the packages included in that release. diff --git a/packages/release-manifest/api-report.md b/packages/release-manifest/api-report.md new file mode 100644 index 0000000000..0837e05763 --- /dev/null +++ b/packages/release-manifest/api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/release-manifest" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +// Warning: (ae-missing-release-tag) "releaseManifest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const releaseManifest: { + '@backstage/cli': string; +}; +``` diff --git a/packages/release-manifest/package.json b/packages/release-manifest/package.json new file mode 100644 index 0000000000..d530ac4df0 --- /dev/null +++ b/packages/release-manifest/package.json @@ -0,0 +1,41 @@ +{ + "name": "@backstage/release-manifest", + "description": "Package information for ", + "version": "0.0.0", + "private": false, + "main": "src/index.ts", + "types": "src/index.ts", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/release-manifest" + }, + "keywords": [ + "backstage" + ], + "license": "Apache-2.0", + "scripts": { + "build": "backstage-cli build --outputs cjs,types", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "fs-extra": "^10.0.0" + }, + "devDependencies": { + "@types/jest": "^26.0.7", + "@types/node": "^14.14.32" + }, + "files": [ + "dist" + ] +} diff --git a/packages/release-manifest/releases/1.0.0 b/packages/release-manifest/releases/1.0.0 new file mode 100644 index 0000000000..9480d17aef --- /dev/null +++ b/packages/release-manifest/releases/1.0.0 @@ -0,0 +1,115 @@ +app-defaults=1.0.0 +backend-common=1.0.0 +backend-tasks=1.0.0 +backend-test-utils=1.0.0 +catalog-client=1.0.0 +catalog-model=1.0.0 +cli-common=1.0.0 +cli=1.0.0 +codemods=1.0.0 +config-loader=1.0.0 +config=1.0.0 +core-app-api=1.0.0 +core-components=1.0.0 +core-plugin-api=1.0.0 +create-app=1.0.0 +dev-utils=1.0.0 +errors=1.0.0 +integration-react=1.0.0 +integration=1.0.0 +plugin-airbrake=1.0.0 +plugin-allure=1.0.0 +plugin-analytics-module-ga=1.0.0 +plugin-apache-airflow=1.0.0 +plugin-api-docs=1.0.0 +plugin-app-backend=1.0.0 +plugin-auth-backend=1.0.0 +plugin-azure-devops-backend=1.0.0 +plugin-azure-devops-common=1.0.0 +plugin-azure-devops=1.0.0 +plugin-badges-backend=1.0.0 +plugin-badges=1.0.0 +plugin-bazaar-backend=1.0.0 +plugin-bazaar=1.0.0 +plugin-bitrise=1.0.0 +plugin-catalog-backend-module-ldap=1.0.0 +plugin-catalog-backend-module-msgraph=1.0.0 +plugin-catalog-backend=1.0.0 +plugin-catalog-common=1.0.0 +plugin-catalog-graph=1.0.0 +plugin-catalog-graphql=1.0.0 +plugin-catalog-import=1.0.0 +plugin-catalog-react=1.0.0 +plugin-catalog=1.0.0 +plugin-circleci=1.0.0 +plugin-cloudbuild=1.0.0 +plugin-code-coverage-backend=1.0.0 +plugin-code-coverage=1.0.0 +plugin-config-schema=1.0.0 +plugin-cost-insights=1.0.0 +plugin-explore-react=1.0.0 +plugin-explore=1.0.0 +plugin-firehydrant=1.0.0 +plugin-fossa=1.0.0 +plugin-gcp-projects=1.0.0 +plugin-git-release-manager=1.0.0 +plugin-github-actions=1.0.0 +plugin-github-deployments=1.0.0 +plugin-gitops-profiles=1.0.0 +plugin-gocd=1.0.0 +plugin-graphiql=1.0.0 +plugin-graphql-backend=1.0.0 +plugin-home=1.0.0 +plugin-ilert=1.0.0 +plugin-jenkins-backend=1.0.0 +plugin-jenkins=1.0.0 +plugin-kafka-backend=1.0.0 +plugin-kafka=1.0.0 +plugin-kubernetes-backend=1.0.0 +plugin-kubernetes-common=1.0.0 +plugin-kubernetes=1.0.0 +plugin-lighthouse=1.0.0 +plugin-newrelic-dashboard=1.0.0 +plugin-newrelic=1.0.0 +plugin-org=1.0.0 +plugin-pagerduty=1.0.0 +plugin-permission-backend=1.0.0 +plugin-permission-common=1.0.0 +plugin-permission-node=1.0.0 +plugin-permission-react=1.0.0 +plugin-proxy-backend=1.0.0 +plugin-rollbar-backend=1.0.0 +plugin-rollbar=1.0.0 +plugin-scaffolder-backend-module-cookiecutter=1.0.0 +plugin-scaffolder-backend-module-rails=1.0.0 +plugin-scaffolder-backend-module-yeoman=1.0.0 +plugin-scaffolder-backend=1.0.0 +plugin-scaffolder-common=1.0.0 +plugin-scaffolder=1.0.0 +plugin-search-backend-module-elasticsearch=1.0.0 +plugin-search-backend-module-pg=1.0.0 +plugin-search-backend-node=1.0.0 +plugin-search-backend=1.0.0 +plugin-search=1.0.0 +plugin-sentry=1.0.0 +plugin-shortcuts=1.0.0 +plugin-sonarqube=1.0.0 +plugin-splunk-on-call=1.0.0 +plugin-tech-insights-backend-module-jsonfc=1.0.0 +plugin-tech-insights-backend=1.0.0 +plugin-tech-insights-common=1.0.0 +plugin-tech-insights-node=1.0.0 +plugin-tech-insights=1.0.0 +plugin-tech-radar=1.0.0 +plugin-techdocs-backend=1.0.0 +plugin-techdocs=1.0.0 +plugin-todo-backend=1.0.0 +plugin-todo=1.0.0 +plugin-user-settings=1.0.0 +plugin-xcmetrics=1.0.0 +search-common=1.0.0 +techdocs-common=1.0.0 +test-utils=1.0.0 +theme=1.0.0 +types=1.0.0 +version-bridge=1.0.0 diff --git a/packages/release-manifest/src/index.ts b/packages/release-manifest/src/index.ts new file mode 100644 index 0000000000..099b146e78 --- /dev/null +++ b/packages/release-manifest/src/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2020 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. + */ + +/** + * Contains mapping between Backstage release and package versions. + * + * @packageDocumentation + */ diff --git a/packages/release-manifest/src/manifest.test.ts b/packages/release-manifest/src/manifest.test.ts new file mode 100644 index 0000000000..0c2005d1a8 --- /dev/null +++ b/packages/release-manifest/src/manifest.test.ts @@ -0,0 +1,9 @@ +import { getRelease } from './manifest'; + +describe('Get Packages', () => { + it('should return a list of packages in a release', async () => { + const pkgs = await getRelease('1.0.0'); + console.log(pkgs); + expect(pkgs.size).toBe(2); + }); +}); diff --git a/packages/release-manifest/src/manifest.ts b/packages/release-manifest/src/manifest.ts new file mode 100644 index 0000000000..07e3ec7cb7 --- /dev/null +++ b/packages/release-manifest/src/manifest.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2022 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. + */ + +/** + * Mapping between a Backstage release and individual package versions. + * @public + */ +import { resolvePackagePath } from '@backstage/backend-common'; +import fs from 'fs-extra'; +import path from 'path'; + +const RELEASE_DIR = resolvePackagePath( + '@backstage/release-manifest', + 'releases', +); + +export type ReleaseManifest = { + packages: Map; +}; + +export async function getRelease(version: string): Promise { + const pkgs = new Map(); + try { + const content = await fs.readFile(path.resolve(RELEASE_DIR, `${version}`)); + for (const line of content.toString().split('\n')) { + const [pkg, version] = line.split('='); + pkgs.set(pkg, version); + } + } catch (e) { + throw new Error(`No release found for ${version} version`); + } + return { packages: pkgs }; +} + +export type ReleaseList = { + items: { + version: string; + }[]; +}; + +export async function listReleases(): Promise { + const files = await fs.readdir(RELEASE_DIR); + return { items: files.map(file => ({ version: file })) }; +}