-
-
Notifications
You must be signed in to change notification settings - Fork 121
136 lines (122 loc) · 6.44 KB
/
Copy pathcd.yml
File metadata and controls
136 lines (122 loc) · 6.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
name: CD
# Builds, tests and packs the NuGet package on a version tag (v1.2.3) or manual run.
# Publishing to NuGet uses Trusted Publishing (OIDC) and runs only on a v*.*.* tag push; a manual
# run packs and uploads the artifact as a dry run without publishing (see the step comments below).
on:
push:
tags: [ 'v*.*.*' ]
workflow_dispatch:
inputs:
version:
description: 'Package version, e.g. 1.2.3. Defaults to a dev version when omitted.'
required: false
permissions:
contents: read
jobs:
pack-publish:
name: Pack & Publish
# Windows is required: the library multi-targets net40/net45 and the demo targets net48, which
# need the .NET Framework reference assemblies / targeting packs available on the Windows runners.
runs-on: windows-latest
timeout-minutes: 15
permissions:
id-token: write # Required for NuGet Trusted Publishing; without it NuGet/login fails with 403.
contents: write # Required to create the GitHub Release; a job-level block drops inherited defaults.
steps:
- uses: actions/checkout@v6
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
# Install the exact SDK pinned in global.json; Dependabot's dotnet-sdk updater keeps it current.
global-json-file: global.json
# Cache the restored NuGet packages, keyed on the committed lock files.
cache: true
cache-dependency-path: '**/packages.lock.json'
- name: Resolve version
id: version
shell: bash
# The manual input is read through an env var, not interpolated into the script, so a crafted
# value cannot inject shell. It is then validated as SemVer before anything downstream uses it.
env:
VERSION_INPUT: ${{ github.event.inputs.version }}
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
VERSION="${GITHUB_REF_NAME#v}"
elif [[ -n "${VERSION_INPUT}" ]]; then
VERSION="${VERSION_INPUT}"
if ! [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]]; then
echo "Invalid version '${VERSION}'; expected SemVer such as 1.2.3 or 1.2.3-rc.1." >&2
exit 1
fi
else
VERSION="0.0.0-dev.${GITHUB_RUN_NUMBER}"
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Resolved package version: ${VERSION}"
- name: Restore
# Locked-mode restore fails the build if any packages.lock.json is missing or out of date, so the
# restore is reproducible and a forgotten lock-file update cannot slip through.
run: dotnet restore SQLite.CodeFirst.slnx --locked-mode
- name: Build
run: dotnet build SQLite.CodeFirst.slnx -c Release --no-restore -p:Version=${{ steps.version.outputs.version }}
- name: Test
# The test project runs on Microsoft.Testing.Platform (opted in via global.json), so target the
# solution with the native MTP dotnet test syntax.
run: dotnet test --solution SQLite.CodeFirst.slnx -c Release --no-build
- name: Pack
run: >
dotnet pack SQLite.CodeFirst/SQLite.CodeFirst.csproj -c Release --no-build
-p:Version=${{ steps.version.outputs.version }}
-o ${{ github.workspace }}/artifacts
- name: Upload package artifact
uses: actions/upload-artifact@v7
with:
name: nuget-package
path: |
${{ github.workspace }}/artifacts/*.nupkg
${{ github.workspace }}/artifacts/*.snupkg
# --- NuGet publishing via Trusted Publishing (OIDC). ---
# No long-lived API key: NuGet/login swaps the GitHub OIDC token for a short-lived key, authorized
# by the trusted publishing policy on nuget.org (the policy must name this workflow file, cd.yml).
# Gated to tag pushes so a manual run stays a dry run and never pushes the 0.0.0-dev.* version.
# https://learn.microsoft.com/nuget/nuget-org/trusted-publishing
- name: NuGet login (OIDC)
id: nuget-login
if: startsWith(github.ref, 'refs/tags/v')
uses: NuGet/login@v1
with:
user: ${{ secrets.NUGET_USER }} # nuget.org account/profile name, NOT the email address.
- name: Publish to NuGet
if: startsWith(github.ref, 'refs/tags/v')
shell: pwsh
# Resolve the package explicitly: on the Windows runner the default PowerShell shell does not
# expand a "*.nupkg" wildcard for dotnet, so a literal glob path is passed through and not found.
# Pushing the .nupkg also pushes the sibling .snupkg symbol package to nuget.org automatically.
run: |
$package = Get-ChildItem -Path "${{ github.workspace }}/artifacts/*.nupkg" | Select-Object -First 1
dotnet nuget push $package.FullName `
--api-key "${{ steps.nuget-login.outputs.NUGET_API_KEY }}" `
--source https://api.nuget.org/v3/index.json `
--skip-duplicate
# --- GitHub Release. ---
# Created only on tag pushes, after a successful NuGet publish, so the Release reflects what was
# actually shipped. Uses the gh CLI (preinstalled on the runner) rather than a third-party action.
# --generate-notes builds the notes from commits/PRs since the previous tag; --verify-tag guards
# against creating a release for a tag the runner cannot see. The .nupkg/.snupkg are attached so
# the package is downloadable straight from the Release page, not just the workflow run.
- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
shell: pwsh
# The tag is passed through an env var rather than interpolated into the script, matching the
# version step above. Assets are resolved with Get-ChildItem so the wildcards expand on the
# Windows runner (bash would mangle the backslashes in the workspace path).
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
run: |
$assets = Get-ChildItem -Path "${{ github.workspace }}/artifacts/*.nupkg", "${{ github.workspace }}/artifacts/*.snupkg" | ForEach-Object { $_.FullName }
# SemVer pre-release tags carry a hyphen (e.g. v1.2.3-rc.1); mark those as GitHub pre-releases.
$ghArgs = @($env:TAG, '--title', $env:TAG, '--generate-notes', '--verify-tag')
if ($env:TAG -like '*-*') { $ghArgs += '--prerelease' }
$ghArgs += $assets
gh release create $ghArgs