Skip to content

Build Pipeline

DGT-ALM-060 — This is the canonical order of steps for building a Dataverse project at DIGITALL, independent of whether the orchestrator is Azure DevOps, GitHub Actions, or a script run by Power Platform Pipelines' extensibility hooks. Individual platform chapters (Azure DevOps, GitHub Actions, Power Platform Pipelines) show how to wire these steps into that platform's syntax; this page is the thing to point at when reviewing whether a pipeline is missing a step.

Step order

  1. Resolve the build version. Compute the SemVer for this build from Git history (see Versioning). Everything downstream is stamped with this single version.

  2. Restore & build client-side projects. For web resources: pnpm install, Biome lint, webpack production bundle (pnpm run build:prod); PCF controls use their pac-scaffolded npm build. Output goes to the folder referenced by the solution's web resource mapping. See TypeScript Web Resources.

  3. Regenerate early-bound models — before compiling server-side code. Run dgtp codegeneration against the build environment so that .cs/.ts models reflect the current Dataverse schema. This must happen before step 4, since server-side projects reference the generated model. See Early-Bound Models.

  4. Bump the solution version in the build environment. dgtp maintenance solution-version <solution> --build (or --revision for a hotfix). This step and codegeneration (step 3) don't depend on each other and can run in either order — but both must complete before the solution export in step 7.

  5. Build & package server-side projects. Compile plugin/Custom API projects, producing the plugin package .nupkg (see Plugin Packages). The assembly version stamped here is the same SemVer resolved in step 1.

  6. Push server-side artifacts to the build environment. dgtp push <package>.nupkg --solution <name> --publish registers/updates the PluginPackage, PluginAssembly, plugin types, steps, and step images — see Pre- & Post-Deployment Tasks for what this does under the hood. Push web resources the same way: dgtp push ./WebResources --solution <name> --publish.

  7. Export & pack the solution. pac solution export (or sync an already-checked-out unpacked solution via pac solution sync) followed by pac solution pack, producing the managed/unmanaged solution .zip that becomes the pipeline artifact.

  8. Run the Solution Checker. pac solution check against the packed solution as a quality gate — see Solution Checker. A failing high-severity result stops the pipeline here.

  9. Run automated tests. Server-side unit tests against Digitall.Dataverse.Testing (no live environment needed), plus any client-side tests. See Testing & Quality.

  10. Publish the build artifact. The packed solution .zip, plus any deployment settings / data files needed for config & reference data migration, become the artifact that later release stages deploy — via Power Platform Pipelines, a release pipeline, or a follow-up Actions job.

flowchart TD
    A["1 - Resolve build version"] --> B["2 - Build client-side (TS/PCF)"]
    A --> C["3 - dgtp codegeneration"]
    C --> D["5 - Build server-side, produce .nupkg"]
    B --> G["7 - Export and pack solution"]
    D --> G
    A --> E["4 - dgtp maintenance solution-version"]
    E --> G
    D --> F["6 - dgtp push (.nupkg, web resources)"]
    F --> G
    G --> H["8 - Solution Checker"]
    H --> I["9 - Automated tests"]
    I --> J["10 - Publish artifact"]

Why this order matters

The two steps most often placed wrong:

  • Codegeneration before server-side build, not after. If you build the plugin project against a stale generated model, the build succeeds but the plugin silently uses outdated field names at runtime — a much worse failure mode than a build error.
  • Solution version bump before export, not after. pac solution export bakes whatever version is currently on the environment into solution.xml. Bumping after export has no effect on the artifact you're about to ship.

CI credentials

DGT-ALM-070 — Use token-based (--msal, service principal / client secret) dgtp profiles for CI — never store a personal account's credentials in a pipeline. Two equivalent wirings satisfy this: create a token-based profile in the pipeline from a secret (dgtp profile create build "..." --msal, as the Azure DevOps and GitHub Actions examples do), or skip the profile entirely and set the dgtp:xrm:connection environment variable from the secret (see dgtp CLI → Connecting). Either way, the credential is a service principal held in the pipeline's secret store.

Local builds (developer workstation)

A developer running the same steps locally during a feature loop does not need the version bump (step 4) or the tag-creation that follows a successful pipeline run — only CI should bump solution and Git versions. Steps 2, 3, 5, and 6 are exactly what a developer runs locally against their own dev environment; see Repository Bootstrap for the equivalent local commands.