These pages show Cloud's URLs. Sign in on Hosted and they show your server's.

Pub from CircleCI

CircleCI jobs read and publish your private packages with no stored secret: each job exchanges its own identity token for a Pub token that lasts 15 minutes. How it works on every provider is on Pub from CI.

BUILDDARTASTIC ARCHITECTUREUSERStokensissuesPub tokenpushCI exchangeapps ship to users: app stores, the web, serverssymbolscrashesstack tracessourcetelemetryDeveloper Computerflutter run · dart pub getCIGitHub Actions, GitLab, …Control Roommint tokens · role-based access controlControl Planeorganizations · roles · tokensDartastic Pubpackages · sourceObservatorysessions · traces · logsSymbolizercrashes → source linesDartastic AIanswers from bothIssue TrackerGitHub · Jira · LinearMobile + Desktop Appsphones · tablets · desktopssends with an OTLP tokenWeb Appsin browserssends with a Browser OTLP tokenDart Serversbackends · servicessends with an OTLP token

1. Trust the issuer

Each CircleCI organization has its own issuer, so an Owner adds it first: in CI access, under This organization's own CI issuers, choose CircleCI and enter the organization ID.

[TODO: screenshot of This organization's own CI issuers with CircleCI chosen and an organization ID entered]

2. Bind the repository

In the Control Room, open Organization, then CI access, Bind a repository, and choose CircleCI. The form asks for:

  • Project ID: in CircleCI, Project Settings, Overview.
  • Organization ID, optional: Organization Settings, Overview. Left out, it is read from the issuer.
  • Context ID, optional: a context the job must use (Organization Settings, Contexts). Its security groups then gate every exchange.
  • Ref pattern, optional: a branch or a tag: refs/tags/v* or refs/heads/main.

Then grant the binding its packages with its Packages button: read, or read and publish.

[TODO: screenshot of the Bind a repository dialog with the CircleCI issuer chosen and a project ID filled in]

3. Exchange in the job

Put your organization id, from the same Organization screen, in DARTASTIC_ORG_ID. This job publishes; for one that only reads, drop dart pub publish and grant the binding read only.

yaml
# .circleci/config.yml: publish on a version tag
version: 2.1
jobs:
  publish:
    docker:
      - image: dart:stable
    environment:
      DARTASTIC_ORG_ID: <your organization id>
    steps:
      - checkout
      - run: apt-get update -qq && apt-get install -y -qq jq
      - run:
          name: Exchange this job's identity for a 15-minute Pub token
          command: |
            OIDC=$(circleci run oidc get --aud https://dartastic.io)
            RESP=$(curl -sS --fail-with-body -X POST https://api.dartastic.io/v1/ci/exchange \
              -H "Authorization: Bearer $OIDC" -H "Content-Type: application/json" \
              -d "{\"orgId\":\"$DARTASTIC_ORG_ID\"}") || { echo "$RESP" >&2; exit 1; }
            export PUB_TOKEN=$(echo "$RESP" | jq -er .token)
            dart pub token add https://pub.dartastic.io --env-var PUB_TOKEN
            echo "export PUB_TOKEN=$PUB_TOKEN" >> "$BASH_ENV"
      - run: dart pub get
      - run: dart pub publish --force
workflows:
  release:
    jobs:
      - publish:
          filters:
            tags: { only: /^v.*/ }
            branches: { ignore: /.*/ }
  • circleci run oidc get --aud https://dartastic.io gives the job a token for this audience. The tokens CircleCI sets on its own carry your organization ID as their audience, so they are refused.
  • A job rerun with SSH is refused: a person at the shell could hold its token. Run it again without SSH.

When it is refused

The job's log shows the reason first, such as TRUSTED PUBLISHER REF MISMATCH. Every reason and what to do is on Pub from CI. CircleCI's own guide to its tokens is in its documentation.