PlatformEngr® Backstage course

Module 10 · Ship it · 60 min · You are: Platform and product

Capstone: onboard team-payments

In this module

  • You learn: Nothing new: the capstone checks you can use everything together.
  • You do: As the platform team, add team-payments and its system. As team-payments, create payments-api from the template. As the platform team, ship and prove it in the image.
  • You end with: team-payments exists, owns payments-api and the payments system, and you are a member. The image runs it all.

Onboarding a team is what a portal is for. If you can do it without the steps, you know where every piece lives and who owns it.

Open this module in the interactive course to track progress.

Concepts

Acceptance criteria
Each challenge lists what must be true at the end. Check them yourself before you open the solution.

Files to know

Open them in your editor or on GitHub; the bullets say what to look at.

Steps

1. Platform: add team-payments (Challenge)

Done when:

Hint 1

Copy team-checkout's Group and the shop System and rename.

Hint 2

Ownership Entities are read at sign-in: sign out and in.

One solution

Three edits in the portal repo, one pull request.

Add to ~/work/portal/catalog/org.yaml after the team-checkout Group

---
apiVersion: backstage.io/v1alpha1
kind: Group
metadata:
  name: team-payments
  title: Team Payments
spec:
  type: team
  parent: acme
  children: []

Change in ~/work/portal/catalog/org.yaml

-   children: [platform, team-checkout]
+   children: [platform, team-checkout, team-payments]

Change in ~/work/portal/catalog/org.yaml

-   memberOf: [platform, team-checkout]
+   memberOf: [platform, team-checkout, team-payments]

Add to ~/work/portal/catalog/systems.yaml at the end

---
apiVersion: backstage.io/v1alpha1
kind: System
metadata:
  name: payments
  description: Taking the money.
spec:
  owner: team-payments
  domain: commerce
cd ~/work/portal

Propose it as a pull request. Put it on its own branch and push it:

git switch -c onboard-team-payments && git add -A && git commit -qm "Catalog: onboard team-payments"
git push -qu origin HEAD

Open the pull request. It prints a link:

gh pr create --fill

Open that link in your browser. Files changed shows exactly your diff.

Merge it on GitHub (Squash and merge, then Delete branch), or from the terminal:

gh pr merge --squash --delete-branch

Either way, bring your copy up to date:

git switch -q main && git pull -q

2. team-payments: a new service (Challenge)

Done when:

Hint 1

Start the dev portal again (yarn start with .env loaded).

Hint 2

Check relations with the catalog API, like in module 03.

One solution

The template does it all; you only check.

Create → Node.js service: name payments-api, owner Team Payments, system payments, repository YOUR_GITHUB_USER/payments-api.

curl -s -H "Authorization: Bearer $PORTAL_API_TOKEN" localhost:7007/api/catalog/entities/by-name/component/default/payments-api | jq -r '.relations[] | .type + " " + .targetRef'

3. Platform: ship and prove it (Challenge)

Done when:

Hint 1

Same commands as module 09.

Hint 2

Discovery finds payments-api on its first scan, about 15 seconds after start.

One solution

Build, fresh database, run, check.

cd ~/work/portal && git switch -q main && git pull -q && yarn install --immutable && yarn tsc && yarn build:backend && yarn build-image
docker rm -f portal-prod-db && docker run -d --name portal-prod-db --network portal-net -e POSTGRES_PASSWORD=portal-prod postgres:17.11
cd ~/work/portal && set -a && . ./.env && set +a
docker run --rm --name portal --network portal-net -p 7007:7007 \
  -e POSTGRES_HOST=portal-prod-db -e POSTGRES_PORT=5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=portal-prod \
  -e PORTAL_API_TOKEN -e GITHUB_TOKEN -e AUTH_GITHUB_CLIENT_ID -e AUTH_GITHUB_CLIENT_SECRET \
  backstage
curl -s -H "Authorization: Bearer $PORTAL_API_TOKEN" localhost:7007/api/catalog/entities/by-name/component/default/payments-api | jq -r '.relations[] | .type + " " + .targetRef'

4. Tear down

Your portal and checkout repos keep everything; the plugins course starts from them. Remove what you do not need.

docker rm -f portal-prod-db && docker network rm portal-net

Deleting repos needs an extra scope once:

gh auth refresh -s delete_repo && gh repo delete YOUR_GITHUB_USER/cart --yes && gh repo delete YOUR_GITHUB_USER/payments-api --yes

Quiz

  1. What did onboarding team-payments need from the platform team?
    • A Group, a System and a membership in org.yaml and systems.yaml, through a pull request
    • A new plugin
    • A new portal for the team
  2. What did team-payments need from the platform team to create a service?
    • A ticket per repo
    • Nothing: the template and discovery do the rest
    • Admin rights on the portal
  3. What would you automate next with a third team?
    • Copying org.yaml by hand
    • More hand-registered locations
    • Importing teams and users from GitHub or your identity provider with an org provider
Answers
  1. A Group, a System and a membership in org.yaml and systems.yaml, through a pull request The catalog files are the onboarding interface.
  2. Nothing: the template and discovery do the rest That is the point of a golden path.
  3. Importing teams and users from GitHub or your identity provider with an org provider Typing people into YAML does not scale.

Field note

If you did this without the solutions, you can run a Backstage portal for a company. Plugins are the next step: the plugins course builds one on this portal.

Report a problem with this module