Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Setting Up Trusted Publishing

Trusted publishing is the recommended way to publish new releases for projects managed in GitHub or GitLab, as it avoids needing to keep a secret token secret. It works by instead declaring to Sysand Index that you trust automation in GitHub Actions or GitLab CI to publish new releases of a project.

Understand the Security Benefit

With an account or project API token, a CI system needs to store a long-lived secret that can publish releases until it is revoked. If that token leaks through logs, exported CI configuration, or a compromised developer machine, an attacker can publish malicious versions before you notice.

With trusted publishing, the CI system does not store a Sysand Index publishing token. Instead, GitHub Actions or GitLab CI requests a fresh short lived OpenID Connect token for the publish job. Sysand Index verifies that token against the trusted publisher configuration, then mints a short-lived upload token scoped to the matching project.

This also links each release to the configured repository, workflow or pipeline file, and environment. Users of your package can treat the release as having come from that trusted automation, rather than from anyone who once had access to a reusable token.

Before you continue

If you are publishing a project for the first time, first publish it with a quickly expiring account API token by following Publishing your first project.

If you don’t version control your Sysand project yet, first set it up under either GitHub or GitLab. Details on doing this are not part of this tutorial.

You need enough access to configure the CI environment before publishing. On GitHub, this means repository admin access. On GitLab, Developer access can create an unprotected environment, while Maintainer access is needed to protect the environment or configure deployment approvals.

Add the Trusted Publisher

Go to Projects, then click Manage on the project you want to configure, then click the publishing tab.

Under the Add a new publisher header, choose the GitHub or GitLab tab, and fill in and submit the relevant details as described below, also under a provider-specific tab.

GitHub Actions
GitLab CI

Fill in:

  • Repository full name: the GitHub owner and repository in owner/repository form, such as my-org/my-project

  • Workflow filename: the file name under .github/workflows/, such as release.yaml

  • Environment: the GitHub Actions environment name, such as sysand

Press Add GitHub publisher.

Create the CI Environment

GitHub and GitLab have a concept of CI environments, and we need to create one in the repository or project. Using environments helps constrain what parts of the CI automation should be allowed to publish to Sysand Index.

GitHub Actions
GitLab CI

Go to your GitHub project and navigate through Settings -> Environments, and then click the New environment button. You should now be at a URL looking like https://github.com/my-org/my-project/settings/environments/new.

Fill in the name sysand and press Configure environment.

We recommend also configuring the environment to require manual approval.

Add the CI Configuration

After adding the trusted publisher, copy the matching CI configuration example below into the repository that you registered as the trusted publisher.

The examples reference https://sysand.com, but you should update SYSAND_INDEX_URL to for example https://test.sysand.com if that is where you added the trusted publisher.

GitHub Actions
GitLab CI

Copy this example to .github/workflows/release.yaml.

# This is a GitHub workflow, defining a set of jobs each with a set of steps.
#
# The workflow will run when a git tag like v1.2.3 is pushed, and publish a
# release to the chosen sysand index using trusted publishing.
#
# trusted publishing reference:  https://docs.sysand.com/tutorial/setting-up-trusted-publishing
# workflow config reference:     https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
# installation script reference: https://client.sysand.com/getting-started/installation#macos-and-linux
#
name: Release

on:
  push:
    tags: ["v*"]

env:
  SYSAND_INDEX_URL: https://sysand.com

jobs:
  test:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6

      - name: Install sysand
        run: |
          curl -fsSL https://client.sysand.com/install.sh | sh -s -- --version latest

      - name: Check version in git tag matches the project's declared version
        run: |
          PROJECT_VERSION="$(sysand info version)"
          TAG_VERSION="${GITHUB_REF_NAME#v}"
          if [ "$PROJECT_VERSION" != "$TAG_VERSION" ]; then
            echo "Project version ${PROJECT_VERSION} does not match tag ${GITHUB_REF_NAME}"
            exit 1
          fi

  publish:
    runs-on: ubuntu-latest
    needs: [test]
    environment: sysand
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v6

      - name: Install sysand
        run: |
          curl -fsSL https://client.sysand.com/install.sh | sh -s -- --version latest

      - name: Acquire and configure sysand index credentials
        run: |
          GITHUB_OIDC_TOKEN=$(
            curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
              "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sysand" \
            | grep -o '"value": *"[^"]*"' \
            | cut -d'"' -f4 \
          )
          SYSAND_INDEX_TOKEN=$(
            curl -s -X POST "${SYSAND_INDEX_URL}/api/v1/oidc/token" \
              -H "Content-Type: application/json" \
              -d "{\"token\": \"${GITHUB_OIDC_TOKEN}\"}" \
            | grep -o '"token": *"[^"]*"' \
            | cut -d'"' -f4 \
          )
          echo "SYSAND_CRED_X=${SYSAND_INDEX_URL}/api/v1/**" >> "$GITHUB_ENV"
          echo "SYSAND_CRED_X_BEARER_TOKEN=$SYSAND_INDEX_TOKEN" >> "$GITHUB_ENV"

      - name: Build and publish a project to the index
        run: |
          sysand build --update-meta
          sysand publish --index "${SYSAND_INDEX_URL}"

Test the Automation

Push a Git Tag

To test the publishing workflow, first update the Sysand project version to the version you want to publish, commit it, and push a tag. While this can be done in a few ways, here is one.

sysand info version --set 1.2.3

Commit that version change and push it to the registered repository:

git add .project.json
git commit -m "Release 1.2.3"
git push

Then create and push a matching tag:

git tag v1.2.3
git push origin v1.2.3

This should now trigger the configured CI automation to run.

Inspect the Triggered CI Automation

After pushing the tag, inspect the CI run for the provider you configured.

GitHub Actions
GitLab CI

Go to your GitHub project and click the Actions tab.

Open the Release workflow run for the tag you pushed, such as v1.2.3. If the sysand environment requires approval, approve the deployment before the publish job starts.

Open the test job and check that it verifies the tag version against the declared Sysand project version. Then open the publish job and check that the steps install sysand, acquire Sysand Index credentials, and publish the project.

When the publish step succeeds, go to Projects, then click the project.

Check that the new release appears and that the rendered README, changelog, licenses, and usages look correct.

If the Token Exchange Fails

Use the error message from the CI job to narrow the problem:

If the token exchange succeeds but upload fails, troubleshoot it like any other publish failure. The short-lived token can only publish to the matched project, and each version can be published only once. For archive validation issues, see KPAR archive validation.