# CI/CD

> Publish a WPF app with TX Text Control from a pipeline: GitHub Actions workflow on windows-latest with feed secrets, win-x64 artifact, Azure Pipelines, licx.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Deployment Guide > CI/CD
- **1667 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/deployment/ci-cd/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/deployment/ci-cd/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/deployment/ci-cd/llms-full.txt

---

Continuous integration builds your WPF application on every push, and a publish step at the end of the pipeline turns the build into a deployable folder. With TX Text Control .NET for WPF, the pipeline has to restore `TXTextControl.TextControl.WPF.SDK` from a feed with credentials, run on Windows and publish for the platform you ship. [Build Servers](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/installation/licensing/build-servers/llms-full.txt) covers the restore and the license rules; what follows adds a complete workflow and the publish step.

### Requirements of a Build Server

- **Windows.** Text Control's pipelines for WPF and Windows Forms projects run on a Windows image, such as `windows-latest`.
- **Feed credentials as secrets.** The package comes from the Text Control Private NuGet Feed or from a feed of your own, never from nuget.org. The pipeline writes *nuget.config* from secrets, so the credentials stay out of the repository.
- **No developer license.** A build server needs no license of its own, under the conditions listed in [What the License Agreement Allows](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/installation/licensing/build-servers/#what-the-license-agreement-allows).

### A GitHub Actions Workflow

This workflow runs on `windows-latest`, restores the package from the private feed, publishes the WPF project for `win-x64` and keeps the result as an artifact of the run. Add the repository secrets `TEXTCONTROL_FEED_URL` (the feed URL `https://www.textcontrol.com/nuget/v3/index.json`), `TEXTCONTROL_EMAIL` (the email address of a licensed developer) and `TEXTCONTROL_API_TOKEN` (that developer's API token), save the workflow as *.github/workflows/publish.yml*, and change *WpfApp/WpfApp.csproj* to your project:

```yaml
name: Publish

on:
  push:
    branches: [ "master" ]

jobs:
  publish:
    runs-on: windows-latest

    steps:
    - uses: actions/checkout@v4

    - name: Setup .NET
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: 8.0.x

    - name: Create nuget.config
      shell: pwsh
      run: |
        $content = @"
        <?xml version="1.0" encoding="utf-8"?>
        <configuration>
          <packageSources>
            <clear />
            <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
            <add key="TextControl" value="${{ secrets.TEXTCONTROL_FEED_URL }}" />
          </packageSources>
          <packageSourceCredentials>
            <TextControl>
              <add key="Username" value="${{ secrets.TEXTCONTROL_EMAIL }}" />
              <add key="ClearTextPassword" value="${{ secrets.TEXTCONTROL_API_TOKEN }}" />
            </TextControl>
          </packageSourceCredentials>
        </configuration>
        "@
        Set-Content -Path "nuget.config" -Value $content -Encoding utf8

    - name: Publish
      run: dotnet publish WpfApp/WpfApp.csproj -c Release -r win-x64 --self-contained false -o publish

    - name: Upload artifact
      uses: actions/upload-artifact@v4
      with:
        name: wpfapp-win-x64
        path: publish
```

What each step contributes:

- **`runs-on: windows-latest`** selects a Windows agent for the WPF project.
- **Setup .NET** installs the SDK. Set `dotnet-version` to the version your project targets, such as `10.0.x`.
- **Create nuget.config** writes the package sources and the credentials into the root of the repository at run time; neither appears in the repository or the log. The package the feed delivers carries your license, so no other license step is needed.
- **Publish** restores, builds and publishes in one command. `-r win-x64` places the 64-bit native libraries of TX Text Control in *publish*; use `-r win-x86` for a 32-bit build.
- **Upload artifact** keeps the publish folder, which holds no license file and no *nuget.config*.

Text Control's article [Building a TX Text Control Project with GitHub Actions and the Text Control NuGet Feed](https://www.textcontrol.com/blog/2026/02/09/building-a-tx-text-control-project-with-github-actions-and-the-text-control-nuget-feed/) shows where to find the email address and the token, how to add the secrets and how to run tests in the workflow.

### Azure Pipelines

For Azure Pipelines, Text Control describes a pipeline for WPF and Windows Forms projects on a `windows-latest` agent that restores the package from Azure Artifacts with `NuGetCommand@2` and builds with `VSBuild@1`. [Build With Your Own Feed](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/installation/licensing/build-servers/#build-with-your-own-feed) summarizes it, and the blog article [Azure Pipelines with TX Text Control .NET for WPF and Windows Forms 32.0 with Azure DevOps and Artifacts](https://www.textcontrol.com/blog/2024/01/05/azure-pipelines-with-tx-text-control-net-for-wpf-and-windows-forms-320-with-azure-devops-and-artifacts/) has the complete YAML. Add the `dotnet publish` command of the workflow above as a script step to get a deployable folder.

### .NET Framework Projects

A WPF project for the .NET Framework is licensed through *licenses.licx* and the license compiler, which needs the assemblies of an installed setup. Hosted agents can't run the setup, so the license is compiled once on a development machine and added to the project as an embedded resource; see [.NET Framework Projects](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/installation/licensing/build-servers/#net-framework-projects). Collect the files for deployment as [Deploying .NET Framework Applications](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/deployment/dotnet-framework/llms-full.txt) describes.

### Pin the Package Version

Every build should restore the same package, so reference a fixed version of `TXTextControl.TextControl.WPF.SDK`, such as 34.0.5, and raise it deliberately when a service pack is released. [Update to a New Service Pack](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/installation/nuget/install-update/#update-to-a-new-service-pack) describes the update.

### Next Steps

- [Build Servers](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/installation/licensing/build-servers/llms-full.txt): the license rules and both ways to restore the package.
- [Configuring Package Sources](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/installation/nuget/sources/llms-full.txt): the private feed and *nuget.config*.
- [Publishing .NET Applications](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/deployment/dotnet/llms-full.txt): the content of the publish folder.

---

## Nearby

- **Previous:** [MSIX Packaging and Microsoft Store Deployment](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/deployment/msix/llms-full.txt)
- **Next:** [Security](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/security/llms-full.txt)
