Skip to content

Latest commit

 

History

History
276 lines (209 loc) · 21.7 KB

File metadata and controls

276 lines (209 loc) · 21.7 KB

DevOps - Pipeline and Workflow Examples

This repository contains a rich set of CI-CD demos where I show you how to:

  • Connect to private nuget feeds; Azure, GitHub packages, and custom (eg Telerik).
  • Build .NET apps and publish to a container registry; Docker, Azure, GitHub, etc.

Although I use Telerik's NuGet server in these demos, the approach works for any private feed; just substitute your source and credentials instead.

Table of Contents

Important

Some commerical Telerik packages are now available on nuget.org! If you are using any of these packages, you can restore using only the default nuget.org => Telerik.UI.for.Blazor Telerik.UI.for.Maui Telerik.Documents.*

CI Systems

System CI/CD file(s)
GitHub Actions .github/workflows
Azure DevOps (YAML) azure-pipelines.yml
Azure DevOps (classic) Click badge
GitLab CI/CD .gitlab-ci.yml
Tekton in Kuberbetes tekton-task-run.yaml

Badges

Project GitHub Actions Azure Pipelines YAML Azure DevOps Classic GitLab CI
.NET MAUI MAUI main Build Status Build - CLASSIC Build status
ASP.NET Core Build ASP.NET Core Application Build Status Build Status Build status
ASP.NET Blazor Build Blazor Application Build Status Build Status Build status
WPF WPF (.NET Framework) Build Status Build - CLASSIC Build status
WinForms WinForms (.NET Framework) Build Status Build - CLASSIC Build status
Console Console (.NET) Build Status AKEYLESS - Build status
WinUI Build WinUI3 Project Build Status - Build status
Kendo Angular Build Angular Build Status Build Status Build status
ASP.NET AJAX Build AJAX Application Build Status Build Status Build status

Tip

There are extra AzDO Classic pipelines examples for Blazor.

Using Azure KeyVault secrets Build Status

Docker Examples

These examples show how to build and publish container images. While they publish to Docker Hub, it works for any image registry.

Image GitHub Action Dockerfile Running Site
myblazorapp link live demo
aspnetcore-reporting-from-msftbase link live demo
aspnetcore-reporting-from-centosbase link -

Important

When creating a container, map port 8080 to the host. For example docker run -d -p 88:8080 lancemccarthy/myblazorapp:latest and then open http://localhost:88

Videos

Azure DevOps with Telerik NuGet Server

The following 4 minute video takes you though all the steps on adding a private NuGet feed as a Service Connection and consuming that service in three different pipeline setups.

YouTube tutorial

  • 0:09 Add a Service connection to the Telerik server
  • 1:14 Classic pipeline for .NET Core
  • 1:47 Classic .NET Framework pipeline
  • 2:25 YAML pipeline setup for .NET Core

Important

The recording has some outdated information, take the following updates into consideration when watching:

  • Use the v3 server address https://nuget.telerik.com/v3/index.json
  • Use an API key credential if your telerik.com account is SSO (see Announcing NuGet Keys).

Tips and Troubleshooting

GitHub Actions: Using Secrets to Set Environment Variables

If you have environment variable placeholders in your nuget.config file, you can easily set them using GitHub Secrets. For example, let's say in your packageSourceCredentials, you have the following the environment variable placeholders %TELERIK_USERNAME% and %TELERIK_PASSWORD%

<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
  <packageSourceCredentials>
    <Telerik_v3_Feed>
      <add key="Username" value="%TELERIK_USERNAME%" />
      <add key="ClearTextPassword" value="%TELERIK_PASSWORD%" />
    </Telerik_v3_Feed>
  </packageSourceCredentials>
  ...
</configuration>

You can directly set those vars on the same step which you invoke the dotnet restore/build/publish command. For example, here I use an API key from my GitHub Actions Secrets for credentials

    - name: Restore NuGet Packages
      run: dotnet restore src/MyProject.csproj --configfile src/nuget.config
      env:
        TELERIK_USERNAME: "api-key"
        TELERIK_PASSWORD: ${{secrets.TELERIK_API_KEY}}

Tip

This is also very useful for Dependabot runs. You can set a Dependabot secret (in the repo settings) and it will be able to restore packages during checks that were triggered by Dependabot.

Powershell: Adding or Updating Package Source Dynamically

Option 1 - Update existing package source

You could also dynamically update the credentials of a Package Source defined in your nuget.config file This is a good option when you do not want to use a packageSourceCredentials section that uses environment variables.

# Setting credentials for the 'Telerik_v3_Feed' defined in the nuget.config file.
dotnet nuget update source "Telerik_v3_Feed" -s "https://nuget.telerik.com/v3/index.json" -u '${{secrets.MyTelerikEmail}}' -p '${{secrets.MyTelerikPassword}}' --configfile "src/nuget.config" --store-password-in-clear-text

That command will look through the nuget.config for a package source with the key Telerik_v3_Feed and then add/update the credentials for that source.

Option 2 - Add a new package source

The other approach is a bit simpler because you dont need a custom nuget.config file. Just use the dotnet nuget add source command

dotnet nuget add source 'https://nuget.telerik.com/v3/index.json' -n "AddedTelerikServer" -u ${{secrets.MyTelerikEmail}} -p ${{secrets.MyTelerikPassword}} --store-password-in-clear-text

