diff --git a/.gitignore b/.gitignore index fbf81390..2ab9ffd1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ logs npm-debug.log* yarn-debug.log* yarn-error.log* -lerna-debug.log* # Coverage directory generated when running tests with coverage coverage @@ -15,18 +14,20 @@ coverage # Dependencies node_modules/ -# Yarn 3 files +# Yarn files .pnp.* .yarn/* -!.yarn/patches +# This is skipped because we specify the Yarn version in the root package.json +.yarn/releases +# Important that we re-include the plugins directory because we need Backstage's +# official Yarn plugin to simplify managing dependencies for each Backstage +# release. The package.json files are updated to include the special +# "backstage:^" value for version numbers, which will break without the plugin !.yarn/plugins -!.yarn/releases +!.yarn/patches !.yarn/sdks !.yarn/versions -# Node version directives -.nvmrc - # dotenv environment variables file .env .env.test @@ -52,3 +53,6 @@ site # E2E test reports e2e-test-report/ + +# Cache +.cache/ \ No newline at end of file diff --git a/.node-version b/.node-version index a9d08739..829e9737 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -18.19.0 +20.19.0 \ No newline at end of file diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..829e9737 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.19.0 \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 3b5fc9c8..67045642 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,5 +2,4 @@ dist dist-types coverage .vscode -.coder.yaml -app-config.local.yaml \ No newline at end of file +.coder.yaml \ No newline at end of file diff --git a/.yarn/plugins/@yarnpkg/plugin-backstage.cjs b/.yarn/plugins/@yarnpkg/plugin-backstage.cjs new file mode 100644 index 00000000..bbc9b43b --- /dev/null +++ b/.yarn/plugins/@yarnpkg/plugin-backstage.cjs @@ -0,0 +1,9 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-backstage", +factory: function (require) { +"use strict";var plugin=(()=>{var F=Object.create;var v=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var G=Object.getPrototypeOf,I=Object.prototype.hasOwnProperty;var p=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var J=(e,t)=>{for(var r in t)v(e,r,{get:t[r],enumerable:!0})},S=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of N(t))!I.call(e,o)&&o!==r&&v(e,o,{get:()=>t[o],enumerable:!(n=_(t,o))||n.enumerable});return e};var L=(e,t,r)=>(r=e!=null?F(G(e)):{},S(t||!e||!e.__esModule?v(r,"default",{value:e,enumerable:!0}):r,e)),z=e=>S(v({},"__esModule",{value:!0}),e);var ae={};J(ae,{default:()=>se});var P=p("@yarnpkg/core");var w=p("@yarnpkg/core");var W=L(p("assert")),j=p("semver"),y=p("@yarnpkg/fslib");var u=L(p("fs")),g=p("path");function A(e,t){let r=e;for(let n=0;n<1e3;n++){let o=(0,g.resolve)(r,"package.json");if(u.default.existsSync(o)&&t(o))return r;let i=(0,g.dirname)(r);if(i===r)return;r=i}throw new Error(`Iteration limit reached when searching for root package.json at ${e}`)}function K(e){let t=A(e,()=>!0);if(!t)throw new Error(`No package.json found while searching for package root of ${e}`);return t}function Y(e){if(!u.default.existsSync((0,g.resolve)(e,"src")))throw new Error("Tried to access monorepo package root dir outside of Backstage repository");return(0,g.resolve)(e,"../..")}function b(e){let t=K(e),r=u.default.realpathSync(process.cwd()).replace(/^[a-z]:/,s=>s.toLocaleUpperCase("en-US")),n="",o=()=>(n||(n=Y(t)),n),a="",i=()=>(a||(a=A(r,s=>{try{let m=u.default.readFileSync(s,"utf8");return!!JSON.parse(m).workspaces}catch(m){throw new Error(`Failed to parse package.json file while searching for root, ${m}`)}})??r),a);return{ownDir:t,get ownRoot(){return o()},targetDir:r,get targetRoot(){return i()},resolveOwn:(...s)=>(0,g.resolve)(t,...s),resolveOwnRoot:(...s)=>(0,g.resolve)(o(),...s),resolveTarget:(...s)=>(0,g.resolve)(r,...s),resolveTargetRoot:(...s)=>(0,g.resolve)(i(),...s)}}var x="backstage.json";var V=e=>{let t=!1,r;return()=>(t||(r=e(),t=!0),r)};var h=p("@yarnpkg/fslib");var C=()=>h.npath.toPortablePath(b(h.npath.fromPortablePath(h.ppath.cwd())).targetRoot);var k=V(()=>{let e=y.ppath.join(C(),x),t=null;try{t=(0,j.valid)(y.xfs.readJsonSync(e).version),(0,W.default)(t!==null)}catch{throw new Error("Valid version string not found in backstage.json")}return t});var d=p("@yarnpkg/core");var q="https://versions.backstage.io",Q="https://raw.githubusercontent.com/backstage/versions/main";function X(e,t){return new Promise((r,n)=>{let o=setTimeout(()=>{t.aborted||r()},e);t.addEventListener("abort",()=>{clearTimeout(o),n(new Error("Aborted"))})})}async function Z(e,t,r){let n=new AbortController,o=new AbortController,a=e(n.signal).then(s=>(o.abort(),s)),i=X(r,o.signal).then(()=>t(o.signal)).then(s=>(n.abort(),s));return Promise.any([a,i]).catch(()=>a)}async function D(e){let t=encodeURIComponent(e.version),r=e.fetch??fetch,n=e.versionsBaseUrl??q,o=e.gitHubRawBaseUrl??Q,a=await Z(i=>r(`${n}/v1/releases/${t}/manifest.json`,{signal:i}),i=>r(`${o}/v1/releases/${t}/manifest.json`,{signal:i}),500);if(a.status===404)throw new Error(`No release found for ${e.version} version`);if(a.status!==200)throw new Error(`Unexpected response status ${a.status} when fetching release from ${a.url}.`);return a.json()}var c="backstage:";var f=async(e,t)=>{let r=d.structUtils.stringifyIdent(e),n=d.structUtils.parseRange(e.range);if(n.protocol!==c)throw new Error(`Unsupported version protocol in version range "${e.range}" for package ${r}`);if(n.selector!=="^")throw new Error(`Unexpected version selector "${n.selector}" for package ${r}`);let o=k(),i=(await D({version:o,fetch:async s=>{let m=await d.httpUtils.get(s,{configuration:t,jsonResponse:!0});return{status:200,url:s,json:()=>m}}})).packages.find(s=>s.name===r);if(!i)throw new Error(`Package ${r} not found in manifest for Backstage v${o}. This means the specified package is not included in this Backstage release. This may imply the package has been replaced with an alternative - please review the documentation for the package. If you need to continue using this package, it will be necessary to switch to manually managing its version.`);return i.version};var ee=e=>w.structUtils.parseRange(e).protocol===c,te=(e,t,r)=>e!=="dependencies"?e:r.manifest.ensureDependencyMeta(w.structUtils.makeDescriptor(t,"unknown")).optional?"optionalDependencies":e,B=async(e,t)=>{for(let r of["dependencies","devDependencies"]){let n=Array.from(e.manifest.getForScope(r).values()).filter(o=>o.range.startsWith(c));for(let o of n){let a=w.structUtils.stringifyIdent(o);if(w.structUtils.parseRange(o.range).selector!=="^")throw new Error(`Unexpected version range "${o.range}" for dependency on "${a}"`);let s=te(r,o,e);t[s][a]=`^${await f(o,e.project.configuration)}`}}if(["dependencies","devDependencies","optionalDependencies"].some(r=>Object.values(t[r]??{}).some(ee)))throw new Error(`Failed to replace all "backstage:" ranges in manifest for ${t.name}`)};var O=p("@yarnpkg/core");var $=async(e,t)=>{let r=O.structUtils.parseRange(e.range);if(r.protocol!==c)return e;if(r.selector!=="^")throw new Error(`Invalid backstage: version range found: ${e.range}`);return O.structUtils.bindDescriptor(e,{backstage:k(),npm:await f(e,t.configuration)})};var H=p("@yarnpkg/core");var U=async(e,t,r,n)=>{let o=H.structUtils.parseRange(r.range);if(r.scope==="backstage"&&o.protocol!==c){let a=r.range;try{r.range=`${c}^`,await f(r,e.project.configuration),console.info(`Setting ${r.scope}/${r.name} to ${c}^`)}catch{r.range=a}}};var M=p("@yarnpkg/core");var E=async(e,t,r,n)=>{let o=M.structUtils.parseRange(n.range);n.scope==="backstage"&&o.protocol!==c&&console.warn(`${n.name} should be set to "${c}^" instead of "${n.range}". Make sure this change is intentional and not a mistake.`)};var l=p("@yarnpkg/core"),T=p("@yarnpkg/plugin-npm");var R=class e{static protocol=c;supportsDescriptor=t=>t.range.startsWith(e.protocol);async getCandidates(t,r,n){let o=l.structUtils.parseRange(t.range).params?.npm;if(!o||Array.isArray(o))throw new Error(`Missing npm parameter on backstage: range "${t.range}"`);return new T.NpmSemverResolver().getCandidates(l.structUtils.makeDescriptor(t,`npm:^${o}`),r,n)}getResolutionDependencies(t){let r=l.structUtils.parseRange(t.range).params?.npm;if(!r)throw new Error(`Missing npm parameter on backstage: range "${t.range}".`);return{[l.structUtils.stringifyIdent(t)]:l.structUtils.makeDescriptor(t,`npm:^${r}`)}}async getSatisfying(t,r,n,o){let a=t,i=l.structUtils.parseRange(a.range);if(i.protocol===c){let s=i.params?.npm;a=l.structUtils.makeDescriptor(t,`npm:^${s}`)}return new T.NpmSemverResolver().getSatisfying(a,r,n,o)}bindDescriptor=t=>t;supportsLocator=()=>!1;shouldPersistResolution=()=>{throw new Error("Unreachable: BackstageNpmResolver should never persist resolution as it uses npm: protocol")};resolve=async()=>{throw new Error("Unreachable: BackstageNpmResolver should never resolve as it uses npm: protocol")}};var re="\x1B[31;1m",oe="\x1B[0m";P.semverUtils.satisfiesWithPrereleases(P.YarnVersion,"^4.1.1")||(console.error(),console.error(`${re}Unsupported yarn version${oe}: The Backstage yarn plugin only works with yarn ^4.1.1. Please upgrade yarn, or remove this plugin with "yarn plugin remove @yarnpkg/plugin-backstage".`),console.error());var ne={hooks:{afterWorkspaceDependencyAddition:U,afterWorkspaceDependencyReplacement:E,reduceDependency:$,beforeWorkspacePacking:B},resolvers:[R]},se=ne;return z(ae);})(); +return plugin; +} +}; diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 00000000..353f47c3 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1,8 @@ +nodeLinker: node-modules + +plugins: + - checksum: 8af7b3f2d7d19cacc7a3712f871efcb6208ba283a1f532260b0cba80c2cb66ed772b207b5ba41b8c5d64dd8d5e0c0e15bbb445bd14afac491712965211ba027c + path: .yarn/plugins/@yarnpkg/plugin-backstage.cjs + spec: 'https://versions.backstage.io/v1/releases/1.42.5/yarn-plugin' + +yarnPath: .yarn/releases/yarn-4.9.4.cjs diff --git a/app-config.production.yaml b/app-config.production.yaml index 3479324e..eee3c6f3 100644 --- a/app-config.production.yaml +++ b/app-config.production.yaml @@ -5,6 +5,7 @@ app: auth: environment: development providers: + guest: {} github: development: clientId: ${GITHUB_CLIENT_ID} @@ -19,13 +20,16 @@ backend: baseUrl: ${BASE_URL} # The listener can also be expressed as a single : string. In this case we bind to # all interfaces, the most permissive setting. The right value depends on your specific deployment. - listen: ':8080' + listen: ':7007' - # config options: https://node-postgres.com/api/client + # config options: https://node-postgres.com/apis/client database: client: pg connection: - ${DATABASE_URL} + host: ${POSTGRES_HOST} + port: ${POSTGRES_PORT} + user: ${POSTGRES_USER} + password: ${POSTGRES_PASSWORD} # https://node-postgres.com/features/ssl # you can set the sslmode configuration option via the `PGSSLMODE` environment variable # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require) @@ -37,4 +41,20 @@ catalog: # Overrides the default list locations from app-config.yaml as these contain example data. # See https://backstage.io/docs/features/software-catalog/#adding-components-to-the-catalog for more details # on how to get entities into the catalog. - locations: [] + locations: + # Local example data, replace this with your production config, these are intended for demo use only. + # File locations are relative to the backend process, typically in a deployed context, such as in a Docker container, this will be the root + - type: file + target: ./examples/entities.yaml + + # Local example template + - type: file + target: ./examples/template/template.yaml + rules: + - allow: [Template] + + # Local example organizational data + - type: file + target: ./examples/org.yaml + rules: + - allow: [User, Group] diff --git a/app-config.yaml b/app-config.yaml index 6d11a74e..091ce921 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -9,8 +9,8 @@ coder: deployment: accessUrl: https://dev.coder.com oauth: - clientId: ${CODER_OAUTH_CLIENT_ID:-backstage} - clientSecret: ${CODER_OAUTH_CLIENT_SECRET:-change-me} + clientId: ${CODER_OAUTH_CLIENT_ID} + clientSecret: ${CODER_OAUTH_CLIENT_SECRET} backend: # Used for enabling authentication, secret is shared by all backend plugins @@ -76,11 +76,20 @@ techdocs: auth: # see https://backstage.io/docs/auth/ to learn about auth providers - providers: {} + providers: + github: + development: + # It's expected that these will be shadowed via an + # app-config.local.yaml file + clientId: ${AUTH_GITHUB_CLIENT_ID} + clientSecret: ${AUTH_GITHUB_CLIENT_SECRET} + signIn: + resolvers: + - resolver: usernameMatchingUserEntityName + +# see https://backstage.io/docs/features/software-templates/configuration for software template options +# scaffolder: -scaffolder: - # see https://backstage.io/docs/features/software-templates/configuration for software template options - {} catalog: import: entityFilename: catalog-info.yaml @@ -113,3 +122,20 @@ catalog: # target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme-corp.yaml # rules: # - allow: [User, Group] + providers: + github: + coderDemoAppConfiguration: + organization: coder + schedule: + frequency: + minutes: 60 + timeout: + minutes: 15 + +# see https://backstage.io/docs/features/kubernetes/configuration for kubernetes configuration options +# kubernetes: + +# see https://backstage.io/docs/permissions/getting-started for more on the permission framework +permission: + # setting this to `false` will disable permissions + enabled: true diff --git a/backstage.json b/backstage.json index 65900481..6c12971c 100644 --- a/backstage.json +++ b/backstage.json @@ -1,3 +1,3 @@ { - "version": "1.22.1" + "version": "1.42.5" } diff --git a/catalog-info.yaml b/catalog-info.yaml index 2cb2dced..adbb41d5 100644 --- a/catalog-info.yaml +++ b/catalog-info.yaml @@ -1,7 +1,7 @@ apiVersion: backstage.io/v1alpha1 kind: Component metadata: - name: backstage-shell + name: backstage description: An example of a Backstage application. # Example for optional annotations # annotations: diff --git a/examples/entities.yaml b/examples/entities.yaml new file mode 100644 index 00000000..447e8b1f --- /dev/null +++ b/examples/entities.yaml @@ -0,0 +1,41 @@ +--- +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system +apiVersion: backstage.io/v1alpha1 +kind: System +metadata: + name: examples +spec: + owner: guests +--- +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: example-website +spec: + type: website + lifecycle: experimental + owner: guests + system: examples + providesApis: [example-grpc-api] +--- +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-api +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: example-grpc-api +spec: + type: grpc + lifecycle: experimental + owner: guests + system: examples + definition: | + syntax = "proto3"; + + service Exampler { + rpc Example (ExampleMessage) returns (ExampleMessage) {}; + } + + message ExampleMessage { + string example = 1; + }; diff --git a/examples/org.yaml b/examples/org.yaml new file mode 100644 index 00000000..6e38e7f7 --- /dev/null +++ b/examples/org.yaml @@ -0,0 +1,31 @@ +# This YAML follows the format from Backstage's guide on setting up GitHub for +# authentication +# https://backstage.io/docs/getting-started/config/authentication/#adding-a-user +# +# Make sure that the `name` field matches your actual GitHub username, and that +# the `memberOf` field matches actual organizations that have been added to the +# app-config.yaml file. +--- +apiVersion: backstage.io/v1alpha1 +kind: User +metadata: + name: Parkreiner +spec: + memberOf: [coder] +--- +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-user +apiVersion: backstage.io/v1alpha1 +kind: User +metadata: + name: guest +spec: + memberOf: [guests] +--- +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-group +apiVersion: backstage.io/v1alpha1 +kind: Group +metadata: + name: guests +spec: + type: team + children: [] diff --git a/examples/template/content/catalog-info.yaml b/examples/template/content/catalog-info.yaml new file mode 100644 index 00000000..d4ccca42 --- /dev/null +++ b/examples/template/content/catalog-info.yaml @@ -0,0 +1,8 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: ${{ values.name | dump }} +spec: + type: service + owner: user:guest + lifecycle: experimental diff --git a/examples/template/template.yaml b/examples/template/template.yaml new file mode 100644 index 00000000..efb33be8 --- /dev/null +++ b/examples/template/template.yaml @@ -0,0 +1,88 @@ +apiVersion: scaffolder.backstage.io/v1beta3 +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-template +kind: Template +metadata: + name: example-nodejs-template + title: Example Node.js Template + description: An example template for the scaffolder that creates a simple Node.js service +spec: + owner: user:guest + type: service + + # These parameters are used to generate the input form in the frontend, and are + # used to gather input data for the execution of the template. + parameters: + - title: Fill in some steps + required: + - name + properties: + name: + title: Name + type: string + description: Unique name of the component + ui:autofocus: true + ui:options: + rows: 5 + - title: Choose a location + required: + - repoUrl + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com + + # These steps are executed in the scaffolder backend, using data that we gathered + # via the parameters above. + steps: + # Each step executes an action, in this case one templates files into the working directory. + - id: fetch-base + name: Fetch Base + action: fetch:template + input: + url: ./content + values: + name: ${{ parameters.name }} + + # This step publishes the contents of the working directory to GitHub. + # If you or your organization prefer another default branch name over 'main' + # you can change that here. + - id: publish + name: Publish + action: publish:github + input: + description: This is ${{ parameters.name }} + repoUrl: ${{ parameters.repoUrl }} + defaultBranch: 'main' + + # The final step is to register our new component in the catalog. + - id: register + name: Register + action: catalog:register + input: + repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }} + catalogInfoPath: '/catalog-info.yaml' + + # Let's notify the user that the template has completed using the Notification action + - id: notify + name: Notify + action: notification:send + input: + recipients: entity + entityRefs: + - user:default/guest + title: 'Template executed' + info: 'Your template has been executed' + severity: 'normal' + + # Outputs are displayed to the user after a successful execution of the template. + output: + links: + - title: Repository + url: ${{ steps['publish'].output.remoteUrl }} + - title: Open in catalog + icon: catalog + entityRef: ${{ steps['register'].output.entityRef }} diff --git a/lerna.json b/lerna.json deleted file mode 100644 index 529a62fe..00000000 --- a/lerna.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "packages": ["packages/*", "plugins/*"], - "npmClient": "yarn", - "version": "0.1.0", - "$schema": "node_modules/lerna/schemas/lerna-schema.json" -} diff --git a/package.json b/package.json index cef9c62a..7a87b1ca 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "engines": { - "node": "18 || 20" + "node": "20 || 22" }, "scripts": { "dev": "yarn dev-init && concurrently --names \"react,backend\" -c \"green,blue\" \"yarn start\" \"yarn start-backend\"", @@ -23,7 +23,7 @@ "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", - "new": "backstage-cli new --scope internal" + "new": "backstage-cli new" }, "workspaces": { "packages": [ @@ -31,22 +31,31 @@ "plugins/*" ] }, + "dependencies": { + "zod": "^4.1.12" + }, + "dependenciesComents": { + "zod--2025-10-24": "Not used directly, but needed for the zod-validation-error override" + }, "devDependencies": { - "@backstage/cli": "^0.25.1", - "@backstage/e2e-test-utils": "^0.1.0", + "@backstage/cli": "backstage:^", + "@backstage/e2e-test-utils": "backstage:^", "@playwright/test": "^1.32.3", "@spotify/prettier-config": "^12.0.0", "concurrently": "^8.0.0", - "lerna": "^7.3.0", "node-gyp": "^9.0.0", "prettier": "^2.3.2", - "typescript": "~5.2.0" + "typescript": "~5.8.0" }, "resolutions": { "@types/react": "^18", - "@types/react-dom": "^18" + "@types/react-dom": "^18", + "zod-validation-error": "3.5.2" + }, + "resolutionsComments": { + "zod-validation-error--2025-10-24": "This library pushed a breaking change on version 3.5.3, which broke internal Backstage packages when trying to install new dependencies (it uses ^3.4.0). Waiting to see if they'll publish a 3.5.4 to revert the change." }, - "prettier": "@spotify/prettier-config", + "prettier": "@backstage/cli/config/prettier", "lint-staged": { "*.{js,jsx,ts,tsx,mjs,cjs}": [ "eslint --fix", @@ -56,5 +65,5 @@ "prettier --write" ] }, - "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" + "packageManager": "yarn@4.9.4" } diff --git a/packages/app/e2e-tests/app.test.ts b/packages/app/e2e-tests/app.test.ts deleted file mode 100644 index d45bc0db..00000000 --- a/packages/app/e2e-tests/app.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - */ - -import { test, expect } from '@playwright/test'; - -test('App should render the welcome page', async ({ page }) => { - await page.goto('/'); - - await expect(page.getByText('My Company Catalog')).toBeVisible(); -}); diff --git a/packages/app/package.json b/packages/app/package.json index 88ecc88a..35c82e55 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -14,44 +14,46 @@ "lint": "backstage-cli package lint" }, "dependencies": { - "@backstage/app-defaults": "^1.4.7", - "@backstage/catalog-model": "^1.4.3", - "@backstage/cli": "^0.25.1", - "@backstage/core-app-api": "^1.11.3", - "@backstage/core-components": "^0.13.10", - "@backstage/core-plugin-api": "^1.8.2", - "@backstage/integration-react": "^1.1.23", - "@backstage/plugin-api-docs": "^0.10.3", - "@backstage/plugin-catalog": "^1.16.1", - "@backstage/plugin-catalog-common": "^1.0.20", - "@backstage/plugin-catalog-graph": "^0.3.3", - "@backstage/plugin-catalog-import": "^0.10.5", - "@backstage/plugin-catalog-react": "^1.9.3", + "@backstage/app-defaults": "backstage:^", + "@backstage/catalog-model": "backstage:^", + "@backstage/cli": "backstage:^", + "@backstage/core-app-api": "backstage:^", + "@backstage/core-components": "backstage:^", + "@backstage/core-plugin-api": "backstage:^", + "@backstage/integration-react": "backstage:^", + "@backstage/plugin-api-docs": "backstage:^", + "@backstage/plugin-catalog": "backstage:^", + "@backstage/plugin-catalog-common": "backstage:^", + "@backstage/plugin-catalog-graph": "backstage:^", + "@backstage/plugin-catalog-import": "backstage:^", + "@backstage/plugin-catalog-react": "backstage:^", "@backstage/plugin-github-actions": "^0.6.10", - "@backstage/plugin-org": "^0.6.19", - "@backstage/plugin-permission-react": "^0.4.19", - "@backstage/plugin-scaffolder": "^1.17.1", - "@backstage/plugin-search": "^1.4.5", - "@backstage/plugin-search-react": "^1.7.5", + "@backstage/plugin-kubernetes": "backstage:^", + "@backstage/plugin-notifications": "backstage:^", + "@backstage/plugin-org": "backstage:^", + "@backstage/plugin-permission-react": "backstage:^", + "@backstage/plugin-scaffolder": "backstage:^", + "@backstage/plugin-search": "backstage:^", + "@backstage/plugin-search-react": "backstage:^", + "@backstage/plugin-signals": "backstage:^", "@backstage/plugin-tech-radar": "^0.6.12", - "@backstage/plugin-techdocs": "^1.9.3", - "@backstage/plugin-techdocs-module-addons-contrib": "^1.1.4", - "@backstage/plugin-techdocs-react": "^1.1.15", - "@backstage/plugin-user-settings": "^0.8.0", - "@backstage/theme": "^0.5.0", + "@backstage/plugin-techdocs": "backstage:^", + "@backstage/plugin-techdocs-module-addons-contrib": "backstage:^", + "@backstage/plugin-techdocs-react": "backstage:^", + "@backstage/plugin-user-settings": "backstage:^", + "@backstage/theme": "backstage:^", + "@backstage/ui": "backstage:^", "@coder/backstage-plugin-coder": "0.0.0", "@coder/backstage-plugin-devcontainers-react": "0.0.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", - "history": "^5.0.0", "react": "^18.0.2", "react-dom": "^18.0.2", "react-router": "^6.3.0", - "react-router-dom": "^6.3.0", - "react-use": "^17.2.4" + "react-router-dom": "^6.3.0" }, "devDependencies": { - "@backstage/test-utils": "^1.4.7", + "@backstage/test-utils": "backstage:^", "@playwright/test": "^1.32.3", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", diff --git a/packages/app/public/index.html b/packages/app/public/index.html index fc758eee..18da7c47 100644 --- a/packages/app/public/index.html +++ b/packages/app/public/index.html @@ -6,7 +6,7 @@