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

Commit 0b59dc0

Browse files
publish symbols & fail on any nuget push errors
fixes #26 fixes #27
1 parent cc84629 commit 0b59dc0

File tree

3 files changed

+99
-107
lines changed

3 files changed

+99
-107
lines changed

README.md

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

20-
# Required for a specific dotnet version that doesn't come with ubuntu-latest / windows-latest
20+
# Required in case of previous dotnet SDK versions as the host always has latest version installed
2121
# Visit bit.ly/2synnZl to see the list of SDKs that are pre-installed with ubuntu-latest / windows-latest
2222
# - name: Setup dotnet
2323
# uses: actions/setup-dotnet@v1
2424
# with:
2525
# dotnet-version: 3.1.100
26-
26+
2727
# Publish
2828
- name: publish on version change
2929
uses: rohith/publish-nuget@v2
3030
with:
3131
PROJECT_FILE_PATH: Core/Core.csproj # Relative to repository root
32-
# VERSION_FILE_PATH: Directory.Build.props # Filepath with version info, relative to repository root. Defaults to project file
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
3334
# VERSION_REGEX: <Version>(.*)<\/Version> # Regex pattern to extract version info in a capturing group
34-
# VERSION_STATIC: Bypasses version resolution; useful for external providers like Nerdbank.GitVersioning
35-
# TAG_COMMIT: true # Flag to enable / disalge git tagging
35+
# VERSION_STATIC: Static version, useful for external providers like Nerdbank.GitVersioning
36+
# TAG_COMMIT: true # Flag to enable / disable git tagging
3637
# TAG_FORMAT: v* # Format of the git tag, [*] gets replaced with version
37-
# NUGET_KEY: ${{secrets.NUGET_API_KEY}} # nuget.org API key
38-
# PACKAGE_NAME: NuGet package name, required when it's different from project name. Defaults to project name
38+
# NUGET_KEY: ${{secrets.NUGET_API_KEY}} # API key for the NuGet feed
3939
```
4040

41-
- With all settings on default, updates to project version are monitored on every push / PR merge to master & a new tag is created
42-
- If a `NUGET_KEY` is present then the project gets built, packed & published to nuget.org
41+
- Project gets built, packed & published only if there's a `NUGET_KEY` configured in the repository
4342

4443
## Inputs
45-
Most of the inputs are optional
4644

4745
Input | Default Value | Description
4846
--- | --- | ---
49-
PROJECT_FILE_PATH | | File path of the project to be packaged, relative to repository root
50-
VERSION_FILE_PATH | `[PROJECT_FILE_PATH]` | File path containing version info, relative to repository root
47+
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
5150
VERSION_REGEX | `<Version>(.*)<\/Version>` | Regex pattern to extract version info in a capturing group
52-
VERSION_STATIC| | Bypasses version resolution; useful for external providers like Nerdbank.GitVersioning
51+
VERSION_STATIC| | Static version, useful for external providers like Nerdbank.GitVersioning
5352
TAG_COMMIT | `true` | Flag to enable / disable git tagging
54-
TAG_FORMAT | `v*` | `[*]` is a placeholder for the actual project version
55-
NUGET_KEY | | API key to authorize the package upload to nuget.org
56-
PACKAGE_NAME | | Name of the NuGet package, required when it's different from project name
53+
TAG_FORMAT | `v*` | Format of the git tag, `[*]` gets replaced with version
54+
NUGET_KEY | | API key for the NuGet feed
5755

58-
**Note:**
59-
For multiple projects, every input except `PROJECT_FILE_PATH` can be given as `env` variable at [job / workflow level](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#env)
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)
6058

6159
## License
6260
[MIT](LICENSE)

action.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
name: Publish NuGet
22
author: Rohith Reddy (@rohith)
3-
description: Build, Pack & Publish NuGet packages with dotnet (.net) core on project version change
3+
description: Build, Pack & Publish a NuGet package with dotnet core on project version change
44

55
inputs:
66
PROJECT_FILE_PATH:
77
description: Filepath of the project to be packaged, relative to root of repository
88
required: true
9+
PACKAGE_NAME:
10+
description: NuGet package id to check against version changes, defaults to project name
11+
required: false
912
VERSION_FILE_PATH:
10-
description: Filepath containing version info, relative to root of repository. Defaults to `PROJECT_FILE_PATH` if not specified
13+
description: Filepath containing version info, relative to root of repository
1114
required: false
1215
VERSION_REGEX:
13-
description: Regex (with version in a capturing group) to extract the version from `VERSION_FILE_PATH`
16+
description: Regex pattern to extract version info in a capturing group
1417
required: false
1518
default: <Version>(.*)<\/Version>
1619
VERSION_STATIC:
17-
description: Bypasses version resolution; useful for external providers like Nerdbank.GitVersioning
20+
description: Static version, useful for external providers like Nerdbank.GitVersioning
1821
required: false
1922
TAG_COMMIT:
20-
description: Whether to create a tag when there's a version change
23+
description: Flag to enable / disable git tagging
2124
required: false
2225
default: true
2326
TAG_FORMAT:
24-
description: Format of the tag, `*` is the placeholder for actual version
27+
description: Format of the git tag, `[*]` gets replaced with version
2528
required: false
2629
default: v*
2730
NUGET_KEY:
2831
description: API key for the NuGet feed
2932
required: false
30-
PACKAGE_NAME:
31-
description: NuGet package name, required when it's different from the project name
32-
required: false
3333

3434
runs:
3535
using: node12

index.js

Lines changed: 73 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -5,144 +5,138 @@ const path = require("path"),
55

66
class Action {
77
constructor() {
8-
this.PROJECT_FILE_PATH = process.env.INPUT_PROJECT_FILE_PATH
9-
this.VERSION_FILE_PATH = process.env.INPUT_VERSION_FILE_PATH || process.env.VERSION_FILE_PATH
10-
this.VERSION_REGEX = new RegExp(process.env.INPUT_VERSION_REGEX || process.env.VERSION_REGEX)
11-
this.VERSION_STATIC = process.env.INPUT_VERSION_STATIC || process.env.VERSION_STATIC
12-
this.TAG_COMMIT = JSON.parse(process.env.INPUT_TAG_COMMIT || process.env.TAG_COMMIT)
13-
this.TAG_FORMAT = process.env.INPUT_TAG_FORMAT || process.env.TAG_FORMAT
14-
this.NUGET_KEY = process.env.INPUT_NUGET_KEY || process.env.NUGET_KEY
15-
this.PACKAGE_NAME = process.env.INPUT_PACKAGE_NAME || process.env.PACKAGE_NAME
8+
this.projectFile = process.env.INPUT_PROJECT_FILE_PATH
9+
this.versionFile = process.env.INPUT_VERSION_FILE_PATH || process.env.VERSION_FILE_PATH
10+
this.versionRegex = new RegExp(process.env.INPUT_VERSION_REGEX || process.env.VERSION_REGEX)
11+
this.version = process.env.INPUT_VERSION_STATIC || process.env.VERSION_STATIC
12+
this.tagCommit = JSON.parse(process.env.INPUT_TAG_COMMIT || process.env.TAG_COMMIT)
13+
this.tagFormat = process.env.INPUT_TAG_FORMAT || process.env.TAG_FORMAT
14+
this.nugetKey = process.env.INPUT_NUGET_KEY || process.env.NUGET_KEY
15+
this.packageName = process.env.INPUT_PACKAGE_NAME || process.env.PACKAGE_NAME
1616
}
1717

18-
_warn(msg) {
18+
_printWarning(msg) {
1919
console.log(`##[warning]${msg}`)
2020
}
2121