The --store-password-in-clear-text switch is important. It does not mean the password is visible, rather it means that you're using the password text and not a custom encrypted variant. For more information, please visit https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file#packagesourcecredentials

Using Telerik NuGet Keys

You can use the same approach in the previous section. Everything is exactly the same, except you use api-key for the username and the NuGet key for the password.

Please visit the Announcing NuGet Keys blog post for more details how ot create the key and how to use it.

dotnet nuget update source "Telerik_v3_Feed" -s "https://nuget.telerik.com/v3/index.json" -u 'api-key' -p '${{secrets.MyNuGetKey}}' --configfile "src/nuget.config" --store-password-in-clear-text

Caution

Protect your key by storing it in a GitHub Secret, then use the secret's ID in the command.

Dockerfile: Using Secrets

When using a Dockerfile to build a .NET project that uses the Telerik NuGet server, you'll need a safe and secure way to handle your NuGet crednetials and your Telerik License Key. This can be done my mounting a Docker secret.

In your GitHub Actions workflow, you can define and set docker secrets in the docker build step. In the following example, notice how we are setting two docker secrets (nuget-sec and license-sec) using the values from GitHub secrets.

    - uses: docker/build-push-action@v3
      with:
        secrets: |
          nuget-sec=${{secrets.MY_NUGET_KEY}}
          license-sec=${{secrets.MY_TELERIK_LICENSE_KEY}}

Now, inside the Dockerfile, you can mount and use those secrets. See Stage 2 in the following example:

### STAGE 1 ###
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
WORKDIR /app

### STAGE 2 ###
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY . .
# STEP 1. Mount the 'nuget-sec' secret, then:
# a. add the Telerik package source
# b. restore packages
RUN --mount=type=secret,id=nuget-sec,required \
    dotnet nuget add source 'https://nuget.telerik.com/v3/index.json' -n "Telerik_v3_Feed" -u "api-key" -p "$(cat /run/secrets/nuget-sec)" --store-password-in-clear-text \
    && \
    dotnet restore "MyBlazorApp.csproj"
# STEP 2. Mount the "license-sec" secret, then:
# a. create the license file
# b. build the project
# c. delete the file so you don't distribute it in your image (important!)
RUN --mount=type=secret,id=license-key,required \
    mkdir -p ~/.telerik  && echo "$(cat /run/secrets/license-sec)" > ~/.telerik/telerik-license.txt \
    && \
    dotnet publish "Researcher.Web/Researcher.Web.csproj" -o /app/publish /p:UseAppHost=false --no-restore --self-contained false \
    && \
    rm -rf ~/.telerik

### STAGE 3 ###
# Build final from base, but copy ONLY THE PUBLISH ARTIFACTS from stage 2
FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyBlazorApp.dll"]

Caution

Pay attention to whether or not you are including any secrets in your final image. You can run your container to explore the files (and env vars in Exec) to make sure.

Telerik License Approaches

With introduction of Deployment Keys, you can now generate a small license key with only the products you need in it.

This much smaller key value will meet even the smallest of CI system's variable size limits You can now generate a very small JWT that contains only the products you need, drastically reducing the key size.

  1. Go to https://www.telerik.com/account/downloads/deployment-keys
  2. Click "Add Application" and select only the products that the project uses
    • classic pipeline secrets
  3. Once saved, click "COPY KEY" and paste it into a secret pipeline variable (e.g. BLAZOR_REPORTING_DEPLOYMENT_KEY)
  4. Set the TELERIK_LICENSE environment variable at build time. Here are some examples:

Deployment Key in GitHub Actions

  1. In the repo's Actions settings, create a new secret named BLAZOR_REPORTING_DEPLOYMENT_KEY with the value in your clipboard
  2. In the YAML, set the TELERIK_LICENSE environment variable to ${{secrets.BLAZOR_REPORTING_DEPLOYMENT_KEY}}.
  - run: dotnet publish MyApp.csproj -o /app/publish
    env:
      TELERIK_LICENSE: ${{secrets.BLAZOR_REPORTING_DEPLOYMENT_KEY}}

Deployment Key in GitLab CI

  1. Go into the project's settings, then CI, and create a BLAZOR_REPORTING_DEPLOYMENT_KEY secret.
  2. In the YAML, set the set the TELERIK_LICENSE environment variable to $BLAZOR_REPORTING_DEPLOYMENT_KEY.
build-blazor-app:
  tags:
    - saas-windows-medium-amd64
  variables:
    TELERIK_LICENSE: $BLAZOR_REPORTING_DEPLOYMENT_KEY
  script:
    - |
      dotnet publish MyApp.csproj -o /app/publish
      ...

Deployment Key in Azure YAML Pipeline

  1. Open the Variables pane in the YAML editor, and create a new secret pipeline variable BLAZOR_REPORTING_DEPLOYMENT_KEY
  2. In the YAML, set the TELERIK_LICENSE environment variable to $(BLAZOR_REPORTING_DEPLOYMENT_KEY)
  - powershell: dotnet publish MyApp.csproj -o /app/publish
    env:
      TELERIK_LICENSE: $(BLAZOR_REPORTING_DEPLOYMENT_KEY) # AzDO pipeline **secret** variable

Deployment Key in Azure Classic Pipeline

  1. In classic pipelines, you can directly set the TELERIK_LICENSE variable and click the lock 🔒 icon to make it a secret.

Image