Merge remote-tracking branch 'refs/remotes/origin/master' into serder-workspace
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-node': minor
|
||||
---
|
||||
|
||||
Added `LocationAnalyzer` type, moved from `@backstage/plugin-catalog-backend`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Bumped create-app version.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-notifications-backend-module-email': patch
|
||||
'@backstage/plugin-notifications-backend': patch
|
||||
---
|
||||
|
||||
Fixed email processor `esm` issue and config reading
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': minor
|
||||
---
|
||||
|
||||
Deprecated the `LocationAnalyzer` type, which has been moved to `@backstage/plugin-catalog-node`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Added `HarnessURLReader` with `readUrl` support.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/repo-tools': minor
|
||||
---
|
||||
|
||||
Adds 2 new commands `repo schema openapi diff` and `package schema openapi diff`. `repo schema openapi diff` is intended to power a new breaking changes check on pull requests and the package level command allows plugin developers to quickly see new API breaking changes. They're intended to be used in complement with the existing `repo schema openapi verify` command to validate your OpenAPI spec against a variety of things.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-notifications-backend-module-email': patch
|
||||
---
|
||||
|
||||
Support relative links in notifications sent via email
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-devtools-backend': patch
|
||||
---
|
||||
|
||||
Added discovery property to the readme documentation to ensure that it will build when setting it up as new to a Backstage instance
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': minor
|
||||
---
|
||||
|
||||
The `/alpha` plugin export has had its implementation of the `catalogAnalysisExtensionPoint` updated to reflect the new API.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Added config prop `ensureSchemaExists` to support postgres instances where user can create schemas but not databases.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
The `versions:bump` command will no longer exit with a non-zero status if the version bump fails due to forbidden duplicate package installations. It will now also provide more information about how to troubleshoot such an error. The set of forbidden duplicates has also been expanded to include all `@backstage/*-app-api` packages.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend-module-aws-alb-provider': patch
|
||||
'@backstage/plugin-auth-backend-module-github-provider': patch
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
---
|
||||
|
||||
fix: Move config declarations to appropriate auth backend modules
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-notifications': patch
|
||||
---
|
||||
|
||||
Increase default and allow modifying notification snackbar auto hide duration
|
||||
+20
-1
@@ -282,36 +282,49 @@
|
||||
"@backstage/plugin-vault-backend": "0.4.10",
|
||||
"@backstage/plugin-vault-node": "0.1.10",
|
||||
"@backstage/plugin-xcmetrics": "0.2.52",
|
||||
"@backstage/plugin-catalog-backend-module-gitlab-org": "0.0.0"
|
||||
"@backstage/plugin-catalog-backend-module-gitlab-org": "0.0.0",
|
||||
"@backstage/plugin-notifications-backend-module-email": "0.0.0"
|
||||
},
|
||||
"changesets": [
|
||||
"afraid-needles-divide",
|
||||
"blue-hotels-shake",
|
||||
"bright-pumpkins-rule",
|
||||
"chatty-cycles-unite",
|
||||
"chilly-adults-sing",
|
||||
"chilly-fireants-roll",
|
||||
"chilly-shoes-doubt",
|
||||
"cold-rats-leave",
|
||||
"cool-elephants-march",
|
||||
"create-app-1714476054",
|
||||
"cuddly-chairs-kick",
|
||||
"curly-shirts-flow",
|
||||
"curvy-planes-flash",
|
||||
"cyan-suns-shave",
|
||||
"dry-sloths-impress",
|
||||
"eighty-apricots-kneel",
|
||||
"eighty-bats-stare",
|
||||
"eleven-pandas-divide",
|
||||
"fix-stackoverflow",
|
||||
"fluffy-hotels-wait",
|
||||
"four-cooks-serve",
|
||||
"fresh-crews-impress",
|
||||
"funny-bees-taste",
|
||||
"fuzzy-seahorses-tell",
|
||||
"gold-waves-bake",
|
||||
"gorgeous-cameras-cross",
|
||||
"green-adults-push",
|
||||
"green-boxes-rescue",
|
||||
"hip-carrots-drive",
|
||||
"hot-forks-train",
|
||||
"itchy-gorillas-hope",
|
||||
"itchy-keys-wonder",
|
||||
"late-planes-fix",
|
||||
"loud-frogs-eat",
|
||||
"loud-timers-flow",
|
||||
"loud-vans-greet",
|
||||
"lovely-games-cry",
|
||||
"lucky-news-guess",
|
||||
"mean-ravens-dance",
|
||||
"orange-numbers-think",
|
||||
"perfect-points-hope",
|
||||
"proud-doors-cheat",
|
||||
@@ -322,16 +335,22 @@
|
||||
"renovate-0d0bd5c",
|
||||
"selfish-pigs-glow",
|
||||
"shy-students-clap",
|
||||
"silent-wombats-hang",
|
||||
"six-scissors-smile",
|
||||
"smart-avocados-invent",
|
||||
"smooth-garlics-behave",
|
||||
"sour-socks-approve",
|
||||
"stupid-onions-know",
|
||||
"sweet-zoos-clap",
|
||||
"tall-ads-shave",
|
||||
"tasty-apes-learn",
|
||||
"thick-llamas-itch",
|
||||
"thick-terms-rush",
|
||||
"tricky-cougars-shout",
|
||||
"unlucky-days-play",
|
||||
"unlucky-rivers-collect",
|
||||
"warm-fans-promise",
|
||||
"young-guests-reflect",
|
||||
"young-olives-drop"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-github': patch
|
||||
---
|
||||
|
||||
Updated to use the new `catalogAnalysisExtensionPoint` API.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Add `alignGauge` prop to the `GaugeCard`, and a small size version. When `alignGauge` is `'bottom'` the gauge will vertically align the gauge in the cards, even when the card titles span across multiple lines.
|
||||
Add `alignContent` prop to the `InfoCard`, defaulting to `'normal'` with the option of `'bottom'` which vertically aligns the content to the bottom of the card.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Fixed an issue causing the `repo fix` command to set an incorrect `workspace` property using Windows
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Avoiding pre-loading display total count undefined for table counts
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-gitlab': minor
|
||||
---
|
||||
|
||||
Add examples for `gitlab:projectVariable:create` scaffolder action & improve related tests
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Add previously-missing semicolon in file templated by `backstage-cli new --select plugin`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/integration': minor
|
||||
---
|
||||
|
||||
Added `HarnessIntegration` via the `ScmIntegrations` interface.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search': patch
|
||||
---
|
||||
|
||||
Added `aria-label` attribute to DialogTitle element and set `aria-modal` attribute to `true` for improved accessibility in the search modal.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-node': minor
|
||||
---
|
||||
|
||||
Breaking change to `/alpha` API where the `catalogAnalysisExtensionPoint` has been reworked. The `addLocationAnalyzer` method has been renamed to `addScmLocationAnalyzer`, and a new `setLocationAnalyzer` method has been added which allows the full `LocationAnalyzer` implementation to be overridden.
|
||||
@@ -62,6 +62,10 @@
|
||||
matchPackageNames: ['p-limit'],
|
||||
allowedVersions: '<4.0.0',
|
||||
},
|
||||
{
|
||||
matchPackageNames: ['p-throttle'],
|
||||
allowedVersions: '<4.0.0',
|
||||
},
|
||||
{
|
||||
matchPackageNames: ['p-queue'],
|
||||
allowedVersions: '<7.0.0',
|
||||
|
||||
@@ -152,6 +152,8 @@ graphviz
|
||||
Hackathons
|
||||
haproxy
|
||||
hardcoded
|
||||
Harness
|
||||
harness
|
||||
Helidon
|
||||
Henneke
|
||||
Heroku
|
||||
@@ -464,6 +466,7 @@ Weaveworks
|
||||
Webpack
|
||||
widget's
|
||||
winston
|
||||
Wolfi
|
||||
www
|
||||
WWW
|
||||
XCMetrics
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
name: API Breaking Changes (comment)
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows:
|
||||
- 'API Breaking Changes (Trigger)'
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
name: Add values from previous step
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
permissions:
|
||||
# "If you specify the access for any of these scopes, all of those that are not specified are set to none."
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
||||
actions: read # Access cache
|
||||
outputs:
|
||||
git-ref: ${{ steps.event.outputs.GIT_REF }}
|
||||
pr-number: ${{ steps.event.outputs.PR_NUMBER }}
|
||||
action: ${{ steps.event.outputs.ACTION }}
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
allowed-endpoints: >
|
||||
api.github.com:443
|
||||
|
||||
- name: 'Download artifacts'
|
||||
# Fetch output (zip archive) from the workflow run that triggered this workflow.
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name == "preview-spec"
|
||||
})[0];
|
||||
if (matchArtifact === undefined) {
|
||||
throw TypeError('Build Artifact not found!');
|
||||
}
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: matchArtifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
let fs = require('fs');
|
||||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/preview-spec.zip`, Buffer.from(download.data));
|
||||
|
||||
- name: 'Accept event from first stage'
|
||||
run: unzip preview-spec.zip event.json
|
||||
|
||||
- name: Read Event into ENV
|
||||
id: event
|
||||
run: |
|
||||
echo PR_NUMBER=$(jq '.number | tonumber' < event.json) >> $GITHUB_OUTPUT
|
||||
echo ACTION=$(jq --raw-output '.action | tostring | [scan("\\w+")][0]' < event.json) >> $GITHUB_OUTPUT
|
||||
echo GIT_REF=$(jq --raw-output '.pull_request.head.sha | tostring | [scan("\\w+")][0]' < event.json) >> $GITHUB_OUTPUT
|
||||
|
||||
- name: DEBUG - Print Job Outputs
|
||||
if: ${{ runner.debug }}
|
||||
run: |
|
||||
echo "PR number: ${{ steps.event.outputs.PR_NUMBER }}"
|
||||
echo "Git Ref: ${{ steps.event.outputs.GIT_REF }}"
|
||||
echo "Action: ${{ steps.event.outputs.ACTION }}"
|
||||
cat event.json
|
||||
|
||||
- name: Get Comment
|
||||
id: get-comment
|
||||
run: |
|
||||
unzip preview-spec.zip comment.md
|
||||
ls
|
||||
grep
|
||||
|
||||
add-comment:
|
||||
name: Write comment about issues
|
||||
needs:
|
||||
- setup
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
|
||||
# Identify comment to be updated
|
||||
- name: Find comment for API Changes
|
||||
uses: peter-evans/find-comment@d5fe37641ad8451bdd80312415672ba26c86575e # v3
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ needs.setup.outputs.pr-number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: API changes
|
||||
direction: last
|
||||
|
||||
- name: Create or Update Comment with API Changes
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
|
||||
with:
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body-path: comment.md
|
||||
edit-mode: replace
|
||||
@@ -0,0 +1,56 @@
|
||||
name: API Breaking Changes (Trigger)
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
paths:
|
||||
- '**/openapi.yaml'
|
||||
|
||||
jobs:
|
||||
get-backstage-changes:
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=4096
|
||||
name: Build PR image
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
# Fetch the commit that's merged into the base rather than the target ref
|
||||
# This will let us diff only the contents of the PR, without fetching more history
|
||||
ref: 'refs/pull/${{ github.event.pull_request.number }}/merge'
|
||||
- name: fetch base
|
||||
run: git fetch --depth 1 origin ${{ github.base_ref }}
|
||||
|
||||
- name: setup-node
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 18.x
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
- name: yarn install
|
||||
uses: backstage/actions/yarn-install@a674369920067381b450d398b27df7039b7ef635 # v0.6.5
|
||||
with:
|
||||
cache-prefix: linux-v18
|
||||
|
||||
- name: breaking changes check
|
||||
run: |
|
||||
yarn backstage-repo-tools repo schema openapi check --since origin/${{ github.base_ref }} > comment.md
|
||||
|
||||
- name: Upload Rendered Comment as Artifact
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
|
||||
with:
|
||||
name: preview-spec
|
||||
path: comment.md
|
||||
retention-days: 2
|
||||
|
||||
- name: Upload PR Event as Artifact
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: preview-spec
|
||||
path: ${{ github.event_path }}
|
||||
retention-days: 2
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
# Fetch the commit that's merged into the base rather than the target ref
|
||||
# This will let us diff only the contents of the PR, without fetching more history
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
ref: '${{ github.event.pull_request.merge_commit_sha }}'
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
@@ -197,7 +197,7 @@ jobs:
|
||||
INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
- name: fetch master branch
|
||||
run: git fetch origin master
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
path: backstage
|
||||
ref: ${{ github.event.client_payload.version && env.RELEASE_VERSION || github.ref }}
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js 18.x
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js 18.x
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
@@ -105,11 +105,11 @@ jobs:
|
||||
- name: test (and upload coverage)
|
||||
run: |
|
||||
yarn backstage-cli repo test --maxWorkers=3 --workerIdleMemoryLimit=1300M --coverage
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
# bash <(curl -s https://codecov.io/bash)
|
||||
# Upload code coverage for some specific flags. Also see .codecov.yml
|
||||
bash <(curl -s https://codecov.io/bash) -f packages/core-app-api/coverage/* -F core-app-api
|
||||
bash <(curl -s https://codecov.io/bash) -f packages/core-components/coverage/* -F core-components
|
||||
bash <(curl -s https://codecov.io/bash) -f packages/core-plugin-api/coverage/* -F core-plugin-api
|
||||
# bash <(curl -s https://codecov.io/bash) -f packages/core-app-api/coverage/* -F core-app-api
|
||||
# bash <(curl -s https://codecov.io/bash) -f packages/core-components/coverage/* -F core-components
|
||||
# bash <(curl -s https://codecov.io/bash) -f packages/core-plugin-api/coverage/* -F core-plugin-api
|
||||
env:
|
||||
BACKSTAGE_TEST_DISABLE_DOCKER: 1
|
||||
BACKSTAGE_TEST_DATABASE_POSTGRES16_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres16.ports[5432] }}
|
||||
@@ -148,7 +148,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: 'Checkout code'
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -66,6 +66,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: 'Upload to code-scanning'
|
||||
uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
# Fetch changes to previous commit - required for 'only_changed' in Prettier action
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
run: npm install semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
path: backstage
|
||||
# 'v' prefix is added here for the tag, we keep it out of the manifest logic
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
|
||||
# Checkout backstage/versions into /backstage/versions, which is where store the output
|
||||
- name: Checkout versions
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
repository: backstage/versions
|
||||
path: backstage/versions
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js 18.x
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
- name: Monitor and Synchronize Snyk Policies
|
||||
uses: snyk/actions/node@8349f9043a8b7f0f3ee8885bf28f0b388d2446e8 # master
|
||||
with:
|
||||
@@ -58,6 +58,6 @@ jobs:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
NODE_OPTIONS: --max-old-space-size=7168
|
||||
- name: Upload Snyk report
|
||||
uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
with:
|
||||
sarif_file: snyk.sarif
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
fetch-depth: 20000
|
||||
fetch-tags: true
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: setup-node
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout git repo
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
- name: Render Compose File
|
||||
run: |
|
||||
# update image after the build above
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -80,4 +80,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
# Vale does not support file excludes, so we use the script to generate a list of files instead
|
||||
# The action also does not allow args or a local config file to be passed in, so the files array
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
git config --global core.autocrlf false
|
||||
git config --global core.eol lf
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: Install Fossa
|
||||
run: "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | bash"
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js 18.x
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
with:
|
||||
fetch-depth: 0 # Required to retrieve git history
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
diff --git a/dist/changesets-assemble-release-plan.cjs.js b/dist/changesets-assemble-release-plan.cjs.js
|
||||
index ee5c0f67fabadeb112e9f238d8b144a4d125830f..9b0e1a156dd88cee35f82faf718d82a8a8f80325 100644
|
||||
--- a/dist/changesets-assemble-release-plan.cjs.js
|
||||
+++ b/dist/changesets-assemble-release-plan.cjs.js
|
||||
@@ -179,12 +179,23 @@ function getDependencyVersionRanges(dependentPkgJSON, dependencyRelease) {
|
||||
if (!versionRange) continue;
|
||||
|
||||
if (versionRange.startsWith("workspace:")) {
|
||||
+ // intentionally keep other workspace ranges untouched
|
||||
+ // this has to be fixed but this should only be done when adding appropriate tests
|
||||
+ let workspaceRange = versionRange.replace(/^workspace:/, "");
|
||||
+ switch (workspaceRange) {
|
||||
+ case "*":
|
||||
+ // workspace:* actually means the current exact version, and not a wildcard similar to a reguler * range
|
||||
+ workspaceRange = dependencyRelease.oldVersion;
|
||||
+ break;
|
||||
+ case "~":
|
||||
+ case "^":
|
||||
+ // Use ^oldVersion for workspace:^ or ~oldVersion for workspace:~.
|
||||
+ // The version range might have changed in dependent package, but that should have its own changeset bumping that package.
|
||||
+ workspaceRange += dependencyRelease.oldVersion;
|
||||
+ }
|
||||
dependencyVersionRanges.push({
|
||||
depType: type,
|
||||
- versionRange: // intentionally keep other workspace ranges untouched
|
||||
- // this has to be fixed but this should only be done when adding appropriate tests
|
||||
- versionRange === "workspace:*" ? // workspace:* actually means the current exact version, and not a wildcard similar to a reguler * range
|
||||
- dependencyRelease.oldVersion : versionRange.replace(/^workspace:/, "")
|
||||
+ versionRange: workspaceRange,
|
||||
});
|
||||
} else {
|
||||
dependencyVersionRanges.push({
|
||||
-233
@@ -1,233 +0,0 @@
|
||||
# Project Areas
|
||||
|
||||
The Backstage project is divided into several project areas, each covering particular parts of the project. The main driver for each area is ownership of code in the main Backstage repository, as well as other repositories in the Backstage GitHub organization. Each area has a set of maintainers and repository content that they own. There may be no overlap in ownership between areas, which means that any given line in the GitHub code owners file should have only one owner specified. Each area is represented by a team in the Backstage GitHub organization. Apart from certain project-wide concerns, such as the release process, each area is self-governing and chooses their own ways of working. Project areas may also have special interest groups (SIGs) related to their area, but this is not required.
|
||||
|
||||
The project areas as well as their maintainers are listed in the [OWNERS.md](./OWNERS.md) file.
|
||||
|
||||
Each project area must have at least one maintainer. Project area maintainers may have shared ownership with the core maintainers, which in that case is considered an incubating area. The project area maintainers help drive work forward in the area, but they might not yet feel ready to take on ownership. The goal should generally be that these project area maintainers eventually become sole maintainers of the project area. This is to allow for a more smooth onboarding and transition of ownership, where members of the community might for example be new to open source maintainership.
|
||||
|
||||
## Adding new project areas
|
||||
|
||||
Project areas are added by nominating new maintainers for that area. See the sections for becoming a [Project Area Maintainer](#project-area-maintainer).
|
||||
|
||||
Project areas may also by added by splitting existing areas. Every area that is created through this process must have at least one maintainer.
|
||||
|
||||
## Removing project areas
|
||||
|
||||
Project areas are removed by removing all maintainers for that area and removing the corresponding team from the Backstage GitHub organization. The project area can be re-added later if there is a need for it. Reasons for removal may include lack of activity, lack of maintainers, or lack of relevance to the project.
|
||||
|
||||
# Project Roles
|
||||
|
||||
## Contributor
|
||||
|
||||
A Contributor contributes directly to the project and adds value to it. Contributions need not be code. People at the Contributor level may be new contributors, or they may only contribute occasionally.
|
||||
|
||||
### Responsibilities
|
||||
|
||||
- Follow the [CNCF CoC](https://github.com/cncf/foundation/blob/main/code-of-conduct.md)
|
||||
- Follow the project [contributing guide](CONTRIBUTING.md)
|
||||
|
||||
### How to get involved
|
||||
|
||||
- Participate in community discussions
|
||||
- Help other users
|
||||
- Submit bug reports
|
||||
- Comment on issues
|
||||
- Try out new releases
|
||||
- Attend community events
|
||||
|
||||
### How to contribute
|
||||
|
||||
- Report and sometimes resolve issues
|
||||
- Occasionally submit PRs
|
||||
- Contribute to the documentation
|
||||
- Show up at meetings, take notes
|
||||
- Answer questions from other community members
|
||||
- Submit feedback on issues and PRs
|
||||
- Test releases and patches and submit reviews
|
||||
- Run or help run events
|
||||
- Promote the project in public
|
||||
|
||||
## Organization Member
|
||||
|
||||
An org member is a frequent contributor that has become a member of the Backstage GitHub organization. In addition to the responsibilities of contributors, an org member is also expected to be reasonably active in the community through continuous contributions of any type.
|
||||
|
||||
An Organization Member must meet the responsibilities and has the requirements of a Contributor.
|
||||
|
||||
### Responsibilities
|
||||
|
||||
- Continues to contribute regularly, as demonstrated by having at least 10 GitHub contributions per year in [Devstats](https://backstage.devstats.cncf.io/d/48/users-statistics-by-repository-group?orgId=1&var-period=y&var-metric=contributions&var-repogroup_name=All&from=now-1y&to=now&var-users=All), or contributions of a similar effort that might not be captured in Devstats.
|
||||
|
||||
### Requirements
|
||||
|
||||
- Must have at least 10 contributions to the projects in the form of:
|
||||
- Accepted PRs
|
||||
- Helpful PR reviews
|
||||
- Resolving GitHub issues
|
||||
- Or some equivalent contributions to the project
|
||||
- Must have been contributing for at least 3 months
|
||||
- Or is the member of a team that owns a project area, in which case the above requirements do not apply and the member is instead vetted by the project area maintainers
|
||||
|
||||
### Becoming an Organization Member
|
||||
|
||||
Open an issue towards [the community repository](https://github.com/backstage/community) using the [org membership request template](https://github.com/backstage/community/issues/new?template=org_member.yaml&title=Org+Member%3A+%3Cyour-github-login%3E).
|
||||
|
||||
### Privileges
|
||||
|
||||
- Membership in the Backstage GitHub organization
|
||||
|
||||
## Plugin Maintainer
|
||||
|
||||
A Plugin Maintainer is responsible for maintaining an individual Backstage plugin or module. This includes reviewing contributions and responding to issues towards an individual plugin, as well as keeping the plugin up to date.
|
||||
|
||||
Plugin Maintainer is a lightweight form of ownership that is primarily reflected though code owners of the plugin packages in the [CODEOWNERS](./.github/CODEOWNERS) file. Each plugin can have one or more maintainers. If a plugin becomes a significant part of the Backstage ecosystem, it may be promoted to be a distinct project area instead.
|
||||
|
||||
A Plugin Maintainer has all the rights and responsibilities of an Organization Member.
|
||||
|
||||
### Responsibilities
|
||||
|
||||
- Review the majority of PRs towards the plugin
|
||||
- Respond to GitHub issues related to the plugin
|
||||
- Keep the plugin up-to-date with Backstage libraries and other dependencies
|
||||
- Follow the [reviewing guide](REVIEWING.md)
|
||||
|
||||
### Requirements
|
||||
|
||||
- Is an Organization Member
|
||||
- Display knowledge of Backstage's review process and best practices for plugin design
|
||||
- Is supportive of new and occasional contributors and helps get useful PRs in shape to merge
|
||||
|
||||
### Privileges
|
||||
|
||||
- GitHub code owner of the plugin directory, with rights to approve and merge PRs towards the plugin
|
||||
|
||||
### Becoming a Plugin Maintainer
|
||||
|
||||
To become a Plugin Maintainer, you first need to be an Organization Member. You can then file a pull request towards [CODEOWNERS.md](./.github/CODEOWNERS) requesting to be added as a code owner of the plugin directory. Existing code owners of that plugin alongside the core maintainers will then review the request.
|
||||
|
||||
## Project Area Maintainer
|
||||
|
||||
Project Area Maintainers are owners of a particular project area. They are expected to review and merge pull requests towards their area, and also drive development and manage tech health. A Project Area Maintainer also need to commit a certain number of hours per month towards the project, and exercise judgment for the good of the project, independent of their employer. Project Area Maintainers should also mentor new maintainers and participate in and lead community meetings related to their area. New Project Area Maintainers need to be approved by the existing project area maintainers, or the core maintainers if it is a new area.
|
||||
|
||||
The maintainers of a project area may be represented by a team in external organization. In this case, the state as a project area maintainer is tied to the membership in that team. New members of the team may automatically be added as maintainers, as well as removed when they leave. This process is governed autonomously by the team of project area maintainers.
|
||||
|
||||
A Project Area Maintainer has all the rights and responsibilities of an Organization Member.
|
||||
|
||||
### Responsibilities
|
||||
|
||||
- Review PRs towards their project area. Project area maintainers are expected to review at least 20 PRs per year, or the majority of all PRs towards the area, if it is less than 20
|
||||
- Follow the [reviewing guide](REVIEWING.md)
|
||||
- Triage and respond to issues related to their project area
|
||||
- Mentor new project area maintainers
|
||||
- Write refactoring PRs
|
||||
- Determine strategy and policy for the project area
|
||||
- Participate in or leading community meetings related to their project area
|
||||
|
||||
### Requirements
|
||||
|
||||
- Is an Organization Member
|
||||
- Have made at least 5 meaningful contributions towards the project area
|
||||
- Demonstrates knowledge of their project area, and how it fits into the larger Backstage project
|
||||
- Is able to exercise judgment for the good of the project, independent of their employer, friends, or team
|
||||
- Mentors other contributors and project area maintainers
|
||||
- Can commit to spending at least 16 hours per month working on the project, preferably distributed evenly across the month
|
||||
|
||||
### Privileges
|
||||
|
||||
- Approve and merge PRs towards their project area
|
||||
- Drive the direction and roadmap of their project area
|
||||
|
||||
### Becoming a Project Area Maintainer
|
||||
|
||||
If you are interested in becoming a project area maintainer, reach out to the existing maintainers for that area. If you wish to become a maintainer for a new area, reach out to the core maintainers.
|
||||
|
||||
Any current project area maintainer or core maintainer may nominate a new project area maintainer by opening a PR towards the [OWNERS.md](OWNERS.md) file. A majority of the project area maintainers for that area must approve the PR. If there are no existing maintainers for that area, the PR must be approved by a majority of the core maintainers.
|
||||
|
||||
## Core Maintainer
|
||||
|
||||
Core Maintainers are responsible for the Backstage project as a whole. They help review and merge project-level pull requests as well as coordinate work affecting multiple project areas. A core maintainer needs to commit the majority of their working time towards the project, and exercise judgment for the good of the project, independent of their employer. Core maintainers should also mentor and seek out new maintainers, lead community meetings, and communicate with the CNCF on behalf of the project. To become a core maintainer one needs to have been the maintainer of a number of different project areas, demonstrate a deep knowledge of large parts of the Backstage project, and be backed by the existing core maintainers.
|
||||
|
||||
A Core Maintainer have all the rights and responsibilities of a Project Area Maintainer.
|
||||
|
||||
### Responsibilities
|
||||
|
||||
- Take part in the incoming issue and PR triage and review process. PRs are shared equally among all maintainers
|
||||
- Mentor new Project Area Maintainers and Plugin Maintainers
|
||||
- Drive refactoring and manage tech health across the entire project
|
||||
- Participate in CNCF maintainer activities
|
||||
- Respond to security incidents in accordance to our [security policy](./SECURITY.md)
|
||||
- Determine strategy and policy for the project
|
||||
- Participate in or leading community meetings
|
||||
|
||||
### Requirements
|
||||
|
||||
- Experience as a Project Area Maintainer for at least 6 months
|
||||
- Demonstrates a broad knowledge of the project across multiple areas
|
||||
- Is able to exercise judgment for the good of the project, independent of their employer, friends, or team
|
||||
- Mentors other contributors
|
||||
- Can commit to spending at least 10 days per month working on the project
|
||||
|
||||
### Privileges
|
||||
|
||||
- Approve PRs that fall outside any specific project area
|
||||
- Merge PRs to any area of the project
|
||||
- Represent the project in public as a Maintainer
|
||||
- Communicate with the CNCF on behalf of the project
|
||||
- Have a vote in Maintainer decision-making meetings
|
||||
|
||||
### Becoming a Core Maintainer
|
||||
|
||||
Any core maintainer or end user sponsor may nominate a new core maintainer by opening a PR towards the [OWNERS.md](OWNERS.md) file. Core maintainers must be approved by a majority of the existing core maintainers and end user sponsors.
|
||||
|
||||
## End User Sponsors
|
||||
|
||||
### Role of a Backstage End User Sponsor
|
||||
|
||||
- Provide support for Backstage by removing blockers, securing funding, providing advocacy, feedback, and ensuring project continuity and long term success
|
||||
- Assist Backstage maintainers in prioritizing upcoming roadmap items and planned work
|
||||
- Provide neutral mediation for any disputes that arise as part of the project
|
||||
|
||||
### Backstage End User Sponsor Membership
|
||||
|
||||
The End User Sponsors group comprises at most 5 people. To be eligible for membership in the group, you or the company where you work you must:
|
||||
|
||||
- Be responsible for and end user of a production Backstage deployment of non-trivial size
|
||||
- Be active contributors to the open source project
|
||||
- Be willing and able to attend regularly-scheduled End User Sponsor meetings
|
||||
- Abide by [CNCF CoC](https://github.com/cncf/foundation/blob/main/code-of-conduct.md)
|
||||
|
||||
Candidates for membership will be nominated by current Sponsor members or by Backstage maintainers. If there are more nominations than Sponsor seats remaining, existing sponsors shall vote on the candidates, and the candidates with the most votes will become Sponsors. Any ties will be broken by current Backstage sponsors.
|
||||
|
||||
# Conflict resolution and voting
|
||||
|
||||
In general, we prefer that technical issues and membership are amicably worked out between the persons involved. If a dispute cannot be decided independently, the sponsors and core maintainers can be called in to decide an issue. If the sponsors and maintainers themselves cannot decide an issue, the issue will be resolved by voting.
|
||||
|
||||
In all cases in this document where voting is mentioned, the voting process is a simple majority in which each sponsor receives two votes and each core maintainer receives one vote. If such a majority is reached, the vote is said to have _passed_.
|
||||
|
||||
## Inactivity
|
||||
|
||||
It is important for contributors to be and stay active to set an example and show commitment to the project. Inactivity is harmful to the project as it may lead to unexpected delays, contributor attrition, and a loss of trust in the project.
|
||||
|
||||
Inactivity is measured by periods of no contributions without explanation, for longer than:
|
||||
|
||||
- Core Maintainer: 2 months
|
||||
- Project Area Maintainer: 4 months
|
||||
- Plugin Maintainer: 6 months
|
||||
- Organization Member: 12 months
|
||||
|
||||
Consequences of being inactive include:
|
||||
|
||||
- Involuntary removal or demotion
|
||||
- Being asked to move to Emeritus status
|
||||
|
||||
## Involuntary Removal or Demotion
|
||||
|
||||
Involuntary removal/demotion of a contributor happens when responsibilities and requirements aren't being met. This may include repeated patterns of inactivity, extended period of inactivity, a period of failing to meet the requirements of your role, and/or a violation of the Code of Conduct. This process is important because it protects the community and its deliverables while also opens up opportunities for new contributors to step in.
|
||||
|
||||
Involuntary removal or demotion is handled through a vote by a majority of the current Core Maintainers. Some aspects of this process may be automated, such as removal after periods of inactivity.
|
||||
|
||||
## Stepping Down/Emeritus Process
|
||||
|
||||
If and when contributors' commitment levels change, contributors can consider stepping down (moving down the contributor ladder) vs moving to emeritus status (completely stepping away from the project).
|
||||
|
||||
Contact the Maintainers about changing to Emeritus status, or reducing your contributor level.
|
||||
@@ -5,3 +5,4 @@ Portions of this software were developed by third-party software vendors:
|
||||
|
||||
- Tech Radar Plugin (https://opensource.zalando.com/tech-radar/), Copyright (c) 2017 Zalando SE
|
||||
- [OpenAPI Generator Templates](./packages/repo-tools/templates), Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) Copyright 2018 SmartBear Software
|
||||
- Optic CLI (https://github.com/opticdev/optic), Copyright 2022, Optic Labs Corporation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
- See [CONTRIBUTING.md](CONTRIBUTING.md) for general contribution guidelines.
|
||||
- See [GOVERNANCE.md](GOVERNANCE.md) for governance guidelines and responsibilities.
|
||||
- See [GOVERNANCE.md](https://github.com/backstage/community/blob/main/GOVERNANCE.md) for governance guidelines and responsibilities.
|
||||
|
||||
## Core Maintainers
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ app:
|
||||
# applicationId: qwerty
|
||||
# site: # datadoghq.eu default = datadoghq.com
|
||||
# env: # optional
|
||||
# sessionSampleRate: 100
|
||||
# sessionReplaySampleRate: 0
|
||||
|
||||
support:
|
||||
url: https://github.com/backstage/backstage/issues # Used by common ErrorPage
|
||||
items: # Used by common SupportButton component
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# Minimal Hardened Image for Backstage
|
||||
|
||||
DockerHub images in general did not seem ideal for Backstage as the number of vulnerabilities were quite high regardless of the image used.
|
||||
|
||||
The `Dockerfile` in this directory uses a [`wolfi-base`](https://github.com/wolfi-dev) image from Chainguard Images. This improves the security of the application and reduces false positives in scanners.
|
||||
|
||||
## Considerations
|
||||
|
||||
- `Wolfi` only releases the `latest` tag for public consumption however digests can be pinned.
|
||||
- `Wolfi` OS uses packages from the [os repository](https://github.com/wolfi-dev/os) on GitHub. Some packages may be named differently.
|
||||
- While `Wolfi` uses `apk`, the OS is designed to support `glibc`.
|
||||
- Due to the stripped down nature of the base image, additional packages might be needed compared to a distribution like Debian or Ubuntu.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Minimal Hardened Image for Backstage
|
||||
|
||||
DockerHub images in general did not seem ideal for Backstage as the number of vulnerabilities were quite high regardless of the image used.
|
||||
|
||||
The `Dockerfile` in this directory uses a [wolfi-base](https://github.com/wolfi-dev) image from Chainguard Images. This improves the security of the application and reduces false positives in scanners.
|
||||
|
||||
## Pinning Digest
|
||||
|
||||
To reduce maintenance, the digest of the image has been removed from the `./Dockerfile` file. A complete example with the digest would be `cgr.dev/chainguard/wolfi-base:latest@sha256:3d6dece13cdb5546cd03b20e14f9af354bc1a56ab5a7b47dca3e6c1557211fcf` and it is suggested to update the `FROM` line in the `Dockerfile` to use a digest.
|
||||
|
||||
Using the digest allows tools such as Dependabot or Renovate to know exactly which image digest is being utilized and allows for Pull Requests to be triggered when a new digest is available. It is suggested to setup Dependabot/Renovate or a similar tool to ensure the image is kept up to date so that vulnerability fixes that have been addressed are pulled in frequently.
|
||||
|
||||
### Obtaining Digest
|
||||
|
||||
To obtain the latest digest, perform a `docker pull` on the image to get the latest digest in the command output or use `crane digest <image>`.
|
||||
|
||||
## Considerations
|
||||
|
||||
- Wolfi only releases the `latest` tag for public consumption however digests can be pinned.
|
||||
- Wolfi OS uses packages from the [os repository](https://github.com/wolfi-dev/os) on GitHub.
|
||||
- Some packages may be named differently.
|
||||
- While Wolfi uses `apk`, the OS is designed to support `glibc`.
|
||||
- Due to the stripped down nature of the base image, additional packages might be needed compared to a distribution like Debian or Ubuntu.
|
||||
- Chainguard will maintain one version of each Wolfi package at a time, which will track the latest version of the upstream software in the package. Chainguard will end patch support for previous versions of packages in Wolfi. [Read more here](https://edu.chainguard.dev/chainguard/chainguard-images/faq/#what-packages-are-available-in-chainguard-images)
|
||||
- It is encouraged to use a relative pin or use a third-party tool to ensure the packages are kept up to date
|
||||
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 72 KiB |
@@ -47,6 +47,12 @@ auth:
|
||||
clientId: ${AUTH_ATLASSIAN_CLIENT_ID}
|
||||
clientSecret: ${AUTH_ATLASSIAN_CLIENT_SECRET}
|
||||
scope: ${AUTH_ATLASSIAN_SCOPES}
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: usernameMatchingUserEntityName
|
||||
```
|
||||
|
||||
The Atlassian provider is a structure with three configuration keys:
|
||||
@@ -57,6 +63,18 @@ The Atlassian provider is a structure with three configuration keys:
|
||||
|
||||
**NOTE:** the scopes `offline_access`, `read:jira-work`, and `read:jira-user` are provided by default.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `usernameMatchingUserEntityName`: Matches the username from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `atlassianAuthApi` reference and
|
||||
|
||||
@@ -41,6 +41,12 @@ auth:
|
||||
clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
|
||||
## uncomment if using GitHub Enterprise
|
||||
# enterpriseInstanceUrl: ${AUTH_GITHUB_ENTERPRISE_INSTANCE_URL}
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: usernameMatchingUserEntityName
|
||||
```
|
||||
|
||||
The GitHub provider is a structure with three configuration keys:
|
||||
@@ -55,6 +61,18 @@ The GitHub provider is a structure with three configuration keys:
|
||||
`https://your-intermediate-service.com/handler`. Only needed if Backstage is
|
||||
not the immediate receiver (e.g. one OAuth app for many backstage instances).
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `usernameMatchingUserEntityName`: Matches the username from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `githubAuthApi` reference and
|
||||
|
||||
@@ -43,6 +43,12 @@ auth:
|
||||
# audience: https://gitlab.company.com
|
||||
## uncomment if using a custom redirect URI
|
||||
# callbackUrl: https://${BASE_URL}/api/auth/gitlab/handler/frame
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: usernameMatchingUserEntityName
|
||||
```
|
||||
|
||||
The GitLab provider is a structure with three configuration keys:
|
||||
@@ -56,6 +62,18 @@ The GitLab provider is a structure with three configuration keys:
|
||||
`https://$backstage.acme.corp/api/auth/gitlab/handler/frame`
|
||||
Note: Due to a peculiarity with GitLab OAuth, ensure there is no trailing `/` after 'frame' in the URL.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `usernameMatchingUserEntityName`: Matches the username from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `gitlabAuthApi` reference and
|
||||
|
||||
@@ -27,6 +27,12 @@ auth:
|
||||
gcp-iap:
|
||||
audience: '/projects/<project number>/global/backendServices/<backend service id>'
|
||||
jwtHeader: x-custom-header # Optional: Only if you are using a custom header for the IAP JWT
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: emailMatchingUserEntityAnnotation
|
||||
```
|
||||
|
||||
The full `audience` value can be obtained by visiting your [Identity-Aware Proxy Google Cloud console](https://console.cloud.google.com/security/iap), selecting your project, finding your Backend Service to proxy, clicking the 3 vertical dots then "Get JWT Audience Code", and copying from the resulting popup, which will look similar to the following:
|
||||
@@ -36,11 +42,44 @@ The full `audience` value can be obtained by visiting your [Identity-Aware Proxy
|
||||
This config section must be in place for the provider to load at all. Now let's
|
||||
add the provider itself.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailMatchingUserEntityAnnotation`: Matches the email address from the auth provider with the User entity where the value of the `google.com/email` annotation matches. If no match is found it will throw a `NotFoundError`.
|
||||
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
## Backend Changes
|
||||
|
||||
This provider is not enabled by default in the auth backend code, because
|
||||
besides the config section above, it also needs to be given one or more
|
||||
callbacks in actual code as well as described below.
|
||||
There is a module for this provider that you will need to add to your backend.
|
||||
|
||||
First you'll want to run this command to add the module:
|
||||
|
||||
```sh
|
||||
yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-gcp-iap-provider
|
||||
```
|
||||
|
||||
Then you will need to add this to your backend:
|
||||
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
const backend = createBackend();
|
||||
|
||||
backend.add(import('@backstage/plugin-auth-backend'));
|
||||
/* highlight-add-start */
|
||||
backend.add(import('@backstage/plugin-auth-backend-module-gcp-iap-provider'));
|
||||
/* highlight-add-end */
|
||||
```
|
||||
|
||||
### Legacy Backend Changes
|
||||
|
||||
If you are still using the legacy backend you will need to make the changes outlined here.
|
||||
|
||||
This provider is not enabled by default in the auth backend code, because besides the config section above, it also needs to be given one or more callbacks in actual code as well as described below.
|
||||
|
||||
Add a `providerFactories` entry to the router in
|
||||
`packages/backend/src/plugins/auth.ts`.
|
||||
|
||||
@@ -42,6 +42,12 @@ auth:
|
||||
development:
|
||||
clientId: ${AUTH_GOOGLE_CLIENT_ID}
|
||||
clientSecret: ${AUTH_GOOGLE_CLIENT_SECRET}
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: emailMatchingUserEntityAnnotation
|
||||
```
|
||||
|
||||
The Google provider is a structure with two configuration keys:
|
||||
@@ -50,6 +56,18 @@ The Google provider is a structure with two configuration keys:
|
||||
`10023341500512-beui241gjwwkrdkr2eh7dprewj2pp1q.apps.googleusercontent.com`
|
||||
- `clientSecret`: The client secret tied to the generated client ID.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailMatchingUserEntityAnnotation`: Matches the email address from the auth provider with the User entity where the value of the `google.com/email` annotation matches. If no match is found it will throw a `NotFoundError`.
|
||||
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `googleAuthApi` reference and
|
||||
|
||||
@@ -57,6 +57,12 @@ auth:
|
||||
domainHint: ${AZURE_TENANT_ID}
|
||||
additionalScopes:
|
||||
- Mail.Send
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: emailMatchingUserEntityAnnotation
|
||||
```
|
||||
|
||||
The Microsoft provider is a structure with three mandatory configuration keys:
|
||||
@@ -70,6 +76,18 @@ The Microsoft provider is a structure with three mandatory configuration keys:
|
||||
For more details, see [Home Realm Discovery](https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/home-realm-discovery-policy)
|
||||
- `additionalScopes` (optional): List of scopes for the App Registration. The default and mandatory value is ['user.read'].
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailMatchingUserEntityAnnotation`: Matches the email address from the auth provider with the User entity where the value of the `microsoft.com/email` annotation matches. If no match is found it will throw a `NotFoundError`.
|
||||
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `microsoftAuthApiRef` reference and
|
||||
|
||||
@@ -22,44 +22,27 @@ The provider configuration can be added to your `app-config.yaml` under the root
|
||||
auth:
|
||||
environment: development
|
||||
providers:
|
||||
oauth2Proxy: {}
|
||||
oauth2Proxy:
|
||||
development:
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: forwardedUserMatchingUserEntityName
|
||||
```
|
||||
|
||||
Right now no configuration options are supported, but the empty object is needed
|
||||
to enable the provider in the auth backend.
|
||||
### Resolvers
|
||||
|
||||
To use the `oauth2Proxy` provider you must also configure it with a sign-in resolver.
|
||||
For more information about the sign-in process in general, see the
|
||||
[Sign-in Identities and Resolvers](../identity-resolver.md) documentation.
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
For the `oauth2Proxy` provider, the sign-in result is quite different than other providers.
|
||||
Because it's a proxy provider that can be configured to forward information through
|
||||
arbitrary headers, the auth result simply just gives you access to the HTTP headers
|
||||
of the incoming request. Using these you can either extract the information directly,
|
||||
or grab ID or access tokens to look up additional information and/or validate the request.
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `forwardedUserMatchingUserEntityName`: Matches the value in the `x-forwarded-user` header from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
|
||||
A simple sign-in resolver might for example look like this:
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
```ts
|
||||
providerFactories: {
|
||||
...defaultAuthProviderFactories,
|
||||
oauth2Proxy: providers.oauth2Proxy.create({
|
||||
signIn: {
|
||||
async resolver({ result }, ctx) {
|
||||
const name = result.getHeader('x-forwarded-user');
|
||||
if (!name) {
|
||||
throw new Error('Request did not contain a user')
|
||||
}
|
||||
return ctx.signInWithCatalogUser({
|
||||
entityRef: { name },
|
||||
});
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
```
|
||||
|
||||
[An example on how to sign a user in without a matching user](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/auth.ts)
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ To add Okta authentication, you must create an Application from Okta:
|
||||
|
||||
The configuration examples provided above are suitable for local development. For a production deployment, substitute `http://localhost:7007` with the url that your Backstage instance is available at.
|
||||
|
||||
# Configuration
|
||||
## Configuration
|
||||
|
||||
The provider configuration can then be added to your `app-config.yaml` under the
|
||||
root `auth` configuration:
|
||||
@@ -47,6 +47,12 @@ auth:
|
||||
idp: ${AUTH_OKTA_IDP} # Optional
|
||||
# https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned
|
||||
additionalScopes: ${AUTH_OKTA_ADDITIONAL_SCOPES} # Optional
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: emailMatchingUserEntityAnnotation
|
||||
```
|
||||
|
||||
The values referenced are found on the Application page on your Okta site.
|
||||
@@ -61,6 +67,18 @@ The values referenced are found on the Application page on your Okta site.
|
||||
|
||||
`additionalScopes` is an optional value, a string of space separated scopes, that will be combined with the default `scope` value of `openid profile email offline_access` to adjust the `scope` sent to Okta during OAuth. This will have an impact on [the dependent claims returned](https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned). For example, setting the `additionalScopes` value to `groups` will result in the claim returning a list of the groups that the user is a member of that also match the ID token group filter of the client app.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailMatchingUserEntityAnnotation`: Matches the email address from the auth provider with the User entity where the value of the `okta.com/email` annotation matches. If no match is found it will throw a `NotFoundError`.
|
||||
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `oktaAuthApi` reference and
|
||||
|
||||
@@ -107,10 +107,6 @@ export default async function createPlugin(
|
||||
In the above, `commonSignInResolvers.emailLocalPartMatchingUserEntityName()`
|
||||
can be replaced with a more suitable resolver for the app in question.
|
||||
|
||||
## Configure Sign-in Resolution
|
||||
|
||||
See [Sign-in Identities and Resolvers](../identity-resolver.md) for details.
|
||||
|
||||
## Add to Sign-in Page
|
||||
|
||||
See the [Sign-In Configuration](../index.md#sign-in-configuration) docs for
|
||||
@@ -156,9 +152,15 @@ auth:
|
||||
development:
|
||||
clientId: ${APP_ID}
|
||||
organizationId: ${ORG_ID}
|
||||
signIn:
|
||||
resolvers:
|
||||
# typically you would pick one of these
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: vmwareCloudSignInResolvers
|
||||
```
|
||||
|
||||
where `APP_ID` refers to the ID retrieved when creating the OAuth App, and
|
||||
Where `APP_ID` refers to the ID retrieved when creating the OAuth App, and
|
||||
`ORG_ID` is the [long ID of the
|
||||
Organization](https://docs.vmware.com/en/VMware-Cloud-services/services/Using-VMware-Cloud-Services/GUID-CF9E9318-B811-48CF-8499-9419997DC1F8.html#view-the-organization-id-1)
|
||||
in VMware Cloud for which you wish to enable sign-in.
|
||||
@@ -169,3 +171,15 @@ library used by this provider requires the use of Express session middleware to
|
||||
do this. Therefore the value `your session secret` under `auth.session.secret`
|
||||
should be replaced with a long, complex and unique string which will act as a
|
||||
key for signing session cookies set by Backstage.
|
||||
|
||||
### Resolvers
|
||||
|
||||
This provider includes several resolvers out of the box that you can use:
|
||||
|
||||
- `emailMatchingUserEntityProfileEmail`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will throw a `NotFoundError`.
|
||||
- `emailLocalPartMatchingUserEntityName`: Matches the [local part](https://en.wikipedia.org/wiki/Email_address#Local-part) of the email address from the auth provider with the User entity that has a matching `name`. If no match is found it will throw a `NotFoundError`.
|
||||
- `vmwareCloudSignInResolvers`: Matches the email address from the auth provider with the User entity that has a matching `spec.profile.email`. If no match is found it will sign in the user without associating with a catalog user.
|
||||
|
||||
> Note: The resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
|
||||
If these resolvers do not fit your needs you can build a custom resolver, this is covered in the [Building Custom Resolvers](../identity-resolver.md#building-custom-resolvers) section of the Sign-in Identities and Resolvers documentation.
|
||||
|
||||
@@ -816,9 +816,9 @@ auth:
|
||||
tenantId: ${AZURE_TENANT_ID}
|
||||
signIn:
|
||||
resolvers:
|
||||
- resolver: emailMatchingUserEntityAnnotation
|
||||
- resolver: emailMatchingUserEntityProfileEmail
|
||||
- resolver: emailLocalPartMatchingUserEntityName
|
||||
- resolver: emailMatchingUserEntityAnnotation
|
||||
```
|
||||
|
||||
> Note: the resolvers will be tried in order, but will only be skipped if they throw a `NotFoundError`.
|
||||
@@ -848,7 +848,7 @@ Additional resolvers:
|
||||
|
||||
- [usernameMatchingUserEntityName](https://github.com/backstage/backstage/blob/5447cffd23cf00772988fb799ced0ec5e54efb2e/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts#L33C16-L33C46)
|
||||
|
||||
##### GCP IAM
|
||||
##### GCP IAP (Google Identity-Aware Proxy)
|
||||
|
||||
Setup:
|
||||
|
||||
|
||||
@@ -345,8 +345,8 @@ The `Dockerfile` mentioned above located in `packages/backend` is maintained by
|
||||
|
||||
### Minimal Hardened Image
|
||||
|
||||
A contributed `Dockerfile` exists within the directory of `contrib/docker/minimal-harded-image` which uses the [`wolfi-base`](https://github.com/wolfi-dev) image to reduce vulnerabilities. When this was contributed, this alternative `Dockerfile` reduced 98.2% of vulnerabilities in the built Backstage docker image when compared with the image built from `packages/backend/Dockerfile`.
|
||||
A contributed `Dockerfile` exists within the directory of `contrib/docker/minimal-hardened-image` which uses the [`wolfi-base`](https://github.com/wolfi-dev) image to reduce vulnerabilities. When this was contributed, this alternative `Dockerfile` reduced 98.2% of vulnerabilities in the built Backstage docker image when compared with the image built from `packages/backend/Dockerfile`.
|
||||
|
||||
To reduce maintenance, the digest of the image has been removed from the `contrib/docker/minimal-harded-image/Dockerfile` file. A complete example with the digest would be `cgr.dev/chainguard/wolfi-base:latest@sha256:3d6dece13cdb5546cd03b20e14f9af354bc1a56ab5a7b47dca3e6c1557211fcf` and it is suggested to update the `FROM` line in the `Dockerfile` to use a digest. Please do a docker pull on the image to get the latest digest. Using the digest allows tools such as Dependabot or Renovate to know exactly which image digest is being utilized and allows for Pull Requests to be triggered when a new digest is available.
|
||||
To reduce maintenance, the digest of the image has been removed from the `contrib/docker/minimal-hardened-image/Dockerfile` file. A complete example with the digest would be `cgr.dev/chainguard/wolfi-base:latest@sha256:3d6dece13cdb5546cd03b20e14f9af354bc1a56ab5a7b47dca3e6c1557211fcf` and it is suggested to update the `FROM` line in the `Dockerfile` to use a digest. Please do a docker pull on the image to get the latest digest. Using the digest allows tools such as Dependabot or Renovate to know exactly which image digest is being utilized and allows for Pull Requests to be triggered when a new digest is available.
|
||||
|
||||
It is suggested to setup Dependabot/Renovate or a similar tool to ensure the image is kept up to date so that vulnerability fixes that have been addressed are pulled in frequently.
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ more, read our blog post,
|
||||
|
||||
Yes, we've already started releasing open source versions of some of the plugins
|
||||
we use here, and we'll continue to do so.
|
||||
[Plugins](#what-is-a-plugin-in-backstage) are the building blocks of
|
||||
[Plugins](technical.md#what-is-a-plugin-in-backstage) are the building blocks of
|
||||
functionality in Backstage. We have over 120 plugins inside Spotify — many of
|
||||
those are specialized for our use, so will remain internal and proprietary to
|
||||
us. But we estimate that about a third of our existing plugins make good open
|
||||
|
||||
@@ -154,7 +154,7 @@ maintains Backstage in your own environment.
|
||||
|
||||
For more information, see our
|
||||
[Owners](https://github.com/backstage/backstage/blob/master/OWNERS.md) and
|
||||
[Governance](https://github.com/backstage/backstage/blob/master/GOVERNANCE.md).
|
||||
[Governance](https://github.com/backstage/community/blob/main/GOVERNANCE.md).
|
||||
|
||||
### Does Spotify provide a managed version of Backstage?
|
||||
|
||||
|
||||
@@ -6,4 +6,50 @@ sidebar_label: Configuring Extensions
|
||||
description: Documentation for how to configure extensions in a Backstage app
|
||||
---
|
||||
|
||||
TODO
|
||||
All extensions in a Backstage app can be configured through static configuration. This configuration is all done under the `app.extensions` configuration key. For more general information on how to write configuration for Backstage, see the section on [writing configuration](../../conf/writing.md).
|
||||
|
||||
## Extension Configuration Schema
|
||||
|
||||
This section focuses on the format of the `app.extensions` configuration and the various shorthands that are available.
|
||||
|
||||
The most complete and verbose format for configuring an individual extensions is as follows:
|
||||
|
||||
```yaml
|
||||
app:
|
||||
extensions:
|
||||
- <id>:
|
||||
attachTo:
|
||||
id: <parent-id>
|
||||
input: <input-name>
|
||||
disabled: <true/false>
|
||||
config: <extension-specific-config->
|
||||
```
|
||||
|
||||
All of the top-level fields are optional: `attachTo`, `disabled`, and `config`. Every extension implementation must provide defaults for all of these fields that will be used if they are not provided in the configuration.
|
||||
|
||||
Note that `app.extensions` is always an array rather than an object. For example, the following is invalid:
|
||||
|
||||
```yaml title="INVALID"
|
||||
app:
|
||||
extensions:
|
||||
<id>: # Invalid, this should be an array item, `app.extensions` is now an object
|
||||
config: ...
|
||||
```
|
||||
|
||||
In addition to this schema, there are a number of shorthands available:
|
||||
|
||||
Rather than a full object, you can specify just the ID of the extension as a string. This is equivalent to setting `disabled` to `false`:
|
||||
|
||||
```yaml
|
||||
app:
|
||||
extensions:
|
||||
- ‘<id>’
|
||||
```
|
||||
|
||||
You can enable/disable individual extension by ID, in this case the value is a boolean:
|
||||
|
||||
```yaml
|
||||
app:
|
||||
extensions:
|
||||
- <id>: <true/false>
|
||||
```
|
||||
|
||||
@@ -117,7 +117,7 @@ You can then also add any additional extensions that you may need to create as p
|
||||
|
||||
[Utility API](../utility-apis/01-index.md) factories are now installed as extensions instead. Pass the existing factory to `createApiExtension` and install it in the app. For more information, see the section on [configuring Utility APIs](../utility-apis/04-configuring.md).
|
||||
|
||||
For example, the following API configuration:
|
||||
For example, the following `apis` configuration:
|
||||
|
||||
```ts
|
||||
const app = createApp({
|
||||
@@ -151,15 +151,75 @@ Icons are currently installed through the usual options to `createApp`, but will
|
||||
|
||||
Plugins are now passed through the `features` options instead.
|
||||
|
||||
For example, the following `plugins` configuration:
|
||||
|
||||
```tsx
|
||||
import { homePlugin } from '@backstage/plugin-home';
|
||||
|
||||
createApp({
|
||||
// ...
|
||||
plugins: [homePlugin],
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
Can be converted to the following `features` configuration:
|
||||
|
||||
```tsx
|
||||
// plugins are now default exported via alpha subpath
|
||||
import homePlugin from '@backstage/plugin-home/alpha';
|
||||
|
||||
createApp({
|
||||
// ...
|
||||
features: [homePlugin],
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
Plugins don't even have to be imported manually after installing their package if [features discovery](../architecture/02-app.md#feature-discovery) is enabled.
|
||||
|
||||
```yaml title="in app-config.yaml"
|
||||
app:
|
||||
# Enabling plugin and override features discovery
|
||||
experimental: 'all'
|
||||
```
|
||||
|
||||
### `featureFlags`
|
||||
|
||||
Declaring features flags in the app is no longer supported, move these declarations to the appropriate plugins instead.
|
||||
|
||||
For example, the following app feature flags configuration:
|
||||
|
||||
```tsx
|
||||
createApp({
|
||||
// ...
|
||||
featureFlags: [
|
||||
{
|
||||
pluginId: '',
|
||||
name: 'tech-radar',
|
||||
description: 'Enables the tech radar plugin',
|
||||
},
|
||||
],
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
Can be converted to the following plugin configuration:
|
||||
|
||||
```tsx
|
||||
createPlugin({
|
||||
id: 'tech-radar',
|
||||
// ...
|
||||
featureFlags: [{ name: 'tech-radar' }],
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### `components`
|
||||
|
||||
Many app components are now installed as extensions instead using `createComponentExtension`. See the section on [configuring app components](./01-index.md#configure-your-app) for more information.
|
||||
|
||||
The `Router` component is now a built-in extension that you can override using `createRouterExtension`.
|
||||
The `Router` component is now a built-in extension that you can [override](../architecture/05-extension-overrides.md) using `createRouterExtension`.
|
||||
|
||||
The Sign-in page is now installed as an extension using the `createSignInPageExtension` instead.
|
||||
|
||||
@@ -277,6 +337,35 @@ const app = createApp({
|
||||
|
||||
Translations are now installed as extensions, using `createTranslationExtension`.
|
||||
|
||||
For example, the following translations configuration:
|
||||
|
||||
```tsx
|
||||
import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha';
|
||||
createApp({
|
||||
// ...
|
||||
__experimentalTranslations: {
|
||||
resources: [
|
||||
createTranslationMessages({
|
||||
ref: catalogTranslationRef,
|
||||
catalog_page_create_button_title: 'Create Software',
|
||||
}),
|
||||
],
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
Can be converted to the following extension:
|
||||
|
||||
```tsx
|
||||
createTranslationExtension({
|
||||
resource: createTranslationMessages({
|
||||
ref: catalogTranslationRef,
|
||||
catalog_page_create_button_title: 'Create Software',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
## Gradual Migration
|
||||
|
||||
After updating all `createApp` options as well as using `convertLegacyApp` to use your existing app structure, you should be able to start up the app and see that it still works. If that is not the case, make sure you read any error messages that you may see in the app as they can provide hints on what you need to fix. If you are still stuck, you can check if anyone else ran into the same issue in our [GitHub issues](https://github.com/backstage/backstage/issues), or ask for help in our [community Discord](https://discord.gg/backstage-687207715902193673).
|
||||
@@ -368,7 +457,7 @@ The entity pages are typically defined in `packages/app/src/components/catalog`
|
||||
|
||||
New apps feature a built-in sidebar extension (`app/nav`) that will render all nav item extensions provided by plugins. This is a placeholder implementation and not intended as a long-term solution. In the future we will aim to provide a more flexible sidebar extension that allows for more customization out of the box.
|
||||
|
||||
Because the built-in sidebar is quite limited you may want to override the sidebar with your own custom implementation. To do so, use `createExtension` directly and refer to the [original sidebar implementation](https://github.com/backstage/backstage/blob/master/packages/frontend-app-api/src/extensions/AppNav.tsx). The following is an example of how to take your existing sidebar from the `Root` component that you typically find in `packages/app/src/components/Root.tsx`, and use it in an extension override:
|
||||
Because the built-in sidebar is quite limited you may want to override the sidebar with your own custom implementation. To do so, use `createExtension` directly and refer to the [original sidebar implementation](https://github.com/backstage/backstage/blob/master/packages/frontend-app-api/src/extensions/AppNav.tsx). The following is an example of how to take your existing sidebar from the `Root` component that you typically find in `packages/app/src/components/Root.tsx`, and use it in an [extension override](../architecture/05-extension-overrides.md):
|
||||
|
||||
```tsx
|
||||
const nav = createExtension({
|
||||
@@ -435,3 +524,24 @@ export default app.createRoot(
|
||||
```
|
||||
|
||||
Any app root wrapper needs to be migrated to be an extension, using `createAppRootWrapperExtension`. Note that if you have multiple wrappers they must be completely independent of each other, i.e. the order in which they the appear in the React tree should not matter. If that is not the case then you should group them into a single wrapper.
|
||||
|
||||
Here is an example converting the `CustomAppBarrier` into extension:
|
||||
|
||||
```tsx
|
||||
createApp({
|
||||
// ...
|
||||
features: [
|
||||
createExtensionOverrides({
|
||||
extensions: [
|
||||
createAppRootWrapperExtension({
|
||||
name: 'CustomAppBarrier',
|
||||
// Whenever your component uses legacy core packages, wrap it with "compatWrapper"
|
||||
// e.g. props => compatWrapper(<CustomAppBarrier {...props} />)
|
||||
Component: CustomAppBarrier,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
---
|
||||
id: discovery--old
|
||||
title: Azure DevOps Discovery
|
||||
sidebar_label: Discovery
|
||||
# prettier-ignore
|
||||
description: Automatically discovering catalog entities from repositories in an Azure DevOps organization
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for the old backend which has been replaced by [the new backend system](../../backend-system/index.md), being the default since Backstage [version 1.24](../../releases/v1.24.0.md). If have migrated to the new backend system, you may want to read [its own article](./discovery.md) instead. Otherwise, [consider migrating](../../backend-system/building-backends/08-migrating.md)!
|
||||
:::
|
||||
|
||||
The Azure DevOps integration has a special entity provider for discovering
|
||||
catalog entities within an Azure DevOps. The provider will crawl your Azure
|
||||
DevOps organization and register entities matching the configured path. This can
|
||||
be useful as an alternative to static locations or manually adding things to the
|
||||
catalog.
|
||||
|
||||
This guide explains how to install and configure the Azure DevOps Entity Provider (recommended) or the Azure DevOps Processor.
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Code Search Feature
|
||||
|
||||
Azure discovery is driven by the Code Search feature in Azure DevOps, this may not be enabled by default. For Azure
|
||||
DevOps Services you can confirm this by looking at the installed extensions in your Organization Settings. For Azure
|
||||
DevOps Server you'll find this information in your Collection Settings.
|
||||
|
||||
If the Code Search extension is not listed then you can install it from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms.vss-code-search&targetId=f9352dac-ba6e-434e-9241-a848a510ce3f&utm_source=vstsproduct&utm_medium=SearchExtStatus).
|
||||
|
||||
### Azure Integration
|
||||
|
||||
Setup [Azure integration](locations.md) with `host` and `token`. Host must be `dev.azure.com` for Cloud users, otherwise set this to your on-premise hostname.
|
||||
|
||||
## Installation
|
||||
|
||||
At your configuration, you add one or more provider configs:
|
||||
|
||||
```yaml title="app-config.yaml"
|
||||
catalog:
|
||||
providers:
|
||||
azureDevOps:
|
||||
yourProviderId: # identifies your dataset / provider independent of config changes
|
||||
organization: myorg
|
||||
project: myproject
|
||||
repository: service-* # this will match all repos starting with service-*
|
||||
path: /catalog-info.yaml
|
||||
schedule: # optional; same options as in TaskScheduleDefinition
|
||||
# supports cron, ISO duration, "human duration" as used in code
|
||||
frequency: { minutes: 30 }
|
||||
# supports ISO duration, "human duration" as used in code
|
||||
timeout: { minutes: 3 }
|
||||
yourSecondProviderId: # identifies your dataset / provider independent of config changes
|
||||
organization: myorg
|
||||
project: '*' # this will match all projects
|
||||
repository: '*' # this will match all repos
|
||||
path: /catalog-info.yaml
|
||||
anotherProviderId: # another identifier
|
||||
organization: myorg
|
||||
project: myproject
|
||||
repository: '*' # this will match all repos
|
||||
path: /src/*/catalog-info.yaml # this will search for files deep inside the /src folder
|
||||
yetAnotherProviderId: # guess, what? Another one :)
|
||||
host: selfhostedazure.yourcompany.com
|
||||
organization: myorg
|
||||
project: myproject
|
||||
branch: development
|
||||
```
|
||||
|
||||
The parameters available are:
|
||||
|
||||
- **`host:`** _(optional)_ Leave empty for Cloud hosted, otherwise set to your self-hosted instance host.
|
||||
- **`organization:`** Your Organization slug (or Collection for on-premise users). Required.
|
||||
- **`project:`** _(required)_ Your project slug. Wildcards are supported as shown on the examples above. Using '\*' will search all projects. For a project name containing spaces, use both single and double quotes as in `project: '"My Project Name"'`.
|
||||
- **`repository:`** _(optional)_ The repository name. Wildcards are supported as show on the examples above. If not set, all repositories will be searched.
|
||||
- **`path:`** _(optional)_ Where to find catalog-info.yaml files. Defaults to /catalog-info.yaml.
|
||||
- **`branch:`** _(optional)_ The branch name to use.
|
||||
- **`schedule`**:
|
||||
- **`frequency`**:
|
||||
How often you want the task to run. The system does its best to avoid overlapping invocations.
|
||||
- **`timeout`**:
|
||||
The maximum amount of time that a single task invocation can take.
|
||||
- **`initialDelay`** _(optional)_:
|
||||
The amount of time that should pass before the first invocation happens.
|
||||
- **`scope`** _(optional)_:
|
||||
`'global'` or `'local'`. Sets the scope of concurrency control.
|
||||
|
||||
_Note:_
|
||||
|
||||
- The path parameter follows the same rules as the search on Azure DevOps web interface. For more details visit the [official search documentation](https://docs.microsoft.com/en-us/azure/devops/project/search/get-started-search?view=azure-devops).
|
||||
- To use branch parameters, it is necessary that the desired branch be added to the "Searchable branches" list within Azure DevOps Repositories. To do this, follow the instructions below:
|
||||
|
||||
1. Access your Azure DevOps and open the repository in which you want to add the branch.
|
||||
2. Click on "Settings" in the lower-left corner of the screen.
|
||||
3. Select the "Options" option in the left navigation bar.
|
||||
4. In the "Searchable branches" section, click on the "Add" button to add a new branch.
|
||||
5. In the window that appears, enter the name of the branch you want to add and click "Add".
|
||||
6. The added branch will now appear in the "Searchable branches" list.
|
||||
|
||||
It may take some time before the branch is indexed and searchable.
|
||||
|
||||
As this provider is not one of the default providers, you will first need to install
|
||||
the Azure catalog plugin:
|
||||
|
||||
```bash
|
||||
# From your Backstage root directory
|
||||
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-azure
|
||||
```
|
||||
|
||||
Once you've done that, you'll also need to add the segment below to `packages/backend/src/plugins/catalog.ts`:
|
||||
|
||||
```ts title="packages/backend/src/plugins/catalog.ts"
|
||||
/* highlight-add-next-line */
|
||||
import { AzureDevOpsEntityProvider } from '@backstage/plugin-catalog-backend-module-azure';
|
||||
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
/** ... other processors and/or providers ... */
|
||||
/* highlight-add-start */
|
||||
builder.addEntityProvider(
|
||||
AzureDevOpsEntityProvider.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
// optional: alternatively, use scheduler with schedule defined in app-config.yaml
|
||||
schedule: env.scheduler.createScheduledTaskRunner({
|
||||
frequency: { minutes: 30 },
|
||||
timeout: { minutes: 3 },
|
||||
}),
|
||||
// optional: alternatively, use schedule
|
||||
scheduler: env.scheduler,
|
||||
}),
|
||||
);
|
||||
/* highlight-add-end */
|
||||
```
|
||||
|
||||
## Alternative Processor
|
||||
|
||||
As an alternative to the entity provider `AzureDevOpsEntityProvider`, you can still use the `AzureDevopsDiscoveryProcessor`.
|
||||
|
||||
```ts title="packages/backend/src/plugins/catalog.ts"
|
||||
/* highlight-add-next-line */
|
||||
import { AzureDevOpsDiscoveryProcessor } from '@backstage/plugin-catalog-backend-module-azure';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
/* highlight-add-next-line */
|
||||
builder.addProcessor(
|
||||
AzureDevOpsDiscoveryProcessor.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
}),
|
||||
);
|
||||
|
||||
// ..
|
||||
}
|
||||
```
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
# Scan all repositories for a catalog-info.yaml in the root of the default branch
|
||||
- type: azure-discovery
|
||||
target: https://dev.azure.com/myorg/myproject
|
||||
# Or use a custom pattern for a subset of all repositories with default repository
|
||||
- type: azure-discovery
|
||||
target: https://dev.azure.com/myorg/myproject/_git/service-*
|
||||
# Or use a custom file format and location
|
||||
- type: azure-discovery
|
||||
target: https://dev.azure.com/myorg/myproject/_git/*?path=/src/*/catalog-info.yaml
|
||||
# And optionally provide a specific branch name using the version parameter
|
||||
- type: azure-discovery
|
||||
target: https://dev.azure.com/myorg/myproject/_git/*?path=/catalog-info.yaml&version=GBtopic/catalog-info
|
||||
```
|
||||
|
||||
Note the `azure-discovery` type, as this is not a regular `url` processor.
|
||||
|
||||
When using a custom pattern, the target is composed of these parts:
|
||||
|
||||
- The base instance URL, `https://dev.azure.com` in this case
|
||||
- The organization name which is required, `myorg` in this case
|
||||
- The project name which is optional, `myproject` in this case. This defaults to \*, which scans all the projects where the token has access to.
|
||||
- The repository blob to scan, which accepts \* wildcard tokens and must be
|
||||
added after `_git/`. This can simply be `*` to scan all repositories in the
|
||||
project.
|
||||
- The path within each repository to find the catalog YAML file. This will
|
||||
usually be `/catalog-info.yaml`, `/src/*/catalog-info.yaml` or a similar
|
||||
variation for catalog files stored in the root directory of each repository.
|
||||
- The repository branch to scan which is optional, `topic/catalog-info` in this case. If omitted, the repo's default branch will be scanned. The `GB` prefix is required, as this is how Azure DevOps identifies the version as a branch.
|
||||
@@ -6,6 +6,10 @@ sidebar_label: Discovery
|
||||
description: Automatically discovering catalog entities from repositories in an Azure DevOps organization
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](./discovery--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
|
||||
:::
|
||||
|
||||
The Azure DevOps integration has a special entity provider for discovering
|
||||
catalog entities within an Azure DevOps. The provider will crawl your Azure
|
||||
DevOps organization and register entities matching the configured path. This can
|
||||
@@ -30,7 +34,7 @@ Setup [Azure integration](locations.md) with `host` and `token`. Host must be `d
|
||||
|
||||
## Installation
|
||||
|
||||
At your configuration, you add one or more provider configs:
|
||||
In your configuration, you add one or more provider configs:
|
||||
|
||||
```yaml title="app-config.yaml"
|
||||
catalog:
|
||||
@@ -103,81 +107,11 @@ the Azure catalog plugin:
|
||||
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-azure
|
||||
```
|
||||
|
||||
Once you've done that, you'll also need to add the segment below to `packages/backend/src/plugins/catalog.ts`:
|
||||
Then updated your backend by adding the following line:
|
||||
|
||||
```ts title="packages/backend/src/plugins/catalog.ts"
|
||||
/* highlight-add-next-line */
|
||||
import { AzureDevOpsEntityProvider } from '@backstage/plugin-catalog-backend-module-azure';
|
||||
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
/** ... other processors and/or providers ... */
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
backend.add(import('@backstage/plugin-catalog-backend/alpha'));
|
||||
/* highlight-add-start */
|
||||
builder.addEntityProvider(
|
||||
AzureDevOpsEntityProvider.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
// optional: alternatively, use scheduler with schedule defined in app-config.yaml
|
||||
schedule: env.scheduler.createScheduledTaskRunner({
|
||||
frequency: { minutes: 30 },
|
||||
timeout: { minutes: 3 },
|
||||
}),
|
||||
// optional: alternatively, use schedule
|
||||
scheduler: env.scheduler,
|
||||
}),
|
||||
);
|
||||
backend.add(import('@backstage/plugin-catalog-backend-module-azure/alpha'));
|
||||
/* highlight-add-end */
|
||||
```
|
||||
|
||||
## Alternative Processor
|
||||
|
||||
As an alternative to the entity provider `AzureDevOpsEntityProvider`, you can still use the `AzureDevopsDiscoveryProcessor`.
|
||||
|
||||
```ts title="packages/backend/src/plugins/catalog.ts"
|
||||
/* highlight-add-next-line */
|
||||
import { AzureDevOpsDiscoveryProcessor } from '@backstage/plugin-catalog-backend-module-azure';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
/* highlight-add-next-line */
|
||||
builder.addProcessor(
|
||||
AzureDevOpsDiscoveryProcessor.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
}),
|
||||
);
|
||||
|
||||
// ..
|
||||
}
|
||||
```
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
# Scan all repositories for a catalog-info.yaml in the root of the default branch
|
||||
- type: azure-discovery
|
||||
target: https://dev.azure.com/myorg/myproject
|
||||
# Or use a custom pattern for a subset of all repositories with default repository
|
||||
- type: azure-discovery
|
||||
target: https://dev.azure.com/myorg/myproject/_git/service-*
|
||||
# Or use a custom file format and location
|
||||
- type: azure-discovery
|
||||
target: https://dev.azure.com/myorg/myproject/_git/*?path=/src/*/catalog-info.yaml
|
||||
# And optionally provide a specific branch name using the version parameter
|
||||
- type: azure-discovery
|
||||
target: https://dev.azure.com/myorg/myproject/_git/*?path=/catalog-info.yaml&version=GBtopic/catalog-info
|
||||
```
|
||||
|
||||
Note the `azure-discovery` type, as this is not a regular `url` processor.
|
||||
|
||||
When using a custom pattern, the target is composed of these parts:
|
||||
|
||||
- The base instance URL, `https://dev.azure.com` in this case
|
||||
- The organization name which is required, `myorg` in this case
|
||||
- The project name which is optional, `myproject` in this case. This defaults to \*, which scans all the projects where the token has access to.
|
||||
- The repository blob to scan, which accepts \* wildcard tokens and must be
|
||||
added after `_git/`. This can simply be `*` to scan all repositories in the
|
||||
project.
|
||||
- The path within each repository to find the catalog YAML file. This will
|
||||
usually be `/catalog-info.yaml`, `/src/*/catalog-info.yaml` or a similar
|
||||
variation for catalog files stored in the root directory of each repository.
|
||||
- The repository branch to scan which is optional, `topic/catalog-info` in this case. If omitted, the repo's default branch will be scanned. The `GB` prefix is required, as this is how Azure DevOps identifies the version as a branch.
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
---
|
||||
id: org--old
|
||||
title: Microsoft Entra Tenant Data
|
||||
sidebar_label: Org Data
|
||||
# prettier-ignore
|
||||
description: Importing users and groups from Microsoft Entra ID into Backstage
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for the old backend which has been replaced by [the new backend system](../../backend-system/index.md), being the default since Backstage [version 1.24](../../releases/v1.24.0.md). If have migrated to the new backend system, you may want to read [its own article](./org.md) instead.Otherwise, [consider migrating](../../backend-system/building-backends/08-migrating.md)!
|
||||
:::
|
||||
|
||||
The Backstage catalog can be set up to ingest organizational data - users and
|
||||
teams - directly from a tenant in Microsoft Entra ID via the
|
||||
Microsoft Graph API.
|
||||
|
||||
## Installation
|
||||
|
||||
The package is not installed by default, therefore you have to add `@backstage/plugin-catalog-backend-module-msgraph` to your backend package.
|
||||
|
||||
```bash
|
||||
# From your Backstage root directory
|
||||
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-msgraph
|
||||
```
|
||||
|
||||
Next add the basic configuration to `app-config.yaml`
|
||||
|
||||
```yaml title="app-config.yaml"
|
||||
catalog:
|
||||
providers:
|
||||
microsoftGraphOrg:
|
||||
default:
|
||||
tenantId: ${AZURE_TENANT_ID}
|
||||
user:
|
||||
filter: accountEnabled eq true and userType eq 'member'
|
||||
group:
|
||||
filter: >
|
||||
securityEnabled eq false
|
||||
and mailEnabled eq true
|
||||
and groupTypes/any(c:c+eq+'Unified')
|
||||
schedule:
|
||||
frequency: PT1H
|
||||
timeout: PT50M
|
||||
```
|
||||
|
||||
Finally, register the plugin in `catalog.ts`.
|
||||
For large organizations, this plugin can take a long time, so be careful setting low frequency / timeouts and importing a large amount of users / groups for the first try.
|
||||
|
||||
```ts title="packages/backend/src/plugins/catalog.ts"
|
||||
/* highlight-add-next-line */
|
||||
import { MicrosoftGraphOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-msgraph';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
|
||||
/* highlight-add-start */
|
||||
builder.addEntityProvider(
|
||||
MicrosoftGraphOrgEntityProvider.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
scheduler: env.scheduler,
|
||||
}),
|
||||
);
|
||||
/* highlight-add-end */
|
||||
|
||||
// ..
|
||||
}
|
||||
```
|
||||
|
||||
## Authenticating with Microsoft Graph
|
||||
|
||||
### Local Development
|
||||
|
||||
For a local dev environment, it's recommended you have the Azure CLI or Azure PowerShell installed, and are logged in to those.
|
||||
Alternatively you can use VSCode with the Azure extension if you install `@azure/identity-vscode`.
|
||||
When these are set up, the plugin will authenticate with the Microsoft Graph API without you needing to configure any credentials, or granting any special permissions.
|
||||
If you can't do this, you'll have to create an App Registration.
|
||||
|
||||
### App Registration
|
||||
|
||||
If none of the other authentication methods work, you can create an app registration in the azure portal.
|
||||
By default the graph plugin requires the following Application permissions (not Delegated) for Microsoft Graph:
|
||||
|
||||
- `GroupMember.Read.All`
|
||||
- `User.Read.All`
|
||||
|
||||
If your organization required Admin Consent for these permissions, that will need to be granted.
|
||||
|
||||
When authenticating with a ClientId/ClientSecret, you can either set the `AZURE_TENANT_ID`, `AZURE_CLIENT_ID` and `AZURE_CLIENT_SECRET` environment variables, or specify the values in configuration
|
||||
|
||||
```yaml
|
||||
microsoftGraphOrg:
|
||||
default:
|
||||
##...
|
||||
clientId: 9ef1aac6-b454-4e69-9cf5-7199df049281
|
||||
clientSecret: REDACTED
|
||||
```
|
||||
|
||||
To authenticate with a certificate rather than a client secret, you can set the `AZURE_TENANT_ID`, `AZURE_CLIENT_ID` and `AZURE_CLIENT_CERTIFICATE_PATH` environments
|
||||
|
||||
### Managed Identity
|
||||
|
||||
If deploying to resources that supports Managed Identity, and has identities configured (e.g. Azure App Services, Azure Container Apps), Managed Identity should be picked up without any additional configuration.
|
||||
If your app has multiple managed identities, you may need to set the `AZURE_CLIENT_ID` environment variable to tell Azure Identity which identity to use.
|
||||
|
||||
To grant the managed identity the same permissions as mentioned in _App Registration_ above, [please follow this guide](https://docs.microsoft.com/en-us/azure/app-service/tutorial-connect-app-access-microsoft-graph-as-app-javascript?tabs=azure-powershell)
|
||||
|
||||
## Filtering imported Users and Groups
|
||||
|
||||
By default, the plugin will import all users and groups from your directory.
|
||||
This can be customized through [filters](https://learn.microsoft.com/en-us/graph/filter-query-parameter) and [search](https://learn.microsoft.com/en-us/graph/search-query-parameter) queries. Keep in mind that if you omit filters and search queries for the user or group properties, the plugin will automatically import all available users or groups.
|
||||
|
||||
### Groups
|
||||
|
||||
A smaller set of groups can be obtained by configuring a search query or a filter.
|
||||
If both `filter` and `search` are provided, then groups must match both to be ingested.
|
||||
|
||||
```yaml
|
||||
microsoftGraphOrg:
|
||||
providerId:
|
||||
group:
|
||||
filter: securityEnabled eq false and mailEnabled eq true and groupTypes/any(c:c+eq+'Unified')
|
||||
search: '"description:One" AND ("displayName:Video" OR "displayName:Drive")'
|
||||
```
|
||||
|
||||
In addition to these groups, one additional group will be created for your organization.
|
||||
All imported groups will be a child of this group.
|
||||
|
||||
### Users
|
||||
|
||||
There are two modes for importing users - You can import all user objects matching a `filter`.
|
||||
|
||||
```yaml
|
||||
microsoftGraphOrg:
|
||||
providerId:
|
||||
user:
|
||||
filter: accountEnabled eq true and userType eq 'member'
|
||||
```
|
||||
|
||||
Alternatively you can import users that are members of specific groups.
|
||||
For each group matching the `search` and `filter` query, each group member will be imported.
|
||||
Only direct group members will be imported, not transient users.
|
||||
|
||||
```yaml
|
||||
microsoftGraphOrg:
|
||||
providerId:
|
||||
userGroupMember:
|
||||
filter: "displayName eq 'Backstage Users'"
|
||||
search: '"description:One" AND ("displayName:Video" OR "displayName:Drive")'
|
||||
```
|
||||
|
||||
### User photos
|
||||
|
||||
By default, the photos of users will be fetched and added to each user entity. For huge organizations this may be unfeasible, as it will take a _very_ long time, and can be disabled by setting `loadPhotos` to `false`:
|
||||
|
||||
```yaml
|
||||
microsoftGraphOrg:
|
||||
providerId:
|
||||
user:
|
||||
filter: ...
|
||||
loadPhotos: false
|
||||
```
|
||||
|
||||
## Customizing Transformation
|
||||
|
||||
Ingested entities can be customized by providing custom transformers.
|
||||
These can be used to completely replace the built in logic, or used to tweak it by using the default transformers (`defaultGroupTransformer`, `defaultUserTransformer` and `defaultOrganizationTransformer`
|
||||
Entities can also be excluded from backstage by returning `undefined`.
|
||||
|
||||
These Transformers are be registered when configuring `MicrosoftGraphOrgEntityProvider`
|
||||
|
||||
```ts
|
||||
builder.addEntityProvider(
|
||||
MicrosoftGraphOrgEntityProvider.fromConfig(env.config, {
|
||||
// ...
|
||||
/* highlight-add-start */
|
||||
groupTransformer: myGroupTransformer,
|
||||
userTransformer: myUserTransformer,
|
||||
organizationTransformer: myOrganizationTransformer,
|
||||
/* highlight-add-end */
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
When using custom transformers, you may want to customize the data returned.
|
||||
Several configuration options can be provided to tweak the Microsoft Graph query to get the data you need
|
||||
|
||||
```yaml
|
||||
microsoftGraphOrg:
|
||||
providerId:
|
||||
user:
|
||||
expand: manager
|
||||
group:
|
||||
expand: member
|
||||
select: ['id', 'displayName', 'description']
|
||||
```
|
||||
|
||||
The following provides an example of each kind of transformer
|
||||
|
||||
```ts
|
||||
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
|
||||
import {
|
||||
defaultGroupTransformer,
|
||||
defaultUserTransformer,
|
||||
defaultOrganizationTransformer,
|
||||
} from '@backstage/plugin-catalog-backend-module-msgraph';
|
||||
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
|
||||
|
||||
// This group transformer completely replaces the built in logic with custom logic.
|
||||
export async function myGroupTransformer(
|
||||
group: MicrosoftGraph.Group,
|
||||
groupPhoto?: string,
|
||||
): Promise<GroupEntity | undefined> {
|
||||
return {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Group',
|
||||
metadata: {
|
||||
name: group.id!,
|
||||
annotations: {},
|
||||
},
|
||||
spec: {
|
||||
type: 'Microsoft Entra ID',
|
||||
children: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// This user transformer makes use of the built in logic, but also sets the description field
|
||||
export async function myUserTransformer(
|
||||
graphUser: MicrosoftGraph.User,
|
||||
userPhoto?: string,
|
||||
): Promise<UserEntity | undefined> {
|
||||
const backstageUser = await defaultUserTransformer(graphUser, userPhoto);
|
||||
|
||||
if (backstageUser) {
|
||||
backstageUser.metadata.description = 'Loaded from Microsoft Entra ID';
|
||||
}
|
||||
|
||||
return backstageUser;
|
||||
}
|
||||
|
||||
// Example organization transformer that removes the organization group completely
|
||||
export async function myOrganizationTransformer(
|
||||
graphOrganization: MicrosoftGraph.Organization,
|
||||
): Promise<GroupEntity | undefined> {
|
||||
return undefined;
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No data
|
||||
|
||||
First check your logs for the message `Reading msgraph users and groups`.
|
||||
If you don't see this, check you've registered the provider, and that the schedule is valid
|
||||
|
||||
If you see a log entry `Read 0 msgraph users and 0 msgraph groups`, check your search and filter arguments.
|
||||
|
||||
If you see the start message (`Reading msgraph users and groups`) but no end message (`Read X msgraph users and Y msgraph groups`), then it is likely the job is taking a long time due to a large volume of data.
|
||||
The default behavior is to import all users and groups, which is often more data than needed.
|
||||
Try importing a smaller set of data (e.g. `filter: displayName eq 'John Smith'`).
|
||||
|
||||
### Authentication / Token Errors
|
||||
|
||||
See [Troubleshooting Azure Identity Authentication Issues](https://aka.ms/azsdk/js/identity/troubleshoot)
|
||||
|
||||
### Error while reading users from Microsoft Graph: Authorization_RequestDenied - Insufficient privileges to complete the operation
|
||||
|
||||
- Make sure you've granted all the required permissions to your application registration or managed identity
|
||||
- Make sure the permissions are `Application` permissions rather than `Delegated`
|
||||
- If your organization has configured "Admin consent" to be required, make sure this has been granted for your application permissions
|
||||
- If your group queries are returning Microsoft Teams groups, you may need to grant addition permissions (e.g. `Team.ReadBasic.All`, `TeamMember.Read.All`)
|
||||
- If you've added additional `select` or `expand` fields, those may need additional permissions granted
|
||||
@@ -6,6 +6,10 @@ sidebar_label: Org Data
|
||||
description: Importing users and groups from Microsoft Entra ID into Backstage
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for [the new backend system](../../backend-system/index.md) which is the default since Backstage [version 1.24](../../releases/v1.24.0.md). If you are still on the old backend system, you may want to read [its own article](./org--old.md) instead, and [consider migrating](../../backend-system/building-backends/08-migrating.md)!
|
||||
:::
|
||||
|
||||
The Backstage catalog can be set up to ingest organizational data - users and
|
||||
teams - directly from a tenant in Microsoft Entra ID via the
|
||||
Microsoft Graph API.
|
||||
@@ -39,29 +43,17 @@ catalog:
|
||||
timeout: PT50M
|
||||
```
|
||||
|
||||
Finally, register the plugin in `catalog.ts`.
|
||||
:::note
|
||||
For large organizations, this plugin can take a long time, so be careful setting low frequency / timeouts and importing a large amount of users / groups for the first try.
|
||||
:::
|
||||
|
||||
```ts title="packages/backend/src/plugins/catalog.ts"
|
||||
/* highlight-add-next-line */
|
||||
import { MicrosoftGraphOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-msgraph';
|
||||
Finally, updated your backend by adding the following line:
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
|
||||
/* highlight-add-start */
|
||||
builder.addEntityProvider(
|
||||
MicrosoftGraphOrgEntityProvider.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
scheduler: env.scheduler,
|
||||
}),
|
||||
);
|
||||
/* highlight-add-end */
|
||||
|
||||
// ..
|
||||
}
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
backend.add(import('@backstage/plugin-catalog-backend/alpha'));
|
||||
/* highlight-add-start */
|
||||
backend.add(import('@backstage/plugin-catalog-backend-module-msgraph/alpha'));
|
||||
/* highlight-add-end */
|
||||
```
|
||||
|
||||
## Authenticating with Microsoft Graph
|
||||
@@ -164,21 +156,6 @@ Ingested entities can be customized by providing custom transformers.
|
||||
These can be used to completely replace the built in logic, or used to tweak it by using the default transformers (`defaultGroupTransformer`, `defaultUserTransformer` and `defaultOrganizationTransformer`
|
||||
Entities can also be excluded from backstage by returning `undefined`.
|
||||
|
||||
These Transformers are be registered when configuring `MicrosoftGraphOrgEntityProvider`
|
||||
|
||||
```ts
|
||||
builder.addEntityProvider(
|
||||
MicrosoftGraphOrgEntityProvider.fromConfig(env.config, {
|
||||
// ...
|
||||
/* highlight-add-start */
|
||||
groupTransformer: myGroupTransformer,
|
||||
userTransformer: myUserTransformer,
|
||||
organizationTransformer: myOrganizationTransformer,
|
||||
/* highlight-add-end */
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
When using custom transformers, you may want to customize the data returned.
|
||||
Several configuration options can be provided to tweak the Microsoft Graph query to get the data you need
|
||||
|
||||
@@ -192,9 +169,53 @@ microsoftGraphOrg:
|
||||
select: ['id', 'displayName', 'description']
|
||||
```
|
||||
|
||||
The following provides an example of each kind of transformer
|
||||
### Using Custom Transformers
|
||||
|
||||
```ts
|
||||
Transformers can be configured by extending `microsoftGraphOrgEntityProviderTransformExtensionPoint`. Here is an example:
|
||||
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
import { createBackendModule } from '@backstage/backend-plugin-api';
|
||||
import { microsoftGraphOrgEntityProviderTransformExtensionPoint } from '@backstage/plugin-catalog-backend-module-msgraph/alpha';
|
||||
import {
|
||||
myUserTransformer,
|
||||
myGroupTransformer,
|
||||
myOrganizationTransformer,
|
||||
} from './transformers';
|
||||
|
||||
backend.add(
|
||||
createBackendModule({
|
||||
pluginId: 'catalog',
|
||||
moduleId: 'microsoft-graph-extensions',
|
||||
register(env) {
|
||||
env.registerInit({
|
||||
deps: {
|
||||
/* highlight-add-start */
|
||||
microsoftGraphTransformers:
|
||||
microsoftGraphOrgEntityProviderTransformExtensionPoint,
|
||||
/* highlight-add-end */
|
||||
},
|
||||
async init({ microsoftGraphTransformers }) {
|
||||
/* highlight-add-start */
|
||||
microsoftGraphTransformers.setUserTransformer(myUserTransformer);
|
||||
microsoftGraphTransformers.setGroupTransformer(myGroupTransformer);
|
||||
microsoftGraphTransformers.setOrganizationTransformer(
|
||||
myOrganizationTransformer,
|
||||
);
|
||||
/* highlight-add-end */
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
The `myUserTransformer`, `myGroupTransformer`, and `myOrganizationTransformer` transformer functions are from the examples in the section below.
|
||||
|
||||
### Transformer Examples
|
||||
|
||||
The following provides an example of each kind of transformer. We recommend creating a `transformers.ts` file in your `packages/backend/src` folder for these.
|
||||
|
||||
```ts title="packages/backend/src/transformers.ts"
|
||||
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
|
||||
import {
|
||||
defaultGroupTransformer,
|
||||
|
||||
@@ -27,7 +27,7 @@ yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-bitbuck
|
||||
### Installation with New Backend System
|
||||
|
||||
```ts
|
||||
// optional if you want HTTP endpojnts to receive external events
|
||||
// optional if you want HTTP endpoints to receive external events
|
||||
// backend.add(import('@backstage/plugin-events-backend/alpha'));
|
||||
// optional if you want to use AWS SQS instead of HTTP endpoints to receive external events
|
||||
// backend.add(import('@backstage/plugin-events-backend-module-aws-sqs/alpha'));
|
||||
|
||||
@@ -22,6 +22,8 @@ app:
|
||||
applicationId: qwerty
|
||||
# site: datadoghq.eu
|
||||
# env: 'staging'
|
||||
# sessionSampleRate: 100
|
||||
# sessionReplaySampleRate: 0
|
||||
```
|
||||
|
||||
If your [`app-config.yaml`](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/app-config.yaml#L5) file does not have this configuration, you may have to adjust your [`packages/app/public/index.html`](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/packages/app/public/index.html#L69) to include the Datadog RUM `init()` section manually.
|
||||
|
||||
@@ -125,6 +125,7 @@ integration:
|
||||
|
||||
- Reading software components:
|
||||
- `Contents`: `Read-only`
|
||||
- `Commit statuses`: `Read-only`
|
||||
- Reading organization data:
|
||||
- `Members`: `Read-only`
|
||||
- Publishing software templates:
|
||||
@@ -135,7 +136,6 @@ integration:
|
||||
- `Pull requests`: `Read & write`
|
||||
- `Issues`: `Read & write`
|
||||
- `Workflows`: `Read & write` (if templates include GitHub workflows)
|
||||
- `Commit statuses`: `Read-only`
|
||||
- `Variables`: `Read & write` (if templates include GitHub Action Repository Variables)
|
||||
- `Secrets`: `Read & write` (if templates include GitHub Action Repository Secrets)
|
||||
- `Environments`: `Read & write` (if templates include GitHub Environments)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
id: locations
|
||||
title: Harness Locations
|
||||
sidebar_label: Locations
|
||||
description: Integrating source code stored in Harness Code into the Backstage catalog
|
||||
---
|
||||
|
||||
The Harness Code integration supports loading catalog entities from a hosted repository. Entities can be added to
|
||||
[static catalog configuration](../../features/software-catalog/configuration.md),
|
||||
registered with the
|
||||
[catalog-import](https://github.com/backstage/backstage/tree/master/plugins/catalog-import)
|
||||
plugin.
|
||||
|
||||
## Configuration
|
||||
|
||||
To use this integration, add configuration to your root `app-config.yaml`:
|
||||
|
||||
```yaml
|
||||
integrations:
|
||||
harness:
|
||||
- host: app.harness.io
|
||||
token: ${HARNESS_CODE_BEARER_TOKEN}
|
||||
apiKey: ${HARNESS_CODE_APIKEY}
|
||||
```
|
||||
|
||||
Directly under the `harness` key is a list of provider configurations, where you
|
||||
can list the Harness instances you want to be able to fetch
|
||||
|
||||
check out https://developer.harness.io/docs/platform/automation/api/add-and-manage-api-keys/ for more information
|
||||
|
||||
- `host`: The host of the Harness Code instance that you want to match on.
|
||||
- `token` (optional): The password or api token to authenticate with.
|
||||
- `apiKey` (optional): The apiKey to authenticate with.
|
||||
@@ -20,7 +20,7 @@ info:
|
||||
|
||||
### Generating your client
|
||||
|
||||
1. Run `yarn backstage-repo-tools schema openapi generate client --output-package <directory>`. This will create a new folder in `<directory>/src/generated` to house the generated content.
|
||||
1. Run `yarn backstage-repo-tools package schema openapi generate client --client-package <directory>`. This will create a new folder in `<directory>/src/generated` to house the generated content.
|
||||
2. You should use the generated files as follows,
|
||||
|
||||
- `apis/DefaultApi.client.ts` - this is the client that you should use. It has types for all of the various operations on your API.
|
||||
|
||||
@@ -81,19 +81,21 @@ In order for Backstage to function properly the following versioning rules must
|
||||
be followed. The rules are referring to the
|
||||
[Package Architecture](https://backstage.io/docs/overview/architecture-overview#package-architecture).
|
||||
|
||||
- The versions of all the packages in the `Frontend App Core` must be from the
|
||||
same release, and it is recommended to keep `Common Tooling` on that release
|
||||
too.
|
||||
- The Backstage dependencies of any given plugin should be from the same
|
||||
release. This includes the packages from `Common Libraries`,
|
||||
`Frontend Plugin Core`, and `Frontend Libraries`, or alternatively the
|
||||
`Backend Libraries`.
|
||||
- There must be no package that is from a newer release than the
|
||||
`Frontend App Core` packages in the app.
|
||||
- The versions of all packages for each of the "App Core" groups must be from the
|
||||
same Backstage release.
|
||||
- For each frontend and backend setup, the "App Core" packages must be ahead of or on the same Backstage release as the "Plugin Core" packages, including transitive dependencies of all installed plugins and modules.
|
||||
- For any given plugin, the versions of all packages from the "Plugin Core" and
|
||||
"Library" groups must be from the same Backstage release.
|
||||
- Frontend plugins with a corresponding backend plugin should be from the same
|
||||
release. The update to the backend plugin **MUST** be deployed before or
|
||||
together with the update to the frontend plugin.
|
||||
|
||||
It is allowed and often expected that the "Plugin Core" and "Library" packages
|
||||
are from older releases than the "App Core" packages. It is also allowed to have
|
||||
duplicate installations of the "Plugin Core" and "Library" packages. This is all
|
||||
to make sure that upgrading Backstage is as smooth as possible and allows for
|
||||
more flexibility across the entire plugin ecosystem.
|
||||
|
||||
## Package Versioning Policy
|
||||
|
||||
Every individual package is versioned according to [semver](https://semver.org).
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ Additional steps for the main line release
|
||||
- Create Release Notes PR
|
||||
- Add the release note file as [`/docs/releases/vx.y.0.md`](./releases)
|
||||
- Add an entry to [`/microsite/sidebar.json`](https://github.com/backstage/backstage/blob/master/microsite/sidebars.json) for the release note
|
||||
- Update the navigation bar item in [`/microsite/docusaurus.config.js`](https://github.com/backstage/backstage/blob/master/microsite/docusaurus.config.js) to point to the new release note
|
||||
- Update the navigation bar item in [`/microsite/docusaurus.config.ts`](https://github.com/backstage/backstage/blob/master/microsite/docusaurus.config.ts) to point to the new release note
|
||||
- Finally copy the content, without the metadata header, into the description of the [`Version Packages` Pull Request](https://github.com/backstage/backstage/pulls?q=is%3Aopen+is%3Apr+in%3Atitle+%22Version+Packages)
|
||||
|
||||
Once the release has been published edit the newly created release in the [GitHub repository](https://github.com/backstage/backstage/releases) and replace the text content with the release notes.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -66,9 +66,9 @@ Speaking of reviewers and maintainers…
|
||||
|
||||
## Adding reviewers and maintainers
|
||||
|
||||
[](https://github.com/backstage/backstage/blob/master/GOVERNANCE.md#reviewers)
|
||||
[](https://github.com/backstage/community/blob/main/GOVERNANCE.md#reviewers)
|
||||
|
||||
We have introduced [reviewers](https://github.com/backstage/backstage/blob/master/GOVERNANCE.md#reviewers) to the project! By adding this new role, we’ve expanded the number of people who are permitted to approve and merge pull requests. This will offload some of the review work from the maintainers, simplifying and speeding up the review process for contributors.
|
||||
We have introduced [reviewers](https://github.com/backstage/community/blob/main/GOVERNANCE.md#reviewers) to the project! By adding this new role, we’ve expanded the number of people who are permitted to approve and merge pull requests. This will offload some of the review work from the maintainers, simplifying and speeding up the review process for contributors.
|
||||
|
||||
Of course, with these new efforts, we expect even more companies to adopt Backstage, which means the platform will continue to grow, and the number of PRs will continue to grow with it. As that happens, we hope to add to both the maintainer and reviewer teams in the future.
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ On Tuesday the Backstage maintainers hosted a jam-packed project meeting. The co
|
||||
|
||||

|
||||
|
||||
Core maintainers [Ben Lambert](https://github.com/benjdlambert) and [Patrik Oldsberg](https://github.com/Rugvip) took center stage on Wednesday for the Backstage Maintainer Track: State of Backstage in 2023 talk. Backstage has officially hit over 1,000 adopters and 1,000 contributors – so it’s apt timing to modernize the governance model for the project. Taking pointers from the [CNCF Contributor Ladder Governance Template](https://contribute.cncf.io/maintainers/templates/), a new [Backstage Governance Model](https://github.com/backstage/backstage/blob/master/GOVERNANCE.md) is now in effect! Patrik walked us through the new ladder model which introduces a number of changes, one being the addition of [project area maintainers](https://github.com/backstage/backstage/blob/master/GOVERNANCE.md#project-area-maintainer). This role lets members of the community take increased ownership over a specific area of interest, like Catalog, Discoverability, TechDocs, Helm Charts, and Kubernetes. New project areas that will be added include Permissions and Software Templates. New project areas can be proposed by nominating a project area maintainer for the area. The new model also adds an organization member role for contributors who want to take a more active role in the Backstage community. You can open an issue to become an organization member [here](https://github.com/backstage/community/issues/new/choose).
|
||||
Core maintainers [Ben Lambert](https://github.com/benjdlambert) and [Patrik Oldsberg](https://github.com/Rugvip) took center stage on Wednesday for the Backstage Maintainer Track: State of Backstage in 2023 talk. Backstage has officially hit over 1,000 adopters and 1,000 contributors – so it’s apt timing to modernize the governance model for the project. Taking pointers from the [CNCF Contributor Ladder Governance Template](https://contribute.cncf.io/maintainers/templates/), a new [Backstage Governance Model](https://github.com/backstage/community/blob/main/GOVERNANCE.md) is now in effect! Patrik walked us through the new ladder model which introduces a number of changes, one being the addition of [project area maintainers](https://github.com/backstage/community/blob/main/GOVERNANCE.md#project-area-maintainer). This role lets members of the community take increased ownership over a specific area of interest, like Catalog, Discoverability, TechDocs, Helm Charts, and Kubernetes. New project areas that will be added include Permissions and Software Templates. New project areas can be proposed by nominating a project area maintainer for the area. The new model also adds an organization member role for contributors who want to take a more active role in the Backstage community. You can open an issue to become an organization member [here](https://github.com/backstage/community/issues/new/choose).
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ For those who depended on these plugins, migrating is as simple as `yarn backsta
|
||||
|
||||
## The community plugins repo
|
||||
|
||||
Some of you who have been around a while, or have seen our [Maintainer Track talks](https://www.youtube.com/watch?v=ONMBYnhxnNU) at KubeCon, might have seen [this RFC](https://github.com/backstage/backstage/issues/20266) which outlines some issues with the scale of the `backstage/backstage` monorepo, and us as maintainers being the de facto owners of all plugins without a [project area](https://github.com/backstage/backstage/blob/master/GOVERNANCE.md#project-area) or [plugin maintainer](https://github.com/backstage/backstage/blob/master/GOVERNANCE.md#project-area-maintainer).
|
||||
Some of you who have been around a while, or have seen our [Maintainer Track talks](https://www.youtube.com/watch?v=ONMBYnhxnNU) at KubeCon, might have seen [this RFC](https://github.com/backstage/backstage/issues/20266) which outlines some issues with the scale of the `backstage/backstage` monorepo, and us as maintainers being the de facto owners of all plugins without a [project area](https://github.com/backstage/community/blob/main/GOVERNANCE.md#project-area) or [plugin maintainer](https://github.com/backstage/community/blob/main/GOVERNANCE.md#project-area-maintainer).
|
||||
|
||||
There was some great discussion in this issue, and some great ideas. One of the ideas was to create a dedicated home for community plugins, with all the burden of release tooling and workspace tooling already set up, which is a pretty big barrier for people wanting to create plugins for Backstage in their own organization or personal account. These plugins would then have the ability to release independently of the main monorepo, and have their own release cadence, which is something that we've been looking at exploring for a while.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ author: Marcin Kozlowski
|
||||
authorUrl: https://betterscan.io
|
||||
category: Security
|
||||
description: View security scanned vulnerabilities in Code and Cloud scanned using Open Source and proprietary scanners directly in Backstage.
|
||||
documentation: https://github.com/marcinguy/betterscan-ce
|
||||
documentation: https://www.npmjs.com/package/@marcinguy/backstage-plugin-betterscan
|
||||
iconUrl: https://uploads-ssl.webflow.com/6339e3b81867539b5fe2498d/633a1643dcb06d3029867161_g4.svg
|
||||
npmPackageName: '@marcinguy/backstage-plugin-betterscan'
|
||||
addedDate: '2022-12-08'
|
||||
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @type{import('prism-react-renderer').PrismTheme} **/
|
||||
// @ts-ignore
|
||||
const prismTheme = require('prism-react-renderer/themes/vsDark');
|
||||
prismTheme.plain.backgroundColor = '#232323';
|
||||
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
module.exports = {
|
||||
title: 'Backstage Software Catalog and Developer Platform',
|
||||
tagline: 'An open source framework for building developer portals',
|
||||
url: 'https://backstage.io',
|
||||
baseUrl: '/',
|
||||
organizationName: 'Spotify',
|
||||
projectName: 'backstage',
|
||||
scripts: [
|
||||
'https://buttons.github.io/buttons.js',
|
||||
'https://unpkg.com/medium-zoom@1.0.6/dist/medium-zoom.min.js',
|
||||
'/js/medium-zoom.js',
|
||||
'/js/dismissable-banner.js',
|
||||
'/js/scroll-nav-to-view-in-docs.js',
|
||||
],
|
||||
stylesheets: [
|
||||
'https://fonts.googleapis.com/css?family=IBM+Plex+Mono:500,700&display=swap',
|
||||
],
|
||||
favicon: 'img/favicon.ico',
|
||||
customFields: {
|
||||
fossWebsite: 'https://spotify.github.io/',
|
||||
repoUrl: 'https://github.com/backstage/backstage',
|
||||
},
|
||||
onBrokenLinks: 'log',
|
||||
onBrokenMarkdownLinks: 'log',
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
{
|
||||
docs: {
|
||||
editUrl: 'https://github.com/backstage/backstage/edit/master/docs/',
|
||||
path: '../docs',
|
||||
sidebarPath: 'sidebars.json',
|
||||
},
|
||||
blog: {
|
||||
path: 'blog',
|
||||
},
|
||||
theme: {
|
||||
customCss: 'src/theme/customTheme.scss',
|
||||
},
|
||||
gtag: {
|
||||
trackingID: 'G-KSEVGGNCJW',
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
markdown: {
|
||||
preprocessor({ fileContent }) {
|
||||
// Replace all HTML comments with empty strings as these are not supported by MDXv2.
|
||||
return fileContent.replace(/<!--.*?-->/gs, '');
|
||||
},
|
||||
format: 'detect',
|
||||
},
|
||||
webpack: {
|
||||
jsLoader: isServer => ({
|
||||
loader: require.resolve('swc-loader'),
|
||||
options: {
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
tsx: true,
|
||||
},
|
||||
target: 'es2017',
|
||||
},
|
||||
module: {
|
||||
type: isServer ? 'commonjs' : 'es6',
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
plugins: [
|
||||
'docusaurus-plugin-sass',
|
||||
() => ({
|
||||
name: 'yaml-loader',
|
||||
configureWebpack() {
|
||||
return {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ya?ml$/,
|
||||
use: 'yaml-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
}),
|
||||
[
|
||||
'@docusaurus/plugin-client-redirects',
|
||||
{
|
||||
redirects: [
|
||||
{
|
||||
from: '/docs',
|
||||
to: '/docs/overview/what-is-backstage',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/software-catalog/software-catalog-overview',
|
||||
to: '/docs/features/software-catalog/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/software-templates/software-templates-index',
|
||||
to: '/docs/features/software-templates/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/techdocs/techdocs-overview',
|
||||
to: '/docs/features/techdocs/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/kubernetes/overview',
|
||||
to: '/docs/features/kubernetes/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/search/search-overview',
|
||||
to: '/docs/features/search/',
|
||||
},
|
||||
{
|
||||
from: '/docs/getting-started/running-backstage-locally',
|
||||
to: '/docs/getting-started/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/software-templates/testing-scaffolder-alpha',
|
||||
to: '/docs/features/software-templates/migrating-to-rjsf-v5',
|
||||
},
|
||||
{
|
||||
from: '/docs/auth/glossary',
|
||||
to: '/docs/references/glossary',
|
||||
},
|
||||
{
|
||||
from: '/docs/overview/glossary',
|
||||
to: '/docs/references/glossary',
|
||||
},
|
||||
{
|
||||
from: '/docs/getting-started/create-an-app',
|
||||
to: '/docs/getting-started/',
|
||||
},
|
||||
{
|
||||
from: '/docs/getting-started/configuration',
|
||||
to: '/docs/getting-started/#next-steps',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
'docusaurus-pushfeedback',
|
||||
{
|
||||
project: 'q8w1i6cair',
|
||||
hideIcon: true,
|
||||
customFont: true,
|
||||
buttonStyle: 'dark',
|
||||
},
|
||||
],
|
||||
],
|
||||
themeConfig:
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
{
|
||||
colorMode: {
|
||||
defaultMode: 'dark',
|
||||
disableSwitch: true,
|
||||
},
|
||||
navbar: {
|
||||
logo: {
|
||||
alt: 'Backstage Software Catalog and Developer Platform',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
href: 'https://github.com/backstage/backstage',
|
||||
label: 'GitHub',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: 'docs/overview/what-is-backstage',
|
||||
label: 'Docs',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: '/plugins',
|
||||
label: 'Plugins',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: '/blog',
|
||||
label: 'Blog',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: 'docs/releases/v1.26.0',
|
||||
label: 'Releases',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: '/demos',
|
||||
label: 'Demos',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: '/community',
|
||||
label: 'Community',
|
||||
position: 'left',
|
||||
},
|
||||
],
|
||||
},
|
||||
image: 'img/sharing-opengraph.png',
|
||||
footer: {
|
||||
links: [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
html: `
|
||||
<a href="/" aria-label="Backstage Home">
|
||||
<div class="footerLogo"></div>
|
||||
</a>`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{
|
||||
label: 'What is Backstage?',
|
||||
to: 'docs/overview/what-is-backstage',
|
||||
},
|
||||
{
|
||||
label: 'Getting started',
|
||||
to: 'docs/getting-started/',
|
||||
},
|
||||
{
|
||||
label: 'Software Catalog',
|
||||
to: 'docs/features/software-catalog/',
|
||||
},
|
||||
{
|
||||
label: 'Create a Plugin',
|
||||
to: 'docs/plugins/create-a-plugin',
|
||||
},
|
||||
{
|
||||
label: 'Designing for Backstage',
|
||||
to: 'docs/dls/design',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'Support chatroom',
|
||||
to: 'https://discord.gg/backstage-687207715902193673',
|
||||
},
|
||||
{
|
||||
label: 'Contributing',
|
||||
to: 'https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md',
|
||||
},
|
||||
{
|
||||
label: 'Adopting',
|
||||
to: 'https://backstage.spotify.com',
|
||||
},
|
||||
{
|
||||
label: 'Subscribe to our newsletter',
|
||||
to: 'https://info.backstage.spotify.com/newsletter_subscribe',
|
||||
},
|
||||
{
|
||||
label: 'CNCF Incubation',
|
||||
to: 'https://www.cncf.io/projects/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'Open Source @ Spotify',
|
||||
to: 'https://spotify.github.io/',
|
||||
},
|
||||
{
|
||||
label: 'Spotify Engineering Blog',
|
||||
to: 'https://engineering.atspotify.com/',
|
||||
},
|
||||
{
|
||||
label: 'Spotify for Developers',
|
||||
to: 'https://developer.spotify.com/',
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
to: 'https://github.com/backstage/',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright:
|
||||
'<p style="text-align:center"><a href="https://spotify.github.io/">Made with ❤️ at Spotify</a></p><p class="copyright">Copyright © 2024 Backstage Project Authors. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our Trademark Usage page: https://www.linuxfoundation.org/trademark-usage</p>',
|
||||
},
|
||||
algolia: {
|
||||
apiKey: '1f0ba86672ccfc3576faa94583e5b318',
|
||||
indexName: 'crawler_Backstage Docusaurus 2',
|
||||
appId: 'JCMFNHCHI8',
|
||||
searchParameters: {},
|
||||
},
|
||||
prism: {
|
||||
theme: prismTheme,
|
||||
// Supported languages: https://prismjs.com/#supported-languages
|
||||
// Default languages: https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/generate-prism-languages/index.ts#L9-L23
|
||||
additionalLanguages: ['docker', 'bash'],
|
||||
magicComments: [
|
||||
// Extend the default highlight class name
|
||||
{
|
||||
className: 'code-block-highlight-line',
|
||||
line: 'highlight-next-line',
|
||||
block: { start: 'highlight-start', end: 'highlight-end' },
|
||||
},
|
||||
{
|
||||
className: 'code-block-add-line',
|
||||
line: 'highlight-add-next-line',
|
||||
block: { start: 'highlight-add-start', end: 'highlight-add-end' },
|
||||
},
|
||||
{
|
||||
className: 'code-block-remove-line',
|
||||
line: 'highlight-remove-next-line',
|
||||
block: {
|
||||
start: 'highlight-remove-start',
|
||||
end: 'highlight-remove-end',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @type{import('prism-react-renderer').PrismTheme} **/
|
||||
// @ts-ignore
|
||||
import { themes } from 'prism-react-renderer';
|
||||
import type * as Preset from '@docusaurus/preset-classic';
|
||||
import { Config } from '@docusaurus/types';
|
||||
const backstageTheme = themes.vsDark;
|
||||
backstageTheme.plain.backgroundColor = '#232323';
|
||||
|
||||
const config: Config = {
|
||||
title: 'Backstage Software Catalog and Developer Platform',
|
||||
tagline: 'An open source framework for building developer portals',
|
||||
url: 'https://backstage.io',
|
||||
baseUrl: '/',
|
||||
organizationName: 'Spotify',
|
||||
projectName: 'backstage',
|
||||
scripts: [
|
||||
'https://buttons.github.io/buttons.js',
|
||||
'https://unpkg.com/medium-zoom@1.0.6/dist/medium-zoom.min.js',
|
||||
'/js/medium-zoom.js',
|
||||
'/js/dismissable-banner.js',
|
||||
'/js/scroll-nav-to-view-in-docs.js',
|
||||
],
|
||||
stylesheets: [
|
||||
'https://fonts.googleapis.com/css?family=IBM+Plex+Mono:500,700&display=swap',
|
||||
],
|
||||
favicon: 'img/favicon.ico',
|
||||
customFields: {
|
||||
fossWebsite: 'https://spotify.github.io/',
|
||||
repoUrl: 'https://github.com/backstage/backstage',
|
||||
},
|
||||
onBrokenLinks: 'log',
|
||||
onBrokenMarkdownLinks: 'log',
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
{
|
||||
docs: {
|
||||
editUrl: 'https://github.com/backstage/backstage/edit/master/docs/',
|
||||
path: '../docs',
|
||||
sidebarPath: 'sidebars.json',
|
||||
},
|
||||
blog: {
|
||||
path: 'blog',
|
||||
},
|
||||
theme: {
|
||||
customCss: 'src/theme/customTheme.scss',
|
||||
},
|
||||
gtag: {
|
||||
trackingID: 'G-KSEVGGNCJW',
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
markdown: {
|
||||
preprocessor({ fileContent }) {
|
||||
// Replace all HTML comments with empty strings as these are not supported by MDXv2.
|
||||
function removeHtmlComments(input) {
|
||||
let previous;
|
||||
do {
|
||||
previous = input;
|
||||
input = input.replace(/<!--.*?-->/gs, '');
|
||||
} while (input !== previous);
|
||||
return input;
|
||||
}
|
||||
return removeHtmlComments(fileContent);
|
||||
},
|
||||
format: 'detect',
|
||||
},
|
||||
webpack: {
|
||||
jsLoader: isServer => ({
|
||||
loader: require.resolve('swc-loader'),
|
||||
options: {
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
tsx: true,
|
||||
},
|
||||
target: 'es2017',
|
||||
},
|
||||
module: {
|
||||
type: isServer ? 'commonjs' : 'es6',
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
plugins: [
|
||||
'docusaurus-plugin-sass',
|
||||
() => ({
|
||||
name: 'yaml-loader',
|
||||
configureWebpack() {
|
||||
return {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ya?ml$/,
|
||||
use: 'yaml-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
}),
|
||||
[
|
||||
'@docusaurus/plugin-client-redirects',
|
||||
{
|
||||
redirects: [
|
||||
{
|
||||
from: '/docs',
|
||||
to: '/docs/overview/what-is-backstage',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/software-catalog/software-catalog-overview',
|
||||
to: '/docs/features/software-catalog/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/software-templates/software-templates-index',
|
||||
to: '/docs/features/software-templates/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/techdocs/techdocs-overview',
|
||||
to: '/docs/features/techdocs/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/kubernetes/overview',
|
||||
to: '/docs/features/kubernetes/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/search/search-overview',
|
||||
to: '/docs/features/search/',
|
||||
},
|
||||
{
|
||||
from: '/docs/getting-started/running-backstage-locally',
|
||||
to: '/docs/getting-started/',
|
||||
},
|
||||
{
|
||||
from: '/docs/features/software-templates/testing-scaffolder-alpha',
|
||||
to: '/docs/features/software-templates/migrating-to-rjsf-v5',
|
||||
},
|
||||
{
|
||||
from: '/docs/auth/glossary',
|
||||
to: '/docs/references/glossary',
|
||||
},
|
||||
{
|
||||
from: '/docs/overview/glossary',
|
||||
to: '/docs/references/glossary',
|
||||
},
|
||||
{
|
||||
from: '/docs/getting-started/create-an-app',
|
||||
to: '/docs/getting-started/',
|
||||
},
|
||||
{
|
||||
from: '/docs/getting-started/configuration',
|
||||
to: '/docs/getting-started/#next-steps',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
'docusaurus-pushfeedback',
|
||||
{
|
||||
project: 'q8w1i6cair',
|
||||
hideIcon: true,
|
||||
customFont: true,
|
||||
buttonStyle: 'dark',
|
||||
},
|
||||
],
|
||||
],
|
||||
themeConfig: {
|
||||
colorMode: {
|
||||
defaultMode: 'dark',
|
||||
disableSwitch: true,
|
||||
},
|
||||
navbar: {
|
||||
logo: {
|
||||
alt: 'Backstage Software Catalog and Developer Platform',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
href: 'https://github.com/backstage/backstage',
|
||||
label: 'GitHub',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: 'docs/overview/what-is-backstage',
|
||||
label: 'Docs',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: '/plugins',
|
||||
label: 'Plugins',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: '/blog',
|
||||
label: 'Blog',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: 'docs/releases/v1.26.0',
|
||||
label: 'Releases',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: '/demos',
|
||||
label: 'Demos',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
to: '/community',
|
||||
label: 'Community',
|
||||
position: 'left',
|
||||
},
|
||||
],
|
||||
},
|
||||
image: 'img/sharing-opengraph.png',
|
||||
footer: {
|
||||
links: [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
html: `
|
||||
<a href="/" aria-label="Backstage Home">
|
||||
<div class="footerLogo"></div>
|
||||
</a>`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{
|
||||
label: 'What is Backstage?',
|
||||
to: 'docs/overview/what-is-backstage',
|
||||
},
|
||||
{
|
||||
label: 'Getting started',
|
||||
to: 'docs/getting-started/',
|
||||
},
|
||||
{
|
||||
label: 'Software Catalog',
|
||||
to: 'docs/features/software-catalog/',
|
||||
},
|
||||
{
|
||||
label: 'Create a Plugin',
|
||||
to: 'docs/plugins/create-a-plugin',
|
||||
},
|
||||
{
|
||||
label: 'Designing for Backstage',
|
||||
to: 'docs/dls/design',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'Support chatroom',
|
||||
to: 'https://discord.gg/backstage-687207715902193673',
|
||||
},
|
||||
{
|
||||
label: 'Contributing',
|
||||
to: 'https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md',
|
||||
},
|
||||
{
|
||||
label: 'Adopting',
|
||||
to: 'https://backstage.spotify.com',
|
||||
},
|
||||
{
|
||||
label: 'Subscribe to our newsletter',
|
||||
to: 'https://info.backstage.spotify.com/newsletter_subscribe',
|
||||
},
|
||||
{
|
||||
label: 'CNCF Incubation',
|
||||
to: 'https://www.cncf.io/projects/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'Open Source @ Spotify',
|
||||
to: 'https://spotify.github.io/',
|
||||
},
|
||||
{
|
||||
label: 'Spotify Engineering Blog',
|
||||
to: 'https://engineering.atspotify.com/',
|
||||
},
|
||||
{
|
||||
label: 'Spotify for Developers',
|
||||
to: 'https://developer.spotify.com/',
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
to: 'https://github.com/backstage/',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `<p style="text-align:center"><a href="https://spotify.github.io/">Made with ❤️ at Spotify</a></p><p class="copyright">Copyright © ${new Date().getFullYear()} Backstage Project Authors. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our Trademark Usage page: https://www.linuxfoundation.org/trademark-usage</p>`,
|
||||
},
|
||||
algolia: {
|
||||
apiKey: '1f0ba86672ccfc3576faa94583e5b318',
|
||||
indexName: 'crawler_Backstage Docusaurus 2',
|
||||
appId: 'JCMFNHCHI8',
|
||||
searchParameters: {},
|
||||
},
|
||||
prism: {
|
||||
theme: backstageTheme,
|
||||
// Supported languages: https://prismjs.com/#supported-languages
|
||||
// Default languages: https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/generate-prism-languages/index.ts#L9-L23
|
||||
additionalLanguages: ['docker', 'bash'],
|
||||
magicComments: [
|
||||
// Extend the default highlight class name
|
||||
{
|
||||
className: 'code-block-highlight-line',
|
||||
line: 'highlight-next-line',
|
||||
block: { start: 'highlight-start', end: 'highlight-end' },
|
||||
},
|
||||
{
|
||||
className: 'code-block-add-line',
|
||||
line: 'highlight-add-next-line',
|
||||
block: { start: 'highlight-add-start', end: 'highlight-add-end' },
|
||||
},
|
||||
{
|
||||
className: 'code-block-remove-line',
|
||||
line: 'highlight-remove-next-line',
|
||||
block: {
|
||||
start: 'highlight-remove-start',
|
||||
end: 'highlight-remove-end',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} satisfies Preset.ThemeConfig,
|
||||
};
|
||||
export default config;
|
||||
@@ -22,12 +22,14 @@
|
||||
"@docusaurus/core": "^3.1.1",
|
||||
"@docusaurus/plugin-client-redirects": "^3.1.1",
|
||||
"@docusaurus/preset-classic": "^3.1.1",
|
||||
"@docusaurus/types": "^3.1.1",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"@swc/core": "^1.3.46",
|
||||
"clsx": "^2.0.0",
|
||||
"docusaurus-plugin-sass": "^0.2.3",
|
||||
"docusaurus-pushfeedback": "^1.0.0",
|
||||
"luxon": "^3.0.0",
|
||||
"prism-react-renderer": "^1.3.5",
|
||||
"prism-react-renderer": "^2.1.0",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"sass": "^1.57.1",
|
||||
@@ -35,8 +37,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^3.1.1",
|
||||
"@docusaurus/tsconfig": "^3.1.1",
|
||||
"@spotify/prettier-config": "^15.0.0",
|
||||
"@tsconfig/docusaurus": "^2.0.0",
|
||||
"@types/luxon": "^3.0.0",
|
||||
"@types/webpack-env": "^1.18.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
|
||||
@@ -238,6 +238,11 @@
|
||||
"label": "Gitea",
|
||||
"items": ["integrations/gitea/locations"]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Harness",
|
||||
"items": ["integrations/harness/locations"]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Google GCS",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
||||
"extends": "@docusaurus/tsconfig",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user