Forum Discussion

dinunoroc's avatar
dinunoroc
New Member
10 hours ago

Deploy a Fabric app with GitHub Actions

I followed every step from the documentation page and I cannot make it work.

The Error I am receiving is:

Deployment failed: Runtime settings sync failed: 403 Forbidden
Details: Could not verify Build permission on semantic model '895b5565-1234-4cff-a0e0-5d322exxxxxx'. Ensure you have Build access, then re-add the connector.
RootActivityId: 6c714e3a-f1f0-4989-85f3-978885985189
Diagnostic log: /home/runner/.rayfin/logs/2026-10-14T152715.236Z-up-56ba7c69-00ff-4450-b13d-0e5b3c4d9ede.log

Tried with Service Principal ad a Contributor and as a Member

name: Deploy to Fabric

on:
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      force:
        description: 'Allow destructive schema changes that may result in data loss'
        required: false
        default: false
        type: boolean

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

jobs:
  deploy:
    name: Deploy to Fabric
    runs-on: ubuntu-latest
    defaults:
      run:
        # The Rayfin project (rayfin/rayfin.yml, package.json, bun.lock) lives here, not at the repo root
        working-directory: used-cars-app
    env:
      CLIENT_ID: ${{ secrets.CLIENT_ID }}
      TENANT_ID: ${{ secrets.TENANT_ID }}
      CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }}
      FABRIC_WORKSPACE_NAME: ${{ secrets.FABRIC_WORKSPACE_NAME }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

      # Installs the app's build tools (vite, tsc) and the Rayfin CLI version pinned in bun.lock
      - name: Install dependencies
        run: bun install --frozen-lockfile

      # The CLI loads keytar, which links against libsecret even when it falls back to a plaintext token cache
      - name: Install libsecret
        run: sudo apt-get update && sudo apt-get install -y libsecret-1-0

      # The runner has no OS keychain, so let the CLI cache its token in a file between steps
      - name: Login to Rayfin with service principal
        run: |
          npx rayfin login \
            --service-principal \
            --tenant "$TENANT_ID" \
            --client-id "$CLIENT_ID" \
            --client-secret "$CLIENT_SECRET" \
            --encryption-fallback-enabled

      - name: Deploy to Fabric
        run: |
          EXTRA_ARGS=""

          if [[ "${{ inputs.force }}" == "true" ]]; then
            EXTRA_ARGS="$EXTRA_ARGS --force"
          fi

          npx rayfin up \
            --workspace "$FABRIC_WORKSPACE_NAME" \
            --yes \
            --encryption-fallback-enabled \
            $EXTRA_ARGS

7 Replies

  • Have you tested that you can deploy one of the Fabric App samples okay in the same workspace? For example, the ToDo example? 

  • Hi dinunoroc​,

    The error is fairly clear here, the semantic model with the ID of 895b5565-1234-4cff-a0e0-5d322exxxxxx is upset because whatever credential you're using doesn't have build permissions. 

    Grant build permissions on that model to the service principal and try again.  

    • dinunoroc's avatar
      dinunoroc
      New Member

      I granted access to the Service Principal in the workspace. Tried with member and contributor roles. 
      When I am checking access to the semantic model that the app is connected to, the SP has all the rights. 

  • jubinsoni's avatar
    jubinsoni
    Icon for Continued Contributor rankContinued Contributor

    Hi dinunoroc​,

    The error is specific: the deploy authenticates fine and can write the app item, but the runtime settings sync step checks that the deploying identity, your service principal, has Build on the semantic model referenced by the fabric-semanticmodel connector. The GitHub Actions guide only lists Contributor on the target workspace, which covers the app item, not the connected model.

    The most common reason Contributor/Member still isn't enough:

    rayfin.yml connector
      workspaceId: <model workspace>   <- often NOT the deploy workspace
      itemId:      895b5565-...
    
    SP is Contributor on the deploy workspace
    -> but has no role / no Build on the model's workspace
    -> 403 "Could not verify Build permission"

    Check the workspaceId in the connector config first. If the model lives in a different workspace, give the SP access there. Either option works:

    option A: add the SP to the model's workspace as Contributor
              (workspace roles Contributor+ include Build on its models)
    option B: share only the model with the SP, with Build
              (Manage permissions on the semantic model)

    Option B is the least-privilege route, and it can be scripted with the Power BI REST API. "ReadExplore" is Read + Build:

    Connect-PowerBIServiceAccount   # as a model owner / workspace admin
    
    $ws    = "<model-workspace-id>"
    $model = "895b5565-1234-4cff-a0e0-5d322exxxxxx"
    
    $body = @{
        identifier             = "<service-principal-object-id>"   # enterprise app object ID
        principalType          = "App"
        datasetUserAccessRight = "ReadExplore"
    } | ConvertTo-Json
    
    Invoke-PowerBIRestMethod -Method Post `
        -Url "groups/$ws/datasets/$model/users" -Body $body

    Note the identifier is the Enterprise application object ID, not the app registration's client ID. Mixing those up is a common cause of "permission granted but still 403".

    Two other things worth confirming with your Fabric admin, since both affect only service principals:

    tenant setting: service principals can use Fabric / Power BI APIs
      -> if scoped to a security group, the SP must be in it
    the model's workspace must allow API access for that SP
      (same tenant setting applies there too)

    After granting Build, re-run the workflow as is; the error message's "re-add the connector" shouldn't be needed once the permission check passes. Also keep in mind that the semantic model connector uses delegated auth at runtime, so app users still need their own access to the model. The SP's Build only matters for deployment.

    Your other thread's notes on the sample workflow (missing line continuations, the $ on CLIENT_SECRET, libsecret on ubuntu-latest) are spot on as well. Worth submitting as feedback on the docs page.

    So my overall approach would be:

    check connector workspaceId vs deploy workspace
    -> grant the SP Build on that model (or Contributor on its workspace)
    -> use the Enterprise app object ID when sharing via API
    -> confirm the SP tenant setting covers it
    -> re-run rayfin up

    AI-assisted drafting: AI was used to help structure and phrase this response. I reviewed and validated the technical content before posting.

    • dinunoroc's avatar
      dinunoroc
      New Member

      Thank you. It is very detailed. I will try your suggestions.