Back to Blog
DevOps

Publishing .NET NuGet Packages to AWS CodeArtifact Using GitHub Actions (OIDC)

3 min read
Publishing .NET NuGet Packages to AWS CodeArtifact Using GitHub Actions (OIDC)

Overview

Publishing internal .NET libraries securely is a common challenge for DevOps teams—especially when multiple services share common packages. In this post, we’ll build a secretless pipeline to publish NuGet packages to AWS CodeArtifact using GitHub Actions + OIDC, so no static AWS keys are stored in GitHub.


What You’ll Build

A two-workflow setup:

  • CI workflow: build + pack on branch/PR (no publish)
  • Publish workflow: publish on release tag (or manual trigger)

This gives you governance (tag-driven releases) and clean separation between build and release.


Architecture Flow

  1. Developer pushes code to GitHub
  2. CI builds and generates .nupkg
  3. Publish pipeline assumes AWS role via OIDC
  4. Package is pushed to CodeArtifact
  5. Apps restore from the private feed

Prerequisites

  • AWS CodeArtifact domain + repository created
  • IAM role configured for GitHub OIDC
  • .NET library project (csproj) ready to pack

CI Workflow (Build & Pack)

Create: .github/workflows/ci-nuget.yml

yaml
1name: ci-nuget
2on:
3  push:
4    branches: [ develop ]
5  pull_request:
6    branches: [ develop, main ]
7  workflow_dispatch: {}
8
9jobs:
10  build-pack:
11    runs-on: ubuntu-latest
12    steps:
13      - uses: actions/checkout@v4
14
15      - uses: actions/setup-dotnet@v4
16        with:
17          dotnet-version: '8.0.x'
18          cache: true
19          cache-dependency-path: '**/packages.lock.json'
20
21      - name: Restore (locked)
22        run: dotnet restore src/My.Library/My.Library.csproj --locked-mode
23
24      - name: Build (Release)
25        run: dotnet build src/My.Library/My.Library.csproj -c Release --no-restore
26
27      - name: Pack (no publish)
28        run: dotnet pack src/My.Library/My.Library.csproj -c Release -o artifacts --no-build
29
30      - uses: actions/upload-artifact@v4
31        with:
32          name: nupkg
33          path: artifacts/*.nupkg

Publish Workflow (Tag Release) Create: .github/workflows/publish-nuget.yml

yaml
1name: publish-nuget
2on:
3  push:
4    tags: ['v*']   # e.g. v1.0.0 or v0.1.0-beta.1
5  workflow_dispatch:
6    inputs:
7      version:
8        description: "Package version (e.g., 0.1.0-beta.6) if running manually"
9        required: false
10
11jobs:
12  publish:
13    runs-on: ubuntu-latest
14    permissions:
15      id-token: write
16      contents: read
17
18    env:
19      AWS_REGION: us-east-1
20      CA_DOMAIN: my-domain
21      CA_REPOSITORY: nuget-internal
22      AWS_ACCOUNT_ID: "123456789012"
23      PROJECT: src/My.Library/My.Library.csproj
24
25    steps:
26      - uses: actions/checkout@v4
27
28      - name: Set VERSION
29        run: |
30          if [ -n "${{ github.event.inputs.version }}" ]; then
31            echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
32          else
33            echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
34          fi
35
36      - uses: actions/setup-dotnet@v4
37        with:
38          dotnet-version: '8.0.x'
39
40      - name: Configure AWS credentials (OIDC)
41        uses: aws-actions/configure-aws-credentials@v4
42        with:
43          role-to-assume: arn:aws:iam::123456789012:role/GitHubActions-CodeArtifact-Publish
44          aws-region: ${{ env.AWS_REGION }}
45
46      - name: CodeArtifact login for NuGet
47        run: |
48          aws codeartifact login \
49            --tool dotnet \
50            --repository $CA_REPOSITORY \
51            --domain $CA_DOMAIN \
52            --domain-owner $AWS_ACCOUNT_ID \
53            --region $AWS_REGION
54
55      - name: Restore/build/pack
56        run: |
57          dotnet restore $PROJECT --locked-mode --source https://api.nuget.org/v3/index.json
58          dotnet build $PROJECT -c Release --no-restore
59          dotnet pack $PROJECT -c Release -o artifacts --no-build -p:PackageVersion=${VERSION}
60
61      - name: Publish to CodeArtifact
62        run: |
63          dotnet nuget push artifacts/*.nupkg \
64            --source "$CA_DOMAIN/$CA_REPOSITORY" \
65            --api-key aws \
66            --skip-duplicate

Tags

#dotnet#nuget#aws#codeartifact#github-actions#oidc#cicd#devops