Skip to content
This repository was archived by the owner on Oct 26, 2022. It is now read-only.

Commit 8aef0d6

Browse files
add custom nuget feed support & set outputs
1 parent 0b59dc0 commit 8aef0d6

File tree

3 files changed

+168
-87
lines changed

3 files changed

+168
-87
lines changed

README.md

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,49 +12,91 @@ on:
1212
- master # Default release branch
1313
jobs:
1414
publish:
15-
name: build, pack & push
15+
name: build, pack & publish
1616
runs-on: ubuntu-latest
1717
steps:
1818
- uses: actions/checkout@v2
1919

20-
# Required in case of previous dotnet SDK versions as the host always has latest version installed
21-
# Visit bit.ly/2synnZl to see the list of SDKs that are pre-installed with ubuntu-latest / windows-latest
2220
# - name: Setup dotnet
2321
# uses: actions/setup-dotnet@v1
2422
# with:
25-
# dotnet-version: 3.1.100
23+
# dotnet-version: 3.1.200
2624

2725
# Publish
2826
- name: publish on version change
27+
id: publish_nuget
2928
uses: rohith/publish-nuget@v2
3029
with:
31-
PROJECT_FILE_PATH: Core/Core.csproj # Relative to repository root
32-
# PACKAGE_NAME: NuGet package id, REQUIRED if it's different from project name
33-
# VERSION_FILE_PATH: Directory.Build.props # Relative to repository root, defaults to project file
34-
# VERSION_REGEX: <Version>(.*)<\/Version> # Regex pattern to extract version info in a capturing group
35-
# VERSION_STATIC: Static version, useful for external providers like Nerdbank.GitVersioning
36-
# TAG_COMMIT: true # Flag to enable / disable git tagging
37-
# TAG_FORMAT: v* # Format of the git tag, [*] gets replaced with version
38-
# NUGET_KEY: ${{secrets.NUGET_API_KEY}} # API key for the NuGet feed
30+
# Filepath of the project to be packaged, relative to root of repository
31+
PROJECT_FILE_PATH: Core/Core.csproj
32+
33+
# NuGet package id, used for version detection & defaults to project name
34+
# PACKAGE_NAME: Core
35+
36+
# Filepath with version info, relative to root of repository & defaults to PROJECT_FILE_PATH
37+
# VERSION_FILE_PATH: Directory.Build.props
38+
39+
# Regex pattern to extract version info in a capturing group
40+
# VERSION_REGEX: <Version>(.*)<\/Version>
41+
42+
# Useful with external providers like Nerdbank.GitVersioning, ignores VERSION_FILE_PATH & VERSION_REGEX
43+
# VERSION_STATIC: 1.0.0
44+
45+
# Flag to toggle git tagging, enabled by default
46+
# TAG_COMMIT: true
47+
48+
# Format of the git tag, [*] gets replaced with actual version
49+
# TAG_FORMAT: v*
50+
51+
# API key to authenticate with NuGet server
52+
# NUGET_KEY: ${{secrets.NUGET_API_KEY}}
53+
54+
# API key to authenticate with NuGet symbols server, defaults to NUGET_KEY
55+
# NUGET_SYMBOL_KEY: ${{secrets.NUGET_SYMBOLS_API_KEY}}
56+
57+
# NuGet server uri hosting the packages, defaults to https://api.nuget.org
58+
# NUGET_SOURCE: https://api.nuget.org
59+
60+
# NuGet server uri hosting the symbols, defaults to https://api.nuget.org
61+
# NUGET_SYMBOL_SOURCE: https://api.nuget.org
62+
63+
# Flag to toggle pushing symbols along with nuget package to the server, enabled by default
64+
# INCLUDE_SYMBOLS: true
3965
```
4066

41-
- Project gets built, packed & published only if there's a `NUGET_KEY` configured in the repository
67+
- Project gets published only if there's a `NUGET_KEY` configured in the repository
4268

4369
## Inputs
4470

4571
Input | Default Value | Description
4672
--- | --- | ---
4773
PROJECT_FILE_PATH | | Filepath of the project to be packaged, relative to root of repository
48-
PACKAGE_NAME | | NuGet package id to check against version changes, defaults to project name
49-
VERSION_FILE_PATH | `[PROJECT_FILE_PATH]` | Filepath containing version info, relative to root of repository
74+
PACKAGE_NAME | | NuGet package id, used for version detection & defaults to project name
75+
VERSION_FILE_PATH | `[PROJECT_FILE_PATH]` | Filepath with version info, relative to root of repository & defaults to PROJECT_FILE_PATH
5076
VERSION_REGEX | `<Version>(.*)<\/Version>` | Regex pattern to extract version info in a capturing group
51-
VERSION_STATIC| | Static version, useful for external providers like Nerdbank.GitVersioning
52-
TAG_COMMIT | `true` | Flag to enable / disable git tagging
53-
TAG_FORMAT | `v*` | Format of the git tag, `[*]` gets replaced with version
54-
NUGET_KEY | | API key for the NuGet feed
77+
VERSION_STATIC| | Useful with external providers like Nerdbank.GitVersioning, ignores VERSION_FILE_PATH & VERSION_REGEX
78+
TAG_COMMIT | `true` | Flag to toggle git tagging, enabled by default
79+
TAG_FORMAT | `v*` | Format of the git tag, `[*]` gets replaced with actual version
80+
NUGET_KEY | | API key to authenticate with NuGet server
81+
NUGET_SYMBOL_KEY | `[NUGET_KEY]` | API key to authenticate with NuGet symbols server, defaults to NUGET_KEY
82+
NUGET_SOURCE | `https://api.nuget.org` | NuGet server uri hosting the packages, defaults to https://api.nuget.org
83+
NUGET_SYMBOL_SOURCE | `https://api.nuget.org` | NuGet server uri hosting the symbols, defaults to https://api.nuget.org
84+
INCLUDE_SYMBOLS | `true` | Flag to toggle pushing symbols along with nuget package to the server, enabled by default
85+
86+
## Outputs
87+
88+
Output | Description
89+
--- | ---
90+
VERSION | Version of the associated git tag
91+
PACKAGE_NAME | Name of the NuGet package generated
92+
PACKAGE_PATH | Path to the generated NuGet package
93+
SYMBOLS_PACKAGE_NAME | Name of the symbols package generated
94+
SYMBOLS_PACKAGE_PATH | Path to the generated symbols package
5595