22-
_fail(msg) {
22+
_printErrorAndExit(msg) {
2323
console.log(`##[error]${msg}`)
2424
throw new Error(msg)
2525
}
2626

27-
_execCmd(cmd, options) {
27+
_executeCommand(cmd, options) {
2828
const INPUT = cmd.split(" "), TOOL = INPUT[0], ARGS = INPUT.slice(1)
2929
return spawnSync(TOOL, ARGS, options)
3030
}
3131

32-
_execAndCapture(cmd) {
33-
return this._execCmd(cmd, { encoding: "utf-8" }).stdout
32+
_executeInProcess(cmd) {
33+
this._executeCommand(cmd, { encoding: "utf-8", stdio: [process.stdin, process.stdout, process.stderr] })
3434
}
3535

36-
_execInProc(cmd) {
37-
this._execCmd(cmd, { encoding: "utf-8", stdio: [process.stdin, process.stdout, process.stderr] })
38-
}
36+
_mayResolveFilepath(filePath, errMsg) {
37+
const fullPath = path.resolve(process.env.GITHUB_WORKSPACE, filePath)
38+
39+
if (!fs.existsSync(fullPath))
40+
this._printErrorAndExit(errMsg)
3941

40-
_resolveIfExists(filePath, errMsg) {
41-
const FULLPATH = path.resolve(process.env.GITHUB_WORKSPACE, filePath)
42+
return fullPath
43+
}
4244

43-
if (!fs.existsSync(FULLPATH))
44-
this._fail(errMsg)
45+
_tagCommit(version) {
46+
const TAG = this.tagFormat.replace("*", version)
4547

46-
return FULLPATH
48+
this._executeInProcess(`git tag ${TAG}`)
49+
this._executeInProcess(`git push origin ${TAG}`)
4750
}
4851

4952
_pushPackage() {
50-
if (!this.NUGET_KEY) {
51-
this._warn("😢 NUGET_KEY not given")
53+
if (!this.nugetKey) {
54+
this._printWarning("😢 NUGET_KEY not given")
5255
return
5356
}
5457

55-
if (!this._execAndCapture("dotnet --version")) {
56-
this._warn("😭 dotnet not found")
57-
return
58-
}
58+
fs.readdirSync(".").filter(fn => fn.endsWith("nupkg")).forEach(fn => fs.unlinkSync(fn))
5959

60-
this._execInProc(`dotnet build -c Release ${this.PROJECT_FILE_PATH}`)
61-
this._execInProc(`dotnet pack --no-build -c Release ${this.PROJECT_FILE_PATH} -o .`)
60+
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 .`)
6262

63-
const generatedPackage = fs.readdirSync(".").filter(fn => fn.startsWith(this.PACKAGE_NAME) && fn.endsWith(".nupkg")).shift()
64-
console.log(`Generated Package: ${generatedPackage}`)
63+
const packages = fs.readdirSync(".").filter(fn => fn.endsWith("nupkg"))
64+
console.log(`Generated Package(s): ${packages.join(", ")}`)
6565

66-
const NUGET_PUSH_RESPONSE = this._execAndCapture(`dotnet nuget push ${generatedPackage} -s https://api.nuget.org/v3/index.json -k ${this.NUGET_KEY}`)
67-
const NUGET_ERROR_REGEX = /(error: Response status code does not indicate success.*)/
66+
const pushCmd = `dotnet nuget push *.nupkg -s https://api.nuget.org/v3/index.json -k ${this.nugetKey} --skip-duplicate`,
67+
pushOutput = this._executeCommand(pushCmd, { encoding: "utf-8" }).stdout
6868

69-
console.log(NUGET_PUSH_RESPONSE)
69+
console.log(pushOutput)
7070

71-
if (NUGET_ERROR_REGEX.test(NUGET_PUSH_RESPONSE))
72-
this._fail(`😭 ${NUGET_ERROR_REGEX.exec(NUGET_PUSH_RESPONSE)[1]}`)
71+
if (/error/.test(pushOutput))
72+
this._printErrorAndExit(`😭 ${/error.*/.exec(pushOutput)[0]}`)
7373
}
7474

75-
_tagCommit(version) {
76-
if (this.TAG_COMMIT) {
77-
const TAG = this.TAG_FORMAT.replace("*", version)
78-
79-
if (this._execAndCapture(`git ls-remote --tags origin ${TAG}`).indexOf(TAG) >= 0) {
80-
this._warn(`😢 tag ${TAG} already exists`)
81-
return
82-
}
75+
_mayTagAndPush(version, name) {
76+
console.log(`👍 found a new version (${version}) of ${name}`)
8377

84-
this._execInProc(`git tag ${TAG}`)
85-
this._execInProc(`git push origin ${TAG}`)
86-
}
87-
}
78+
if (this.tagCommit)
79+
this._tagCommit(version)
8880

89-
_pushAndTag(version, name) {
90-
console.log(`👍 found a new version (${version}) of ${name}`)
91-
this._tagCommit(version)
9281
this._pushPackage()
9382
}
9483

95-
run() {
96-
if (!this.PROJECT_FILE_PATH)
97-
this._fail("😭 project file not given")
98-
99-
this.PROJECT_FILE_PATH = this._resolveIfExists(this.PROJECT_FILE_PATH, "😭 project file not found")
84+
_determineProjectFilepath() {
85+
if (!this.projectFile)
86+
this._printErrorAndExit("😭 project file not given")
10087

101-
console.log(`Project Filepath: ${this.PROJECT_FILE_PATH}`)
102-
103-
let CURRENT_VERSION
104-
105-
if (!this.VERSION_STATIC) {
106-
this.VERSION_FILE_PATH = !this.VERSION_FILE_PATH ? this.PROJECT_FILE_PATH : this._resolveIfExists(this.VERSION_FILE_PATH, "😭 version file not found")
88+
this.projectFile = this._mayResolveFilepath(this.projectFile, "😭 project file not found")
89+
console.log(`Project Filepath: ${this.projectFile}`)
90+
}
10791

108-
console.log(`Version Filepath: ${this.VERSION_FILE_PATH}`)
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}`)
10996

110-
const FILE_CONTENT = fs.readFileSync(this.VERSION_FILE_PATH, { encoding: "utf-8" }),
111-
VERSION_INFO = this.VERSION_REGEX.exec(FILE_CONTENT)
97+
const versionFileContent = fs.readFileSync(this.versionFile, { encoding: "utf-8" }),
98+
parsedVersion = this.versionRegex.exec(versionFileContent)
11299

113-
if (!VERSION_INFO)
114-
this._fail("😢 unable to extract version info!")
100+
if (!parsedVersion)
101+
this._printErrorAndExit("😢 unable to extract version info!")
115102

116-
CURRENT_VERSION = VERSION_INFO[1]
117-
} else
118-
CURRENT_VERSION = this.VERSION_STATIC
103+
this.version = parsedVersion[1]
104+
}
119105

120-
console.log(`Version: ${CURRENT_VERSION}`)
106+
console.log(`Version: ${this.version}`)
107+
}
121108

122-
if (!this.PACKAGE_NAME) {
123-
this.PACKAGE_NAME = path.basename(this.PROJECT_FILE_PATH).split(".").slice(0, -1).join(".")
124-
console.log(`Package Name: ${this.PACKAGE_NAME}`)
109+
_checkForUpdate() {
110+
if (!this.packageName) {
111+
this.packageName = path.basename(this.projectFile).split(".").slice(0, -1).join(".")
112+
console.log(`Package Name: ${this.packageName}`)
125113
}
126114

127-
https.get(`https://api.nuget.org/v3-flatcontainer/${this.PACKAGE_NAME}/index.json`, res => {
115+
https.get(`https://api.nuget.org/v3-flatcontainer/${this.packageName}/index.json`, res => {
128116
let body = ""
129117

130118
if (res.statusCode == 404)
131-
this._pushAndTag(CURRENT_VERSION, this.PACKAGE_NAME)
119+
this._mayTagAndPush(this.version, this.packageName)
132120

133121
if (res.statusCode == 200) {
134122
res.setEncoding("utf8")
135123
res.on("data", chunk => body += chunk)
136124
res.on("end", () => {
137125
const existingVersions = JSON.parse(body)
138-
if (existingVersions.versions.indexOf(CURRENT_VERSION) < 0)
139-
this._pushAndTag(CURRENT_VERSION, this.PACKAGE_NAME)
126+
if (existingVersions.versions.indexOf(this.version) < 0)
127+
this._mayTagAndPush(this.version, this.packageName)
140128
})
141129
}
142130
}).on("error", e => {
143-
this._warn(`😢 error reaching nuget.org ${e.message}`)
131+
this._printWarning(`😢 error reaching nuget.org ${e.message}`)
144132
})
145133
}
134+
135+
run() {
136+
this._determineProjectFilepath()
137+
this._determineVersion()
138+
this._checkForUpdate()
139+
}
146140
}
147141

148142
new Action().run()

0 commit comments

Comments
 (0)