diff --git a/README.md b/README.md index 3557d48..340f7cd 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ name: publish to nuget on: push: branches: - - master # Your default release branch + - master # Default release branch jobs: publish: name: list on nuget @@ -34,6 +34,7 @@ jobs: # TAG_COMMIT: true # Flag to enable / disalge git tagging # TAG_FORMAT: v* # Format of the git tag, [*] gets replaced with version # NUGET_KEY: ${{secrets.NUGET_API_KEY}} # nuget.org API key + # PACKAGE_NAME: NuGet package name, required when it's different from project name. Defaults to project name ``` - With all settings on default, updates to project version are monitored on every push / PR merge to master & a new tag is created @@ -50,6 +51,7 @@ VERSION_REGEX | `(.*)<\/Version>` | Regex pattern to extract version in TAG_COMMIT | `true` | Flag to enable / disable git tagging TAG_FORMAT | `v*` | `[*]` is a placeholder for the actual project version NUGET_KEY | | API key to authorize the package upload to nuget.org +PACKAGE_NAME | | Name of the NuGet package, required when it's different from project name **Note:** 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) diff --git a/action.yml b/action.yml index 60553fa..4c0504f 100644 --- a/action.yml +++ b/action.yml @@ -14,7 +14,7 @@ inputs: required: false default: (.*)<\/Version> TAG_COMMIT: - description: Whether to create a tag when there's a version change or not + description: Whether to create a tag when there's a version change required: false default: true TAG_FORMAT: @@ -24,6 +24,9 @@ inputs: NUGET_KEY: description: API key for the NuGet feed required: false + PACKAGE_NAME: + description: NuGet package name, required when it's different from the project name + required: false runs: using: node12 diff --git a/index.js b/index.js index 9be5abd..c66f06a 100644 --- a/index.js +++ b/index.js @@ -1,120 +1,123 @@ -const path = require("path"), - spawnSync = require("child_process").spawnSync, - fs = require("fs"), - https = require("https") - -class Action { - constructor() { - this.PROJECT_FILE_PATH = process.env.INPUT_PROJECT_FILE_PATH - this.VERSION_FILE_PATH = process.env.INPUT_VERSION_FILE_PATH || process.env.VERSION_FILE_PATH - this.VERSION_REGEX = new RegExp(process.env.INPUT_VERSION_REGEX || process.env.VERSION_REGEX) - this.TAG_COMMIT = JSON.parse(process.env.INPUT_TAG_COMMIT || process.env.TAG_COMMIT) - this.TAG_FORMAT = process.env.INPUT_TAG_FORMAT || process.env.TAG_FORMAT - this.NUGET_KEY = process.env.INPUT_NUGET_KEY || process.env.NUGET_KEY - } - - _warn(msg) { - console.log(`##[warning]${msg}`) - } - - _fail(msg) { - console.log(`##[error]${msg}`) - throw new Error(msg) - } - - _execCmd(cmd, options) { - const INPUT = cmd.split(" "), TOOL = INPUT[0], ARGS = INPUT.slice(1) - return spawnSync(TOOL, ARGS, options) - } - - _execAndCapture(cmd) { - return this._execCmd(cmd, { encoding: "utf-8" }).stdout - } - - _execInProc(cmd) { - this._execCmd(cmd, { encoding: "utf-8", stdio: [process.stdin, process.stdout, process.stderr] }) - } - - _resolveIfExists(filePath, msg) { - const FULLPATH = path.resolve(process.env.GITHUB_WORKSPACE, filePath) - if (!fs.existsSync(FULLPATH)) this._fail(msg) - return FULLPATH - } - - _pushPackage() { - if (!this.NUGET_KEY) { - this._warn("😢 nuget_key not given") - return - } - - if (!this._execAndCapture("dotnet --version")) { - this._warn("😭 dotnet not found") - return - } - - this._execInProc(`dotnet pack -c Release ${this.PROJECT_FILE_PATH} -o .`) - const NUGET_PUSH_RESPONSE = this._execAndCapture(`dotnet nuget push *.nupkg -s https://api.nuget.org/v3/index.json -k ${this.NUGET_KEY}`) - const NUGET_ERROR_REGEX = /(error: Response status code does not indicate success.*)/ - - if (NUGET_ERROR_REGEX.test(NUGET_PUSH_RESPONSE)) - this._fail(`😭 ${NUGET_ERROR_REGEX.exec(NUGET_PUSH_RESPONSE)[1]}`) - } - - _tagCommit(version) { - if (this.TAG_COMMIT) { - const TAG = this.TAG_FORMAT.replace("*", version) - - if (this._execAndCapture(`git ls-remote --tags origin ${TAG}`).indexOf(TAG) >= 0) { - this._warn(`😢 tag ${TAG} already exists`) - return - } - - this._execInProc(`git tag ${TAG}`) - this._execInProc(`git push origin ${TAG}`) - } - } - - _pushAndTag(CURRENT_VERSION, PACKAGE_NAME) { - console.log(`👍 found a new version (${CURRENT_VERSION}) of ${PACKAGE_NAME}`) - this._tagCommit(CURRENT_VERSION) - this._pushPackage() - } - - run() { - if (!this.PROJECT_FILE_PATH) - this._fail("😭 project file not given") - - this.PROJECT_FILE_PATH = this._resolveIfExists(this.PROJECT_FILE_PATH, "😭 project file not found") - this.VERSION_FILE_PATH = !this.VERSION_FILE_PATH ? this.PROJECT_FILE_PATH : this._resolveIfExists(this.VERSION_FILE_PATH, "😭 version file not found") - - const FILE_CONTENT = fs.readFileSync(this.VERSION_FILE_PATH, { encoding: "utf-8" }), - VERSION_INFO = this.VERSION_REGEX.exec(FILE_CONTENT) - - if (!VERSION_INFO) - this._fail("😢 unable to extract version info") - - const CURRENT_VERSION = VERSION_INFO[1], - PACKAGE_NAME = path.basename(this.PROJECT_FILE_PATH).split(".").slice(0, -1).join(".") - - https.get(`https://api.nuget.org/v3-flatcontainer/${PACKAGE_NAME}/index.json`, res => { - let body = "" - - if (res.statusCode == 404) - this._pushAndTag(CURRENT_VERSION, PACKAGE_NAME) - - if (res.statusCode == 200) { - res.setEncoding("utf8") - res.on("data", chunk => body += chunk) - res.on("end", () => { - const existingVersions = JSON.parse(body) - if (existingVersions.versions.indexOf(CURRENT_VERSION) < 0) - this._pushAndTag(CURRENT_VERSION, PACKAGE_NAME) - }) - } - }).on("error", e => { - this._warn(`😢 error reaching nuget.org ${e.message}`) - }) - } -} - -new Action().run() \ No newline at end of file +const path = require("path"), + spawnSync = require("child_process").spawnSync, + fs = require("fs"), + https = require("https") + +class Action { + constructor() { + this.PROJECT_FILE_PATH = process.env.INPUT_PROJECT_FILE_PATH + this.VERSION_FILE_PATH = process.env.INPUT_VERSION_FILE_PATH || process.env.VERSION_FILE_PATH + this.VERSION_REGEX = new RegExp(process.env.INPUT_VERSION_REGEX || process.env.VERSION_REGEX) + this.TAG_COMMIT = JSON.parse(process.env.INPUT_TAG_COMMIT || process.env.TAG_COMMIT) + this.TAG_FORMAT = process.env.INPUT_TAG_FORMAT || process.env.TAG_FORMAT + this.NUGET_KEY = process.env.INPUT_NUGET_KEY || process.env.NUGET_KEY + this.PACKAGE_NAME = process.env.INPUT_PACKAGE_NAME || process.env.PACKAGE_NAME + } + + _warn(msg) { + console.log(`##[warning]${msg}`) + } + + _fail(msg) { + console.log(`##[error]${msg}`) + throw new Error(msg) + } + + _execCmd(cmd, options) { + const INPUT = cmd.split(" "), TOOL = INPUT[0], ARGS = INPUT.slice(1) + return spawnSync(TOOL, ARGS, options) + } + + _execAndCapture(cmd) { + return this._execCmd(cmd, { encoding: "utf-8" }).stdout + } + + _execInProc(cmd) { + this._execCmd(cmd, { encoding: "utf-8", stdio: [process.stdin, process.stdout, process.stderr] }) + } + + _resolveIfExists(filePath, msg) { + const FULLPATH = path.resolve(process.env.GITHUB_WORKSPACE, filePath) + if (!fs.existsSync(FULLPATH)) this._fail(msg) + return FULLPATH + } + + _pushPackage() { + if (!this.NUGET_KEY) { + this._warn("😢 nuget_key not given") + return + } + + if (!this._execAndCapture("dotnet --version")) { + this._warn("😭 dotnet not found") + return + } + + this._execInProc(`dotnet pack -c Release ${this.PROJECT_FILE_PATH} -o .`) + const NUGET_PUSH_RESPONSE = this._execAndCapture(`dotnet nuget push *.nupkg -s https://api.nuget.org/v3/index.json -k ${this.NUGET_KEY}`) + const NUGET_ERROR_REGEX = /(error: Response status code does not indicate success.*)/ + + if (NUGET_ERROR_REGEX.test(NUGET_PUSH_RESPONSE)) + this._fail(`😭 ${NUGET_ERROR_REGEX.exec(NUGET_PUSH_RESPONSE)[1]}`) + } + + _tagCommit(version) { + if (this.TAG_COMMIT) { + const TAG = this.TAG_FORMAT.replace("*", version) + + if (this._execAndCapture(`git ls-remote --tags origin ${TAG}`).indexOf(TAG) >= 0) { + this._warn(`😢 tag ${TAG} already exists`) + return + } + + this._execInProc(`git tag ${TAG}`) + this._execInProc(`git push origin ${TAG}`) + } + } + + _pushAndTag(version, name) { + console.log(`👍 found a new version (${version}) of ${name}`) + this._tagCommit(version) + this._pushPackage() + } + + run() { + if (!this.PROJECT_FILE_PATH) + this._fail("😭 project file not given") + + this.PROJECT_FILE_PATH = this._resolveIfExists(this.PROJECT_FILE_PATH, "😭 project file not found") + this.VERSION_FILE_PATH = !this.VERSION_FILE_PATH ? this.PROJECT_FILE_PATH : this._resolveIfExists(this.VERSION_FILE_PATH, "😭 version file not found") + + const FILE_CONTENT = fs.readFileSync(this.VERSION_FILE_PATH, { encoding: "utf-8" }), + VERSION_INFO = this.VERSION_REGEX.exec(FILE_CONTENT) + + if (!VERSION_INFO) + this._fail("😢 unable to extract version info") + + const CURRENT_VERSION = VERSION_INFO[1] + + if (!this.PACKAGE_NAME) + this.PACKAGE_NAME = path.basename(this.PROJECT_FILE_PATH).split(".").slice(0, -1).join(".") + + https.get(`https://api.nuget.org/v3-flatcontainer/${this.PACKAGE_NAME}/index.json`, res => { + let body = "" + + if (res.statusCode == 404) + this._pushAndTag(CURRENT_VERSION, this.PACKAGE_NAME) + + if (res.statusCode == 200) { + res.setEncoding("utf8") + res.on("data", chunk => body += chunk) + res.on("end", () => { + const existingVersions = JSON.parse(body) + if (existingVersions.versions.indexOf(CURRENT_VERSION) < 0) + this._pushAndTag(CURRENT_VERSION, this.PACKAGE_NAME) + }) + } + }).on("error", e => { + this._warn(`😢 error reaching nuget.org ${e.message}`) + }) + } +} + +new Action().run()