56-
**Note:**
57-
Multiple projects can make use of steps to configure each project individually, common inputs between steps can be given as `env` for [job / workflow](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#env)
96+
**FYI:**
97+
- Outputs may not be set if the action failed
98+
- `NUGET_SOURCE` must support `/v3-flatcontainer/PACKAGE_NAME/index.json` for version change detection to work
99+
- Multiple projects can make use of steps to configure each project individually, common inputs between steps can be given as `env` for [job / workflow](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#env)
58100

59101
## License
60102
[MIT](LICENSE)

action.yml

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,60 @@ inputs:
77
description: Filepath of the project to be packaged, relative to root of repository
88
required: true
99
PACKAGE_NAME:
10-
description: NuGet package id to check against version changes, defaults to project name
10+
description: NuGet package id, used for version detection & defaults to project name
1111
required: false
1212
VERSION_FILE_PATH:
13-
description: Filepath containing version info, relative to root of repository
13+
description: Filepath with version info, relative to root of repository & defaults to PROJECT_FILE_PATH
1414
required: false
1515
VERSION_REGEX:
1616
description: Regex pattern to extract version info in a capturing group
1717
required: false
1818
default: <Version>(.*)<\/Version>
1919
VERSION_STATIC:
20-
description: Static version, useful for external providers like Nerdbank.GitVersioning
20+
description: Useful with external providers like Nerdbank.GitVersioning, ignores VERSION_FILE_PATH & VERSION_REGEX
2121
required: false
2222
TAG_COMMIT:
23-
description: Flag to enable / disable git tagging
23+
description: Flag to toggle git tagging, enabled by default
2424
required: false
2525
default: true
2626
TAG_FORMAT:
27-
description: Format of the git tag, `[*]` gets replaced with version
27+
description: Format of the git tag, [*] gets replaced with actual version
2828
required: false
2929
default: v*
3030
NUGET_KEY:
31-
description: API key for the NuGet feed
31+
description: API key to authenticate with NuGet server
3232
required: false
33+
NUGET_SYMBOL_KEY:
34+
description: API key to authenticate with NuGet symbols server, defaults to NUGET_KEY
35+
required: false
36+
NUGET_SOURCE:
37+
description: NuGet server uri hosting the packages, defaults to https://api.nuget.org
38+
required: false
39+
default: https://api.nuget.org
40+
NUGET_SYMBOL_SOURCE:
41+
description: NuGet server uri hosting the symbols, defaults to https://api.nuget.org
42+
required: false
43+
default: https://api.nuget.org
44+
INCLUDE_SYMBOLS:
45+
description: Flag to toggle pushing symbols along with nuget package to the server, enabled by default
46+
required: false
47+
default: true
48+
49+
outputs:
50+
VERSION:
51+
description: Version of the associated git tag
52+
53+
PACKAGE_NAME:
54+
description: Name of the NuGet package generated
55+
56+
PACKAGE_PATH:
57+
description: Path to the generated NuGet package
58+
59+
SYMBOLS_PACKAGE_NAME:
60+
description: Name of the symbols package generated
61+
62+
SYMBOLS_PACKAGE_PATH:
63+
description: Path to the generated symbols package
3364

3465
runs:
3566
using: node12

index.js

Lines changed: 68 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
1-
const path = require("path"),
2-
spawnSync = require("child_process").spawnSync,
1+
const os = require("os"),
32
fs = require("fs"),
4-
https = require("https")
3+
path = require("path"),
4+
https = require("https"),
5+
spawnSync = require("child_process").spawnSync
56

67
class Action {
78
constructor() {
89
this.projectFile = process.env.INPUT_PROJECT_FILE_PATH
9-
this.versionFile = process.env.INPUT_VERSION_FILE_PATH || process.env.VERSION_FILE_PATH
10+
this.packageName = process.env.INPUT_PACKAGE_NAME || process.env.PACKAGE_NAME
11+
this.versionFile = process.env.INPUT_VERSION_FILE_PATH || process.env.VERSION_FILE_PATH || this.projectFile
1012
this.versionRegex = new RegExp(process.env.INPUT_VERSION_REGEX || process.env.VERSION_REGEX)
1113
this.version = process.env.INPUT_VERSION_STATIC || process.env.VERSION_STATIC
1214
this.tagCommit = JSON.parse(process.env.INPUT_TAG_COMMIT || process.env.TAG_COMMIT)
1315
this.tagFormat = process.env.INPUT_TAG_FORMAT || process.env.TAG_FORMAT
1416
this.nugetKey = process.env.INPUT_NUGET_KEY || process.env.NUGET_KEY
15-
this.packageName = process.env.INPUT_PACKAGE_NAME || process.env.PACKAGE_NAME
16-
}
17-
18-
_printWarning(msg) {
19-
console.log(`##[warning]${msg}`)
17+
this.nugetSymbolKey = process.env.INPUT_NUGET_SYMBOL_KEY || process.env.NUGET_SYMBOL_KEY || this.nugetKey
18+
this.nugetSource = process.env.INPUT_NUGET_SOURCE || process.env.NUGET_SOURCE
19+
this.nugetSymbolSource = process.env.INPUT_NUGET_SYMBOL_SOURCE || process.env.NUGET_SYMBOL_SOURCE
20+
this.includeSymbols = JSON.parse(process.env.INPUT_INCLUDE_SYMBOLS || process.env.INCLUDE_SYMBOLS)
2021
}
2122

2223
_printErrorAndExit(msg) {
23-
console.log(`##[error]${msg}`)
24+
console.log(`##[error]😭 ${msg}`)
2425
throw new Error(msg)
2526
}
2627

2728
_executeCommand(cmd, options) {
29+
console.log(`executing: [${cmd}]`)
30+
2831
const INPUT = cmd.split(" "), TOOL = INPUT[0], ARGS = INPUT.slice(1)
2932
return spawnSync(TOOL, ARGS, options)
3033
}
@@ -33,108 +36,113 @@ class Action {
3336
this._executeCommand(cmd, { encoding: "utf-8", stdio: [process.stdin, process.stdout, process.stderr] })
3437
}
3538

36-
_mayResolveFilepath(filePath, errMsg) {
37-
const fullPath = path.resolve(process.env.GITHUB_WORKSPACE, filePath)
38-
39-
if (!fs.existsSync(fullPath))
40-
this._printErrorAndExit(errMsg)
41-
42-
return fullPath
43-
}
44-
4539
_tagCommit(version) {
4640
const TAG = this.tagFormat.replace("*", version)
4741

42+
console.log(`✨ creating new tag ${TAG}`)
43+
4844
this._executeInProcess(`git tag ${TAG}`)
4945
this._executeInProcess(`git push origin ${TAG}`)
46+
47+
process.stdout.write(`::set-output name=VERSION::${TAG}` + os.EOL)
5048
}
5149

52-
_pushPackage() {
50+
_pushPackage(version, name) {
51+
console.log(`✨ found new version (${version}) of ${name}`)
52+
5353
if (!this.nugetKey) {
54-
this._printWarning("😢 NUGET_KEY not given")
54+
console.log("##[warning]😢 NUGET_KEY not given")
5555
return
5656
}
5757

58+
console.log(`NuGet Source: ${this.nugetSource}`)
59+
console.log(`NuGet Symbol Source: ${this.nugetSymbolSource}`)
60+
5861
fs.readdirSync(".").filter(fn => fn.endsWith("nupkg")).forEach(fn => fs.unlinkSync(fn))
5962

6063
this._executeInProcess(`dotnet build -c Release ${this.projectFile}`)
61-
this._executeInProcess(`dotnet pack --include-symbols -p:SymbolPackageFormat=snupkg --no-build -c Release ${this.projectFile} -o .`)
64+
65+
const packSymbolFlags = this.includeSymbols ? "--include-symbols -p:SymbolPackageFormat=snupkg" : ""
66+
this._executeInProcess(`dotnet pack ${packSymbolFlags} --no-build -c Release ${this.projectFile} -o .`)
6267

6368
const packages = fs.readdirSync(".").filter(fn => fn.endsWith("nupkg"))
6469
console.log(`Generated Package(s): ${packages.join(", ")}`)
6570

66-
const pushCmd = `dotnet nuget push *.nupkg -s https://api.nuget.org/v3/index.json -k ${this.nugetKey} --skip-duplicate`,
71+
const pushSymbolFlags = this.includeSymbols ? `-ss ${this.nugetSymbolSource}/v3/index.json -sk ${this.nugetSymbolKey}` : "--no-symbols",
72+
pushCmd = `dotnet nuget push *.nupkg -s ${this.nugetSource}/v3/index.json -k ${this.nugetKey} ${pushSymbolFlags} --skip-duplicate`,
6773
pushOutput = this._executeCommand(pushCmd, { encoding: "utf-8" }).stdout
6874

6975
console.log(pushOutput)
7076

7177
if (/error/.test(pushOutput))
72-
this._printErrorAndExit(`😭 ${/error.*/.exec(pushOutput)[0]}`)
73-
}
78+
this._printErrorAndExit(`${/error.*/.exec(pushOutput)[0]}`)
7479

75-
_mayTagAndPush(version, name) {
76-
console.log(`👍 found a new version (${version}) of ${name}`)
80+
const packageFilename = packages.filter(p => p.endsWith(".nupkg"))[0],
81+
symbolsFilename = packages.filter(p => p.endsWith(".snupkg"))[0]
7782

78-
if (this.tagCommit)
79-
this._tagCommit(version)
83+
process.stdout.write(`::set-output name=PACKAGE_NAME::${packageFilename}` + os.EOL)
84+
process.stdout.write(`::set-output name=PACKAGE_PATH::${path.resolve(packageFilename)}` + os.EOL)
8085

81-
this._pushPackage()
82-
}
83-
84-
_determineProjectFilepath() {
85-
if (!this.projectFile)
86-
this._printErrorAndExit("😭 project file not given")
87-
88-
this.projectFile = this._mayResolveFilepath(this.projectFile, "😭 project file not found")
89-
console.log(`Project Filepath: ${this.projectFile}`)
90-
}
91-
92-
_determineVersion() {
93-
if (!this.version) {
94-
this.versionFile = !this.versionFile ? this.projectFile : this._mayResolveFilepath(this.versionFile, "😭 version file not found")
95-
console.log(`Version Filepath: ${this.versionFile}`)
96-
97-
const versionFileContent = fs.readFileSync(this.versionFile, { encoding: "utf-8" }),
98-
parsedVersion = this.versionRegex.exec(versionFileContent)
99-
100-
if (!parsedVersion)
101-
this._printErrorAndExit("😢 unable to extract version info!")
102-
103-
this.version = parsedVersion[1]
86+
if (symbolsFilename) {
87+
process.stdout.write(`::set-output name=SYMBOLS_PACKAGE_NAME::${symbolsFilename}` + os.EOL)
88+
process.stdout.write(`::set-output name=SYMBOLS_PACKAGE_PATH::${path.resolve(symbolsFilename)}` + os.EOL)
10489
}
10590

106-
console.log(`Version: ${this.version}`)
91+
if (this.tagCommit)
92+
this._tagCommit(version)
10793
}
10894

10995
_checkForUpdate() {
11096
if (!this.packageName) {
11197
this.packageName = path.basename(this.projectFile).split(".").slice(0, -1).join(".")
112-
console.log(`Package Name: ${this.packageName}`)
11398
}
11499

115-
https.get(`https://api.nuget.org/v3-flatcontainer/${this.packageName}/index.json`, res => {
100+
console.log(`Package Name: ${this.packageName}`)
101+
102+
https.get(`${this.nugetSource}/v3-flatcontainer/${this.packageName}/index.json`, res => {
116103
let body = ""
117104

118105
if (res.statusCode == 404)
119-
this._mayTagAndPush(this.version, this.packageName)
106+
this._pushPackage(this.version, this.packageName)
120107

121108
if (res.statusCode == 200) {
122109
res.setEncoding("utf8")
123110
res.on("data", chunk => body += chunk)
124111
res.on("end", () => {
125112
const existingVersions = JSON.parse(body)
126113
if (existingVersions.versions.indexOf(this.version) < 0)
127-
this._mayTagAndPush(this.version, this.packageName)
114+
this._pushPackage(this.version, this.packageName)
128115
})
129116
}
130117
}).on("error", e => {
131-
this._printWarning(`😢 error reaching nuget.org ${e.message}`)
118+
this._printErrorAndExit(`error: ${e.message}`)
132119
})
133120
}
134121

135122
run() {
136-
this._determineProjectFilepath()
137-
this._determineVersion()
123+
if (!this.projectFile || !fs.existsSync(this.projectFile))
124+
this._printErrorAndExit("project file not found")
125+
126+
console.log(`Project Filepath: ${this.projectFile}`)
127+
128+
if (!this.version) {
129+
if (this.versionFile !== this.projectFile && !fs.existsSync(this.versionFile))
130+
this._printErrorAndExit("version file not found")
131+
132+
console.log(`Version Filepath: ${this.versionFile}`)
133+
console.log(`Version Regex: ${this.versionRegex}`)
134+
135+
const versionFileContent = fs.readFileSync(this.versionFile, { encoding: "utf-8" }),
136+
parsedVersion = this.versionRegex.exec(versionFileContent)
137+
138+
if (!parsedVersion)
139+
this._printErrorAndExit("unable to extract version info!")
140+
141+
this.version = parsedVersion[1]
142+
}
143+
144+
console.log(`Version: ${this.version}`)
145+
138146
this._checkForUpdate()
139147
}
140148
}

0 commit comments

Comments
 (0)