SWIRL for Backstage

Source: GitHub

This page connects GitHub as a federated source. GitHub results appear in the Backstage search page under the swirl-federated document type, alongside catalog and TechDocs results.

Federated GitHub results use one credential for every portal user. Read Security first.

What you get

SWIRL ships four GitHub SearchProviders, inactive out of the box. Activate the ones you want.

Provider GitHub API Returns
Code - GitHub /search/code Matching files, with the matching fragment as the body.
Issues - GitHub /search/issues Issues, with state, assignees, and labels.
PRs - GitHub /search/issues Pull requests, with state and merge date.
Commits - GitHub /search/commits Commits, with author and date.

Step 1: create a service account and token

Do not use a personal token belonging to an engineer. Create a machine account, give it access only to the repositories the portal should search, and issue the token from that account.

  1. Create a GitHub account for the portal, or use an existing machine account.
  2. Add it to the repositories or the organisation with read access only.
  3. Create a fine-grained personal access token owned by that account. Grant Contents: Read-only for code search, and Issues: Read-only and Pull requests: Read-only for the other providers.
  4. Select repositories explicitly rather than granting access to all repositories.
  5. Set an expiry and note the renewal date.

The token is stored in the SWIRL database on the /data volume. Treat that volume as a secret store, and back it up accordingly.

Step 2: set the scope restriction

SWIRL will not activate a provider tagged GitHub unless its query carries repo:, org:, or user:. The shipped template already has the shape, with a placeholder to replace:

{url}?q={query_string}+repo:<your-org>/<your-repo>

Replace the placeholder with a real target. Both of these are accepted:

{url}?q={query_string}+repo:acme/platform
{url}?q={query_string}+org:acme

An organisation-wide org: scope means every portal user can search every repository that token can read in that organisation. Prefer a repository list where you can.

Step 3: edit the provider in SWIRL

Open the SWIRL admin UI at http://localhost:8000/admin/ and sign in as admin with the value you set in SWIRL_ADMIN_PASSWORD on the container. That variable is on the compose block on the install page. If it was never set, there is no password to sign in with: set it, recreate the container, and try again.

Open Search providers, which lists every shipped provider, and click Code - GitHub. Edit these fields.

Field Set it to
Query template The scoped template from step 2, with your organisation and repository.
Credentials bearer=<your-token>, using the token from step 1. The field is masked once saved, so it shows a placeholder rather than the token. Retyping it replaces it; leaving it alone keeps it.
Tags Confirm backstage is present. The four shipped GitHub providers already carry it. The engine module fans out to the tags in federated.providerTags, which defaults to ["backstage"].
Active Tick it. Saving with an unscoped query is refused here.
Results per query Leave at 10 unless you have a reason to change it.

Repeat for Issues - GitHub, PRs - GitHub, and Commits - GitHub if you want them. Each has its own template with the same placeholder.

Or via the API

The same change over HTTP, for a bootstrap script or a CI job. SWIRL requires a CSRF cookie and header on a write even when the request carries a token, so fetch the cookie first. The provider id, 23 below, is in the admin URL and in the list response.

csrf=$(curl -s -c jar http://localhost:8000/admin/login/ -o /dev/null; grep csrftoken jar | awk '{print $NF}')
curl -X PATCH http://localhost:8000/swirl/sapi/searchproviders/23/ \
  -H "Authorization: Token <admin-api-token>" \
  -H "Content-Type: application/json" \
  -H "X-CSRFToken: $csrf" -H "Cookie: csrftoken=$csrf" \
  -H "Referer: http://localhost:8000/swirl/sapi/searchproviders/23/" \
  -d '{"query_template":"{url}?q={query_string}+repo:acme/platform","credentials":"bearer=<token>","active":true}'

Two things to know. The write path is /swirl/sapi/searchproviders/; /swirl/searchproviders/ answers 403 to a token. And a token on its own, with no CSRF cookie and header, is refused with {"detail":"CSRF Failed: CSRF cookie not set."}.

Query SWIRL directly first, so a failure is unambiguous:

curl -s -H "Authorization: Token <admin-api-token>" \
    "http://localhost:8000/swirl/search/?qs=readme&providers=backstage"

The messages array in the response names each provider that answered and how many results it returned. A provider that failed reports its error there.

Then search in Backstage. GitHub results appear with the document type swirl-federated. If they do not, see Troubleshooting.

Other sources

Confluence is the other source in this release, on its own page. Jira, GitLab, and further sources are planned. No dates are set. SWIRL Community already carries Jira and GitLab scope rules, and SWIRL itself connects to many more sources than the two documented here. See the SearchProvider Guide.