diff --git a/.github/version.yml b/.github/version.yml index 56faa73..5804257 100644 --- a/.github/version.yml +++ b/.github/version.yml @@ -5,19 +5,12 @@ on: pattern: '(?<=export const version = ").*(?=";)' - kind: regexp file: README.md - pattern: '(?<=semver-cli@).*(?=\/main.ts)' - - kind: regexp - file: README.md - pattern: "(?<=semver-cli@).*$" - - kind: regexp - file: Dockerfile - pattern: '(?<=VERSION=).*(?=; \\)' + pattern: "(?<=semver-cli@).*" + flags: g - kind: regexp file: setup/action.yml pattern: "(?<=default: ).*" - - kind: regexp - file: action.yml - pattern: "(?<=default: ).*" - kind: regexp file: Dockerfile.action pattern: "(?<=semver-cli:).*" + format: docker diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 4ce64d1..9c0d782 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -17,7 +17,15 @@ jobs: with: deno-version: v2.x - - run: deno --version + # When we develop this internally we have to go through the repo1 mirror + # When we run it in GitHub its running outside of the optum network and cant access repo1 + # Ideally these lock files wouldn't store the repository in it but just the sha of the module + # For now we have to remove the lock file in order to install the dependencies in the ci server + - name: Install Dependencies + run: | + rm deno.lock + deno install --no-lock + - run: deno fmt --check - run: deno lint - run: deno task test diff --git a/.gitignore b/.gitignore index 8cca141..74d7048 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ bin obj .vscode deno.zip +node_modules diff --git a/Dockerfile b/Dockerfile index 40484d4..a4ea336 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,18 +20,17 @@ WORKDIR /app ENV PATH="/app/bin:${PATH}" RUN mkdir -p /app/bin -# Cache the dependencies as a layer (the following two steps are re-run only when deps.ts is modified). -# Ideally cache deps.ts will download and compile _all_ external files used in main.ts. -COPY deps/ /app/deps +# Cache the dependencies as a layer (the following two steps are re-run only when deno.json/deno.lock is modified). +# Install dependencies from npm and JSR registries instead of copying deps folder COPY deno.json /app/ COPY deno.lock /app/ -RUN deno cache --allow-import deps/mod.ts +RUN rm deno.lock && \ + deno install # These steps will be re-run upon any file change in your working directory: ADD src /app/src ADD main.ts /app # Compile the main app so that it doesn't need to be compiled each startup/entry. -RUN deno cache main.ts RUN deno compile --allow-run --allow-env --allow-read --allow-write -o bin/semver main.ts ENTRYPOINT ["semver"] diff --git a/README.md b/README.md index a445b73..dbc7576 100644 --- a/README.md +++ b/README.md @@ -96,15 +96,10 @@ semver parse 1.0.0 # {"major":1,"minor":1,"patch":0,"prerelease":[],"build":[]} When calling the command `inc` the `VERSION` file will be updated based on the sub command specified, `major`, `minor`, `patch`, `none`. Additional metadata -may be added to the version using the `--pre` and `--build` parameters. If the -`--name` parameter is specified then that will be used instead of the default -`pre`. If the same prerelease name is used multiple times the prerelease number -will be incremented and it defaults to `0` if set initially or changed to a new -name. If the argument `--value` is set then the prerelease number will be -specifically set to the value provided. +may be added to the version using the `--prerelease` and `--build` parameters. `none` can be used to synchronize new or out of sync files with post hooks, and -also it can be used in conjunction with `--pre` and `--build` without +also it can be used in conjunction with `--prerelease` and `--build` without incrementing the main version numbers. #### examples @@ -119,14 +114,10 @@ semver inc major # 2.0.0 ```sh semver set 1.2.3-pre.0 -semver inc --pre # 1.2.3-pre.1 -semver inc --pre --value 10 # 1.2.3-pre.10 -semver inc --pre --name alpha # 1.2.3-alpha.0 +semver inc --prerelease alpha # 1.2.3-alpha.0 +semver inc --prerelease alpha # 1.2.3-alpha.1 semver inc --build 1 # 1.2.3-alpha.1+1 -semver inc --pre \ - --name alpha \ - --value 11 \ - --build abc123 # 1.2.3-alpha.11+abc123 +semver inc --prerelease beta # 1.2.3-beta.0+1 ``` ### Increment Post Hooks @@ -197,7 +188,7 @@ jobs: steps: - if: inputs.pre name: Increment Pre-Release Version - uses: optum/semver-cli@0.9.20 + uses: optum/semver-cli@0.9.27 with: action: inc pre: true @@ -207,7 +198,7 @@ jobs: - id: version name: Get Version - uses: optum/semver-cli@0.9.20 + uses: optum/semver-cli@0.9.27 - run: echo "The calculated ${{ steps.version.outputs.version }}" ``` diff --git a/action.yml b/action.yml index 9940438..08f2c0e 100644 --- a/action.yml +++ b/action.yml @@ -4,31 +4,43 @@ branding: icon: activity color: orange inputs: - action: - description: "A versioning action to perform (get|set|inc|parse)" - required: false command: + type: choice + description: Command + default: get + required: false + options: + - get + - set + - inc + - parse + sub-command: type: choice description: "The kind of increment (major|minor|patch|none) for (get|inc) actions" required: false + default: none options: - - none - major - minor - patch - pre: - type: boolean - description: "Whether or not to create a pre-release version (inc|get)" - name: - description: "If pre is set, you may optionally specify a prerelease name" + - none + prerelease: + type: string + description: Optional Prerelease Metadata required: false - value: - description: "If pre is set, you may optionally specify a prerelease number" build: - description: "Optional build metadata" + type: string + description: Optional Build Metadata + required: false + value: + type: string + description: The Version (for set action or parse action) + required: false + config: + type: string + description: "Path to a configuration file" required: false - current: - description: "The version for the set command" + default: .github/version.yml outputs: version: @@ -51,13 +63,12 @@ runs: using: "docker" image: "Dockerfile.action" args: - - ${{ inputs.action || 'get' }} - ${{ inputs.command }} - - ${{ inputs.pre && '--pre' || ''}} - - ${{ inputs.name && '--name' || '' }} - - ${{ inputs.name || '' }} - - ${{ inputs.value && '--value' || '' }} + - ${{ inputs.sub-command }} - ${{ inputs.value || '' }} + - ${{ inputs.prerelease && '--prerelease' || '' }} + - ${{ inputs.prerelease || '' }} - ${{ inputs.build && '--build' || '' }} - ${{ inputs.build || '' }} - - ${{ inputs.current }} + - ${{ inputs.config && '--config' || '' }} + - ${{ inputs.config || '' }} diff --git a/deno.json b/deno.json index 1747f1a..fc2dac1 100644 --- a/deno.json +++ b/deno.json @@ -1,11 +1,24 @@ { + "nodeModulesDir": "auto", + "imports": { + "@std/assert": "jsr:@std/assert@^1.0.14", + "json5": "npm:json5@^2.2.3", + "jsonc-parser": "npm:jsonc-parser@^3.2.1", + "semver": "jsr:@std/semver@^1.0.3", + "path": "jsr:@std/path@^1.0.6", + "assert": "jsr:@std/assert@^1.0.6", + "testing/bdd": "jsr:@std/testing@^1.0.3/bdd", + "testing/mock": "jsr:@std/testing@^1.0.3/mock", + "yaml": "jsr:@std/yaml@^1.0.5", + "yargs": "npm:yargs@^17.7.2" + }, "tasks": { - "check": "deno fmt && deno lint && deno task test", + "check": "deno fmt && deno lint && deno task test && deno run -A main.ts parse", "install": "deno install --allow-run --allow-env --allow-read --allow-write -f main.ts -n semver", "test": "deno test && deno task test:node && deno task test:helm && deno task test:maven && deno task test:dotnet", - "test:node": "(cd test/node && deno run -A ../../main.ts inc minor --pre --name alpha --build xyz.987)", - "test:helm": "(cd test/helm && deno run -A ../../main.ts inc minor --pre --name beta --build abc.123)", - "test:maven": "(cd test/maven && deno run -A ../../main.ts inc minor --pre --name omega --build def.456)", - "test:dotnet": "(cd test/dotnet && deno run -A ../../main.ts inc minor --pre --name lambda --build ghi.789)" + "test:node": "(cd test/node && deno run -A ../../main.ts inc minor --prerelease alpha --build xyz.987)", + "test:helm": "(cd test/helm && deno run -A ../../main.ts inc minor --prerelease beta --build abc.123)", + "test:maven": "(cd test/maven && deno run -A ../../main.ts inc minor --prerelease omega --build def.456)", + "test:dotnet": "(cd test/dotnet && deno run -A ../../main.ts inc minor --prerelease lambda --build ghi.789)" } } diff --git a/deno.lock b/deno.lock index 704765d..2ed11cd 100644 --- a/deno.lock +++ b/deno.lock @@ -1,5 +1,157 @@ { - "version": "4", + "version": "5", + "specifiers": { + "jsr:@std/assert@^1.0.13": "1.0.14", + "jsr:@std/assert@^1.0.14": "1.0.14", + "jsr:@std/assert@^1.0.6": "1.0.14", + "jsr:@std/internal@^1.0.10": "1.0.10", + "jsr:@std/path@^1.0.6": "1.1.2", + "jsr:@std/semver@*": "1.0.5", + "jsr:@std/semver@^1.0.3": "1.0.5", + "jsr:@std/testing@^1.0.3": "1.0.15", + "jsr:@std/yaml@^1.0.5": "1.0.9", + "npm:json5@^2.2.3": "2.2.3", + "npm:jsonc-parser@^3.2.1": "3.3.1", + "npm:yargs@^17.7.2": "17.7.2" + }, + "jsr": { + "@std/assert@1.0.14": { + "integrity": "68d0d4a43b365abc927f45a9b85c639ea18a9fab96ad92281e493e4ed84abaa4", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/internal@1.0.10": { + "integrity": "e3be62ce42cab0e177c27698e5d9800122f67b766a0bea6ca4867886cbde8cf7" + }, + "@std/path@1.1.2": { + "integrity": "c0b13b97dfe06546d5e16bf3966b1cadf92e1cc83e56ba5476ad8b498d9e3038", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/semver@1.0.5": { + "integrity": "529f79e83705714c105ad0ba55bec0f9da0f24d2f726b6cc1c15e505cc2c0624" + }, + "@std/testing@1.0.15": { + "integrity": "a490169f5ccb0f3ae9c94fbc69d2cd43603f2cffb41713a85f99bbb0e3087cbc", + "dependencies": [ + "jsr:@std/assert@^1.0.13", + "jsr:@std/internal" + ] + }, + "@std/yaml@1.0.9": { + "integrity": "6bad3dc766dd85b4b37eabcba81b6aa4eac7a392792ae29abcfb0f90602d55bb" + } + }, + "npm": { + "ansi-regex@5.0.1": { + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/ansi-regex/-/ansi-regex-5.0.1.tgz" + }, + "ansi-styles@4.3.0": { + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": [ + "color-convert" + ], + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/ansi-styles/-/ansi-styles-4.3.0.tgz" + }, + "cliui@8.0.1": { + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": [ + "string-width", + "strip-ansi", + "wrap-ansi" + ], + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/cliui/-/cliui-8.0.1.tgz" + }, + "color-convert@2.0.1": { + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": [ + "color-name" + ], + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/color-convert/-/color-convert-2.0.1.tgz" + }, + "color-name@1.1.4": { + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/color-name/-/color-name-1.1.4.tgz" + }, + "emoji-regex@8.0.0": { + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/emoji-regex/-/emoji-regex-8.0.0.tgz" + }, + "escalade@3.2.0": { + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/escalade/-/escalade-3.2.0.tgz" + }, + "get-caller-file@2.0.5": { + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/get-caller-file/-/get-caller-file-2.0.5.tgz" + }, + "is-fullwidth-code-point@3.0.0": { + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + }, + "json5@2.2.3": { + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": true, + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/json5/-/json5-2.2.3.tgz" + }, + "jsonc-parser@3.3.1": { + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/jsonc-parser/-/jsonc-parser-3.3.1.tgz" + }, + "require-directory@2.1.1": { + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/require-directory/-/require-directory-2.1.1.tgz" + }, + "string-width@4.2.3": { + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": [ + "emoji-regex", + "is-fullwidth-code-point", + "strip-ansi" + ], + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/string-width/-/string-width-4.2.3.tgz" + }, + "strip-ansi@6.0.1": { + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": [ + "ansi-regex" + ], + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/strip-ansi/-/strip-ansi-6.0.1.tgz" + }, + "wrap-ansi@7.0.0": { + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": [ + "ansi-styles", + "string-width", + "strip-ansi" + ], + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + }, + "y18n@5.0.8": { + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/y18n/-/y18n-5.0.8.tgz" + }, + "yargs-parser@21.1.1": { + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/yargs-parser/-/yargs-parser-21.1.1.tgz" + }, + "yargs@17.7.2": { + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": [ + "cliui", + "escalade", + "get-caller-file", + "require-directory", + "string-width", + "y18n", + "yargs-parser" + ], + "tarball": "https://repo1.uhc.com:443/artifactory/api/npm/npm-virtual/yargs/-/yargs-17.7.2.tgz" + } + }, "redirects": { "https://deno.land/std/fmt/printf.ts": "https://deno.land/std@0.224.0/fmt/printf.ts", "https://deno.land/std/path/mod.ts": "https://deno.land/std@0.224.0/path/mod.ts", @@ -288,5 +440,18 @@ "https://deno.land/x/yargs_parser@v20.2.4-deno/build/lib/tokenize-arg-string.js": "7e0875b11795b8e217386e45f14b24a6e501ebbc62e15aa469aa8829d4d0ee61", "https://deno.land/x/yargs_parser@v20.2.4-deno/build/lib/yargs-parser.js": "453200a7dfbb002e605d8009b7dad30f2b1d93665e046ab89c073a4fe63dfd48", "https://deno.land/x/yargs_parser@v20.2.4-deno/deno.ts": "ad53c0c82c3982c4fc5be9472384b259e0a32ce1f7ae0f68de7b2445df5642fc" + }, + "workspace": { + "dependencies": [ + "jsr:@std/assert@^1.0.14", + "jsr:@std/assert@^1.0.6", + "jsr:@std/path@^1.0.6", + "jsr:@std/semver@^1.0.3", + "jsr:@std/testing@^1.0.3", + "jsr:@std/yaml@^1.0.5", + "npm:json5@^2.2.3", + "npm:jsonc-parser@^3.2.1", + "npm:yargs@^17.7.2" + ] } } diff --git a/deps/json5.ts b/deps/json5.ts deleted file mode 100644 index d453af0..0000000 --- a/deps/json5.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as JSON5 from "https://deno.land/x/json5@v1.0.0/mod.ts"; -export { JSON5 }; diff --git a/deps/jsonc.ts b/deps/jsonc.ts deleted file mode 100644 index 6c83821..0000000 --- a/deps/jsonc.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as JSONC from "https://deno.land/x/jsonc@1/main.ts"; -export { JSONC }; diff --git a/deps/mod.ts b/deps/mod.ts deleted file mode 100644 index c7299aa..0000000 --- a/deps/mod.ts +++ /dev/null @@ -1,7 +0,0 @@ -import "./json5.ts"; -import "./jsonc.ts"; -import "./semver.ts"; -import "./std.ts"; -import "./xml.ts"; -import "./yaml.ts"; -import "./yargs.ts"; diff --git a/deps/semver.ts b/deps/semver.ts deleted file mode 100644 index 774ab36..0000000 --- a/deps/semver.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "https://deno.land/std@0.209.0/semver/mod.ts"; diff --git a/deps/std.ts b/deps/std.ts deleted file mode 100644 index f7a5a26..0000000 --- a/deps/std.ts +++ /dev/null @@ -1,17 +0,0 @@ -export * as path from "https://deno.land/std@0.152.0/path/mod.ts"; -export * from "https://deno.land/std@0.152.0/testing/asserts.ts"; -export { - assertSpyCall, - assertSpyCalls, - resolvesNext, - returnsNext, - spy, - stub, -} from "https://deno.land/std@0.152.0/testing/mock.ts"; -export type { Spy, Stub } from "https://deno.land/std@0.152.0/testing/mock.ts"; -export { - afterEach, - beforeEach, - describe, - it, -} from "https://deno.land/std@0.152.0/testing/bdd.ts"; diff --git a/deps/xml.ts b/deps/xml.ts deleted file mode 100644 index 027f7fe..0000000 --- a/deps/xml.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { xml2js as parse } from "https://deno.land/x/xml2js@1.0.0/mod.ts"; -import { js2xml as stringify } from "https://deno.land/x/js2xml@1.0.4/mod.ts"; - -export interface Node extends Record { - elements: Element[]; -} - -export interface Element extends Node { - type: "element" | "text"; - name: string; - attributes: Record; -} - -export const xml = { parse, stringify }; diff --git a/deps/yaml.ts b/deps/yaml.ts deleted file mode 100644 index 83f6150..0000000 --- a/deps/yaml.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { - parse, - parseAll, - stringify, -} from "https://deno.land/std@0.182.0/yaml/mod.ts"; - -export const YAML = { parse, parseAll, stringify }; diff --git a/deps/yargs.ts b/deps/yargs.ts deleted file mode 100644 index 13abeb1..0000000 --- a/deps/yargs.ts +++ /dev/null @@ -1,6 +0,0 @@ -import yargs from "https://deno.land/x/yargs@v17.7.2-deno/deno.ts"; -import { YargsInstance } from "https://deno.land/x/yargs@v17.7.2-deno/build/lib/yargs-factory.js"; -import { Arguments } from "https://deno.land/x/yargs@v17.7.2-deno/deno-types.ts"; - -export type { Arguments }; -export { yargs, YargsInstance }; diff --git a/main.ts b/main.ts index fbd7167..b2367f0 100644 --- a/main.ts +++ b/main.ts @@ -1,4 +1,4 @@ -import { yargs } from "./deps/yargs.ts"; +import yargs from "yargs"; import { version } from "./src/info.ts"; import { get, inc, parse, set } from "./src/commands/mod.ts"; import { getContext } from "./src/context.ts"; @@ -14,6 +14,7 @@ await yargs() .command(set) .command(inc) .command(parse) + .strictOptions() .strictCommands() .demandCommand(1) .version(version) diff --git a/semver-cli.sln b/semver-cli.sln new file mode 100644 index 0000000..1bb7550 --- /dev/null +++ b/semver-cli.sln @@ -0,0 +1,29 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{0C88DD14-F956-CE84-757C-A364CCF449FC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example", "test\dotnet\example.csproj", "{F6A25165-90B6-AA43-6257-EBEAEC16634A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F6A25165-90B6-AA43-6257-EBEAEC16634A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6A25165-90B6-AA43-6257-EBEAEC16634A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6A25165-90B6-AA43-6257-EBEAEC16634A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6A25165-90B6-AA43-6257-EBEAEC16634A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F6A25165-90B6-AA43-6257-EBEAEC16634A} = {0C88DD14-F956-CE84-757C-A364CCF449FC} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {51D20147-773F-4FF4-B292-10A11DC46D8D} + EndGlobalSection +EndGlobal diff --git a/src/commands/get.ts b/src/commands/get.ts index c56a0a8..2de0e52 100644 --- a/src/commands/get.ts +++ b/src/commands/get.ts @@ -1,13 +1,6 @@ -import { YargsInstance } from "../../deps/yargs.ts"; +import type { YargsInstance } from "yargs"; import { major, minor, none, patch } from "./get/mod.ts"; -import { - build, - config, - output, - prerelease, - prereleaseName, - prereleaseValue, -} from "./options.ts"; +import { build, config, output, prerelease } from "./options.ts"; export const get = { command: "get", @@ -16,14 +9,13 @@ export const get = { yargs .option("config", config) .option("output", output) + .option("prerelease", prerelease) .option("build", build) - .option("pre", prerelease) - .option("name", prereleaseName) - .option("value", prereleaseValue) .command(major) .command(minor) .command(patch) .command(none) + .strictOptions() .strictCommands() .demandCommand(1), }; diff --git a/src/commands/get/major.ts b/src/commands/get/major.ts index 20bba0f..8f999ee 100644 --- a/src/commands/get/major.ts +++ b/src/commands/get/major.ts @@ -1,4 +1,4 @@ -import { Arguments } from "../../../deps/yargs.ts"; +import type { Arguments } from "yargs"; import { increment, IncrementKind } from "../../util/increment.ts"; import { printVersion, readVersionFile } from "../../util/version.ts"; import { IContext } from "../../context.ts"; @@ -7,13 +7,12 @@ export const major = { command: "major", describe: "A major version increment", handler: async (args: Arguments & IContext) => { - const { pre, name = "pre", value, build } = args; + const { prerelease, build } = args; const version = await readVersionFile(); const { current } = increment({ - kind: IncrementKind.Major, version, - pre: pre ? name : undefined, - value, + kind: IncrementKind.Major, + prerelease, build, }); await printVersion(args, current); diff --git a/src/commands/get/minor.ts b/src/commands/get/minor.ts index bc462a1..e2033f4 100644 --- a/src/commands/get/minor.ts +++ b/src/commands/get/minor.ts @@ -1,4 +1,4 @@ -import { Arguments } from "../../../deps/yargs.ts"; +import type { Arguments } from "yargs"; import { increment, IncrementKind } from "../../util/increment.ts"; import { printVersion, readVersionFile } from "../../util/version.ts"; import { IContext } from "../../context.ts"; @@ -7,13 +7,12 @@ export const minor = { command: "minor", describe: "A minor version increment", handler: async (args: Arguments & IContext) => { - const { pre, name, value, build } = args; + const { prerelease, build } = args; const version = await readVersionFile(); const { current } = increment({ - kind: IncrementKind.Minor, version, - pre: pre ? name : undefined, - value, + kind: IncrementKind.Minor, + prerelease, build, }); await printVersion(args, current); diff --git a/src/commands/get/none.ts b/src/commands/get/none.ts index b5b3b17..d66edd4 100644 --- a/src/commands/get/none.ts +++ b/src/commands/get/none.ts @@ -1,4 +1,4 @@ -import { Arguments } from "../../../deps/yargs.ts"; +import type { Arguments } from "yargs"; import { increment, IncrementKind } from "../../util/increment.ts"; import { printVersion, readVersionFile } from "../../util/version.ts"; import { IContext } from "../../context.ts"; @@ -7,13 +7,12 @@ export const none = { command: ["none", "$0"], describe: "Gets the version", handler: async (args: Arguments & IContext) => { - const { pre, name, value, build } = args; + const { prerelease, build } = args; const version = await readVersionFile(); const { current } = increment({ - kind: IncrementKind.None, version, - pre: pre ? name : undefined, - value, + kind: IncrementKind.None, + prerelease, build, }); await printVersion(args, current); diff --git a/src/commands/get/patch.ts b/src/commands/get/patch.ts index 549a242..518e176 100644 --- a/src/commands/get/patch.ts +++ b/src/commands/get/patch.ts @@ -1,4 +1,4 @@ -import { Arguments } from "../../../deps/yargs.ts"; +import type { Arguments } from "yargs"; import { increment, IncrementKind } from "../../util/increment.ts"; import { printVersion, readVersionFile } from "../../util/version.ts"; import { IContext } from "../../context.ts"; @@ -7,13 +7,12 @@ export const patch = { command: "patch", describe: "A patch version increment", handler: async (args: Arguments & IContext) => { - const { pre, name, value, build } = args; + const { prerelease, build } = args; const version = await readVersionFile(); const { current } = increment({ - kind: IncrementKind.Patch, version, - pre: pre ? name : undefined, - value, + kind: IncrementKind.Patch, + prerelease, build, }); await printVersion(args, current); diff --git a/src/commands/inc.ts b/src/commands/inc.ts index 3c7d78b..797a511 100644 --- a/src/commands/inc.ts +++ b/src/commands/inc.ts @@ -1,13 +1,6 @@ -import { YargsInstance } from "../../deps/yargs.ts"; +import type { YargsInstance } from "yargs"; import { major, minor, none, patch } from "./inc/mod.ts"; -import { - build, - config, - output, - prerelease, - prereleaseName, - prereleaseValue, -} from "./options.ts"; +import { build, config, output, prerelease } from "./options.ts"; export const inc = { command: "inc", @@ -16,14 +9,13 @@ export const inc = { yargs .option("config", config) .option("output", output) + .option("prerelease", prerelease) .option("build", build) - .option("pre", prerelease) - .option("name", prereleaseName) - .option("value", prereleaseValue) .command(major) .command(minor) .command(patch) .command(none) + .strictOptions() .strictCommands() .demandCommand(1), }; diff --git a/src/commands/inc/major.test.ts b/src/commands/inc/major.test.ts index aa27bf7..6e24f2f 100644 --- a/src/commands/inc/major.test.ts +++ b/src/commands/inc/major.test.ts @@ -1,12 +1,6 @@ -import { - assertSpyCall, - describe, - it, - resolvesNext, - returnsNext, - stub, -} from "../../../deps/std.ts"; -import { Arguments } from "../../../deps/yargs.ts"; +import { describe, it } from "testing/bdd"; +import { assertSpyCall, resolvesNext, returnsNext, stub } from "testing/mock"; +import type { Arguments } from "yargs"; import { major } from "./major.ts"; import { testContext } from "../../util/testContext.ts"; import { IContext } from "../../context.ts"; @@ -44,15 +38,14 @@ describe("major", () => { await major.handler( { _: [], - pre: true, - name: "pre", + prerelease: "pr", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["2.0.0-pre.0"], + args: ["2.0.0-pr.0"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "2.0.0-pre.0\n"], + args: ["VERSION", "2.0.0-pr.0\n"], }); }); it("major02", async () => { @@ -73,33 +66,29 @@ describe("major", () => { await major.handler( { _: [], - pre: true, - name: "pre", - value: "7", + prerelease: "pr", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["2.0.0-pre.7"], + args: ["2.0.0-pr.0"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "2.0.0-pre.7\n"], + args: ["VERSION", "2.0.0-pr.0\n"], }); }); it("major05", async () => { await major.handler( { _: [], - pre: true, - name: "pre", - value: "7", + prerelease: "pr", build: "abc123", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["2.0.0-pre.7+abc123"], + args: ["2.0.0-pr.0+abc123"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "2.0.0-pre.7+abc123\n"], + args: ["VERSION", "2.0.0-pr.0+abc123\n"], }); }); }); diff --git a/src/commands/inc/major.ts b/src/commands/inc/major.ts index 90b7d4c..03e744e 100644 --- a/src/commands/inc/major.ts +++ b/src/commands/inc/major.ts @@ -1,4 +1,4 @@ -import { Arguments } from "../../../deps/yargs.ts"; +import type { Arguments } from "yargs"; import { increment, IncrementKind } from "../../util/increment.ts"; import { printVersion, @@ -12,13 +12,12 @@ export const major = { command: "major", describe: "A major version increment", handler: async (args: Arguments & IContext) => { - const { pre, name, value, build } = args; + const { prerelease, build } = args; const version = await readVersionFile(); const { previous, current } = increment({ - kind: IncrementKind.Major, version, - pre: pre ? name : undefined, - value, + kind: IncrementKind.Major, + prerelease, build, }); await writeVersionFile(current); diff --git a/src/commands/inc/minor.test.ts b/src/commands/inc/minor.test.ts index 875aae2..eabda82 100644 --- a/src/commands/inc/minor.test.ts +++ b/src/commands/inc/minor.test.ts @@ -1,12 +1,6 @@ -import { - assertSpyCall, - describe, - it, - resolvesNext, - returnsNext, - stub, -} from "../../../deps/std.ts"; -import { Arguments } from "../../../deps/yargs.ts"; +import { describe, it } from "testing/bdd"; +import { assertSpyCall, resolvesNext, returnsNext, stub } from "testing/mock"; +import type { Arguments } from "yargs"; import { minor } from "./minor.ts"; import { testContext } from "../../util/testContext.ts"; import { IContext } from "../../context.ts"; @@ -54,15 +48,14 @@ describe("minor", () => { await minor.handler( { _: [], - pre: true, - name: "pre", + prerelease: "pr", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.3.0-pre.0"], + args: ["1.3.0-pr.0"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.3.0-pre.0\n"], + args: ["VERSION", "1.3.0-pr.0\n"], }); }); it("minor02", async () => { @@ -85,16 +78,14 @@ describe("minor", () => { { ...context, _: [], - pre: true, - name: "pre", - value: "7", + prerelease: "pr", } as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.3.0-pre.7"], + args: ["1.3.0-pr.0"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.3.0-pre.7\n"], + args: ["VERSION", "1.3.0-pr.0\n"], }); }); it("minor05", async () => { @@ -102,17 +93,15 @@ describe("minor", () => { { ...context, _: [], - pre: true, - name: "pre", - value: "7", + prerelease: "pr", build: "abc123", } as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.3.0-pre.7+abc123"], + args: ["1.3.0-pr.0+abc123"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.3.0-pre.7+abc123\n"], + args: ["VERSION", "1.3.0-pr.0+abc123\n"], }); }); }); diff --git a/src/commands/inc/minor.ts b/src/commands/inc/minor.ts index 898e5ba..4084151 100644 --- a/src/commands/inc/minor.ts +++ b/src/commands/inc/minor.ts @@ -1,4 +1,4 @@ -import { Arguments } from "../../../deps/yargs.ts"; +import type { Arguments } from "yargs"; import { increment, IncrementKind } from "../../util/increment.ts"; import { printVersion, @@ -12,13 +12,12 @@ export const minor = { command: "minor", describe: "A minor version increment", handler: async (args: Arguments & IContext) => { - const { pre, name, value, build } = args; + const { prerelease, build } = args; const version = await readVersionFile(); const { previous, current } = increment({ - kind: IncrementKind.Minor, version, - pre: pre ? name : undefined, - value, + kind: IncrementKind.Minor, + prerelease, build, }); await writeVersionFile(current); diff --git a/src/commands/inc/none.test.ts b/src/commands/inc/none.test.ts index 5df6f15..62ae62e 100644 --- a/src/commands/inc/none.test.ts +++ b/src/commands/inc/none.test.ts @@ -1,12 +1,6 @@ -import { - assertSpyCall, - describe, - it, - resolvesNext, - returnsNext, - stub, -} from "../../../deps/std.ts"; -import { Arguments } from "../../../deps/yargs.ts"; +import { describe, it } from "testing/bdd"; +import { assertSpyCall, resolvesNext, returnsNext, stub } from "testing/mock"; +import type { Arguments } from "yargs"; import { none } from "./none.ts"; import { testContext } from "../../util/testContext.ts"; import { IContext } from "../../context.ts"; @@ -44,15 +38,14 @@ describe("none", () => { await none.handler( { _: [], - pre: true, - name: "pre", + prerelease: "pr", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.2.3-pre.0"], + args: ["1.2.3-pr.0"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.2.3-pre.0\n"], + args: ["VERSION", "1.2.3-pr.0\n"], }); }); it("none02", async () => { @@ -73,33 +66,29 @@ describe("none", () => { await none.handler( { _: [], - pre: true, - name: "pre", - value: "7", + prerelease: "pr", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.2.3-pre.7"], + args: ["1.2.3-pr.0"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.2.3-pre.7\n"], + args: ["VERSION", "1.2.3-pr.0\n"], }); }); it("none04", async () => { await none.handler( { _: [], - pre: true, - name: "pre", - value: "7", + prerelease: "pr", build: "abc.123", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.2.3-pre.7+abc.123"], + args: ["1.2.3-pr.0+abc.123"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.2.3-pre.7+abc.123\n"], + args: ["VERSION", "1.2.3-pr.0+abc.123\n"], }); }); }); diff --git a/src/commands/inc/none.ts b/src/commands/inc/none.ts index c68fe91..6deb106 100644 --- a/src/commands/inc/none.ts +++ b/src/commands/inc/none.ts @@ -1,4 +1,4 @@ -import { Arguments } from "../../../deps/yargs.ts"; +import type { Arguments } from "yargs"; import { increment, IncrementKind } from "../../util/increment.ts"; import { printVersion, @@ -12,13 +12,12 @@ export const none = { command: ["none", "$0"], describe: "A none version increment", handler: async (args: Arguments & IContext) => { - const { pre, name, value, build } = args; + const { prerelease, build } = args; const version = await readVersionFile(); const { previous, current } = increment({ - kind: IncrementKind.None, version, - pre: pre ? name : undefined, - value, + kind: IncrementKind.None, + prerelease, build, }); await writeVersionFile(current); diff --git a/src/commands/inc/patch.test.ts b/src/commands/inc/patch.test.ts index b5cbf5d..42dda31 100644 --- a/src/commands/inc/patch.test.ts +++ b/src/commands/inc/patch.test.ts @@ -1,12 +1,6 @@ -import { - assertSpyCall, - describe, - it, - resolvesNext, - returnsNext, - stub, -} from "../../../deps/std.ts"; -import { Arguments } from "../../../deps/yargs.ts"; +import { describe, it } from "testing/bdd"; +import { assertSpyCall, resolvesNext, returnsNext, stub } from "testing/mock"; +import type { Arguments } from "yargs"; import { patch } from "./patch.ts"; import { testContext } from "../../util/testContext.ts"; import { IContext } from "../../context.ts"; @@ -44,15 +38,14 @@ describe("patch", () => { await patch.handler( { _: [], - pre: true, - name: "pre", + prerelease: "pr", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.2.4-pre.0"], + args: ["1.2.4-pr.0"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.2.4-pre.0\n"], + args: ["VERSION", "1.2.4-pr.0\n"], }); }); it("patch02", async () => { @@ -73,33 +66,29 @@ describe("patch", () => { await patch.handler( { _: [], - pre: true, - name: "pre", - value: "7", + prerelease: "pr", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.2.4-pre.7"], + args: ["1.2.4-pr.0"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.2.4-pre.7\n"], + args: ["VERSION", "1.2.4-pr.0\n"], }); }); it("patch04", async () => { await patch.handler( { _: [], - pre: true, - name: "pre", - value: "7", + prerelease: "pre", build: "abc.123", } as unknown as Arguments & IContext, ); assertSpyCall(ctx0.consoleLog, 0, { - args: ["1.2.4-pre.7+abc.123"], + args: ["1.2.4-pre.0+abc.123"], }); assertSpyCall(ctx0.writeTextFile, 0, { - args: ["VERSION", "1.2.4-pre.7+abc.123\n"], + args: ["VERSION", "1.2.4-pre.0+abc.123\n"], }); }); }); diff --git a/src/commands/inc/patch.ts b/src/commands/inc/patch.ts index 12c6c9f..2b75605 100644 --- a/src/commands/inc/patch.ts +++ b/src/commands/inc/patch.ts @@ -1,4 +1,4 @@ -import { Arguments } from "../../../deps/yargs.ts"; +import type { Arguments } from "yargs"; import { increment, IncrementKind } from "../../util/increment.ts"; import { printVersion, @@ -12,13 +12,12 @@ export const patch = { command: "patch", describe: "A patch version increment", handler: async (args: Arguments & IContext) => { - const { pre, name, value, build } = args; + const { prerelease, build } = args; const version = await readVersionFile(); const { previous, current } = increment({ - kind: IncrementKind.Patch, version, - pre: pre ? name : undefined, - value, + kind: IncrementKind.Patch, + prerelease, build, }); await writeVersionFile(current); diff --git a/src/commands/options.ts b/src/commands/options.ts index 64aff54..5785b97 100644 --- a/src/commands/options.ts +++ b/src/commands/options.ts @@ -13,31 +13,18 @@ export const output = { default: undefined, }; -export const build = { - alias: "b", - type: "string", - description: "Build metadata", - example: "1234.abc", - default: undefined, -}; - export const prerelease = { alias: "p", - type: "flag", + type: "string", description: "Include prerelease", + example: "pr.1", + default: undefined, }; -export const prereleaseName = { - alias: "n", +export const build = { + alias: "b", type: "string", - description: "Prerelease name", - example: "alpha", - default: "pre", -}; - -export const prereleaseValue = { - alias: "v", - type: "number", - description: "Prerelease number value", + description: "Build metadata", + example: "1234.abc", default: undefined, }; diff --git a/src/commands/parse.ts b/src/commands/parse.ts index 07c0471..da0fd90 100644 --- a/src/commands/parse.ts +++ b/src/commands/parse.ts @@ -1,5 +1,6 @@ -import { Arguments, YargsInstance } from "../../deps/yargs.ts"; -import { parse as parseVersion } from "../../deps/semver.ts"; +import type { Arguments } from "yargs"; +import type { YargsInstance } from "yargs"; +import * as semver from "semver"; import { InvalidVersionError } from "../errors/mod.ts"; import { printVersion, readVersionFile } from "../util/version.ts"; import { IContext } from "../context.ts"; @@ -7,7 +8,7 @@ import { output } from "./options.ts"; export const parse = { command: "parse [value]", - describe: "Parse the version and print as JSON", + describe: "Parse the version (or version file if not provided) and print", builder(yargs: YargsInstance) { return yargs .positional("value", { @@ -17,11 +18,10 @@ export const parse = { }, async handler(args: Arguments & IContext) { const { value } = args; - const current = value ?? await readVersionFile(); - const semver = parseVersion(current); - if (!semver) { - throw new InvalidVersionError(current); + const result = value ? semver.parse(value) : await readVersionFile(); + if (!result) { + throw new InvalidVersionError(`${result}`); } - await printVersion(args, semver, true); + await printVersion(args, result, true); }, }; diff --git a/src/commands/set.test.ts b/src/commands/set.test.ts index 4ce8166..3a55b0f 100644 --- a/src/commands/set.test.ts +++ b/src/commands/set.test.ts @@ -1,18 +1,17 @@ +import { describe, it } from "testing/bdd"; import { - assertRejects, assertSpyCall, assertSpyCalls, - describe, - it, resolvesNext, returnsNext, stub, -} from "../../deps/std.ts"; -import { Arguments } from "../../deps/yargs.ts"; +} from "testing/mock"; +import { assertRejects } from "assert"; +import type { Arguments } from "yargs"; import { set } from "./set.ts"; import { testContext } from "../util/testContext.ts"; import { IContext } from "../context.ts"; -import { parse } from "../../deps/semver.ts"; +import { parse } from "semver"; describe("set", () => { const hooks = { @@ -38,7 +37,7 @@ describe("set", () => { await set.handler( { _: [], - current: "1.2.3", + value: "1.2.3", hooks, } as unknown as Arguments & IContext, ); @@ -80,7 +79,7 @@ describe("set", () => { await set.handler( { _: [], - current: "1.2.3", + value: "1.2.3", hooks, } as unknown as Arguments & IContext, ); @@ -144,7 +143,7 @@ describe("set", () => { await set.handler( { _: [], - current: "1.2.3", + value: "1.2.3", hooks, config: "version.yml", } as unknown as Arguments & IContext, @@ -211,7 +210,7 @@ describe("set", () => { await set.handler( { _: [], - current: "1.2.3", + value: "1.2.3", hooks, config: "version.yml", } as unknown as Arguments & IContext, diff --git a/src/commands/set.ts b/src/commands/set.ts index 007f1a6..d4feaa8 100644 --- a/src/commands/set.ts +++ b/src/commands/set.ts @@ -1,44 +1,35 @@ -import { Arguments, YargsInstance } from "../../deps/yargs.ts"; -import { parse } from "../../deps/semver.ts"; -import { increment, IncrementKind } from "../util/increment.ts"; +import type { Arguments, YargsInstance } from "yargs"; +import { parse } from "semver"; import { printVersion, readVersionFile, writeVersionFile, } from "../util/version.ts"; import { postVersionHook } from "../hooks/mod.ts"; -import { InvalidVersionError } from "../errors/invalidVersion.error.ts"; import { IContext } from "../context.ts"; import { config, output } from "./options.ts"; export const set = { - command: "set ", + command: "set ", describe: "Set the version", builder(yargs: YargsInstance) { return yargs - .positional("current", { + .positional("value", { describe: "The version to set to", }) .option("config", config) .option("output", output); }, async handler(args: Arguments & IContext) { + const { value } = args; const previous = await readVersionFile(); - const value = args.current || previous || "0.1.0"; - const version = parse(value); - if (!version) { - throw new InvalidVersionError(value); - } - const { current } = increment({ - kind: IncrementKind.None, - version: version, - }); - await writeVersionFile(current); + const version = value ? parse(value) : previous ? previous : parse("0.1.0"); + await writeVersionFile(version); await postVersionHook( args, previous, - current, + version, ); - await printVersion(args, current); + await printVersion(args, version); }, }; diff --git a/src/context.ts b/src/context.ts index ba782c0..4d7c142 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,4 +1,4 @@ -import { SemVer } from "../deps/semver.ts"; +import { SemVer } from "semver"; import { patch, regexp, replace } from "./hooks/mod.ts"; import { FormatKind } from "./util/variant.ts"; diff --git a/src/hooks/patch.ts b/src/hooks/patch.ts index 629b458..92e5669 100644 --- a/src/hooks/patch.ts +++ b/src/hooks/patch.ts @@ -1,16 +1,15 @@ -import { path } from "../../deps/std.ts"; -import { Node, xml } from "../../deps/xml.ts"; -import { JSONC } from "../../deps/jsonc.ts"; +import * as path from "path"; +import { applyEdits, modify } from "jsonc-parser"; import { UnsupportedFileKindError } from "../errors/mod.ts"; import { semverFormats } from "../util/variant.ts"; import { exists } from "../util/exists.ts"; -import { SemVer } from "../../deps/semver.ts"; +import { format, SemVer } from "semver"; export async function patch( file: string, version: SemVer, ) { - console.log(`patching ${version} in ${file}`); + console.log(`patching ${format(version)} in ${file}`); const ext = path.extname(file); const fileName = path.basename(file); if (ext === ".csproj" || ext === ".targets") { @@ -30,96 +29,25 @@ export async function patch( async function patchCsproj(file: string, version: SemVer) { const { dotnet } = semverFormats(version); const contents = await Deno.readTextFile(file); - const document = xml.parse(contents, { - captureSpacesBetweenElements: true, - }) as Node; - const project = document.elements[0]; - if (project.type !== "element" || project.name !== "Project") { - throw new UnsupportedFileKindError(file, { - cause: new Error("The csproj file must contain a root Project element"), - }); - } - - let isVersionSet = false; - for (const el of project.elements) { - if (isVersionSet) { - break; - } else if (el.type === "element" && el.name === "PropertyGroup") { - for (const property of el.elements) { - if (property.type === "element" && property.name === "Version") { - const value = property.elements[0]; - if (value.type === "text") { - value.text = dotnet; - isVersionSet = true; - break; - } - } - } - } - } - - if (!isVersionSet) { - throw new UnsupportedFileKindError(file, { - cause: new Error( - "The csproj file must contain a '0.0.0' element", - ), - }); - } - - const updated = xml.stringify(document, { - compact: false, - }); + const r = + /(?<=(.|\n)*(.|\n)*).*(?=<\/Version>)/; + const updated = contents.replace(r, dotnet); await Deno.writeTextFile(file, updated); } async function patchPomXml(file: string, version: SemVer) { const { original } = semverFormats(version); const contents = await Deno.readTextFile(file); - const document = xml.parse(contents, { - captureSpacesBetweenElements: true, - }) as Node; - const project = document.elements[0]; - if (project.type !== "element" || project.name !== "project") { - throw new UnsupportedFileKindError(file, { - cause: new Error( - "The pom.xml file must contain a root element", - ), - }); - } - - let isVersionSet = false; - for (const el of project.elements) { - if (isVersionSet) { - break; - } else if (el.type === "element" && el.name === "version") { - const value = el.elements[0]; - if (value.type === "text") { - value.text = original; - isVersionSet = true; - break; - } - } - } - - if (!isVersionSet) { - throw new UnsupportedFileKindError(file, { - cause: new Error( - "The pom.xml file must contain a '0.0.0' element", - ), - }); - } - - const updated = xml.stringify(document, { - compact: false, - }); + const r = /(?<=(.|\n)*).*(?=<\/version>)/; + const updated = contents.replace(r, original); await Deno.writeTextFile(file, updated); } async function patchPackageJson(file: string, version: SemVer) { const { original } = semverFormats(version); const contents = await Deno.readTextFile(file); - const edits = JSONC.modify(contents, ["version"], original, {}); - const result = JSONC.applyEdits(contents, edits); + const edits = modify(contents, ["version"], original, {}); + const result = applyEdits(contents, edits); await Deno.writeTextFile(file, result); } @@ -129,15 +57,15 @@ async function patchPackageLockJson(packageJsonPath: string, version: SemVer) { const packageLockJsonPath = path.resolve(dir, "package-lock.json"); if (await exists(packageLockJsonPath)) { const contents = await Deno.readTextFile(packageLockJsonPath); - const versionEdits = JSONC.modify(contents, ["version"], original, {}); - const moduleVersionEdits = JSONC.modify( + const versionEdits = modify(contents, ["version"], original, {}); + const moduleVersionEdits = modify( contents, ["packages", "", "version"], original, {}, ); const edits = [...versionEdits, ...moduleVersionEdits]; - const result = JSONC.applyEdits(contents, edits); + const result = applyEdits(contents, edits); await Deno.writeTextFile(packageLockJsonPath, result); } } diff --git a/src/hooks/post.test.ts b/src/hooks/post.test.ts index a87b461..5db3a99 100644 --- a/src/hooks/post.test.ts +++ b/src/hooks/post.test.ts @@ -1,6 +1,7 @@ -import { parse } from "../../deps/semver.ts"; -import { assertEquals, resolvesNext, stub } from "../../deps/std.ts"; -import { YAML } from "../../deps/yaml.ts"; +import { parse } from "semver"; +import { assertEquals } from "assert"; +import { resolvesNext, stub } from "testing/mock"; +import * as YAML from "yaml"; import { IContext } from "../context.ts"; import { postVersionHook } from "./post.ts"; @@ -66,7 +67,7 @@ Deno.test("custom config", async () => { stub( Deno, "readTextFile", - async (path, _opts) => { + async (path: string | URL, _opts?: Deno.ReadFileOptions) => { configPath = path; return await YAML.stringify({ on: { post: [] }, diff --git a/src/hooks/post.ts b/src/hooks/post.ts index 2fa4cb7..dc00214 100644 --- a/src/hooks/post.ts +++ b/src/hooks/post.ts @@ -1,9 +1,9 @@ -import { YAML } from "../../deps/yaml.ts"; +import * as YAML from "yaml"; import { HookError } from "../errors/mod.ts"; import { exists } from "../util/exists.ts"; import { PostHookKind, VersionConfig } from "./hooks.interfaces.ts"; import { IContext } from "../context.ts"; -import { SemVer } from "../../deps/semver.ts"; +import { SemVer } from "semver"; // Post hooks are a set of per-repo configurable actions that can be taken // after the version is updated. diff --git a/src/hooks/regexp.ts b/src/hooks/regexp.ts index fd11a16..29f2c0e 100644 --- a/src/hooks/regexp.ts +++ b/src/hooks/regexp.ts @@ -1,4 +1,4 @@ -import { SemVer } from "../../deps/semver.ts"; +import { SemVer } from "semver"; import { FormatKind, semverFormatByKey } from "../util/variant.ts"; export async function regexp( diff --git a/src/hooks/replace.ts b/src/hooks/replace.ts index 5c579b7..fb8819c 100644 --- a/src/hooks/replace.ts +++ b/src/hooks/replace.ts @@ -1,4 +1,4 @@ -import { format, SemVer } from "../../deps/semver.ts"; +import { format, SemVer } from "semver"; export async function replace( file: string, diff --git a/src/util/increment.test.ts b/src/util/increment.test.ts index ae3f481..b47c52a 100644 --- a/src/util/increment.test.ts +++ b/src/util/increment.test.ts @@ -1,114 +1,114 @@ -import { assertEquals } from "../../deps/std.ts"; -import { format } from "../../deps/semver.ts"; +import { assertEquals } from "assert"; +import { format, parse } from "semver"; import { increment, IncrementKind, IncrementOptions } from "./increment.ts"; const testCases: (IncrementOptions & { expected: string })[] = [ { kind: IncrementKind.Major, - version: "1.0.0", - pre: undefined, + version: parse("1.0.0"), + prerelease: undefined, expected: "2.0.0", }, { kind: IncrementKind.Minor, - version: "1.0.0", - pre: undefined, + version: parse("1.0.0"), + prerelease: undefined, expected: "1.1.0", }, { kind: IncrementKind.Patch, - version: "1.0.0", - pre: undefined, + version: parse("1.0.0"), + prerelease: undefined, expected: "1.0.1", }, { kind: IncrementKind.None, - version: "1.0.0", - pre: undefined, + version: parse("1.0.0"), + prerelease: undefined, expected: "1.0.0", }, { kind: IncrementKind.Major, - version: "1.0.0", - pre: "pre", + version: parse("1.0.0"), + prerelease: "pre", expected: "2.0.0-pre.0", }, { kind: IncrementKind.Minor, - version: "1.0.0", - pre: "pre", + version: parse("1.0.0"), + prerelease: "pre", expected: "1.1.0-pre.0", }, { kind: IncrementKind.Patch, - version: "1.0.0", - pre: "pre", + version: parse("1.0.0"), + prerelease: "pre", expected: "1.0.1-pre.0", }, { kind: IncrementKind.None, - version: "1.0.0", - pre: "pre", + version: parse("1.0.0"), + prerelease: "pre", expected: "1.0.0-pre.0", }, { kind: IncrementKind.Major, - version: "1.0.0-pre.0", - pre: "pre", + version: parse("1.0.0-pre.0"), + prerelease: "pre", expected: "2.0.0-pre.1", }, { kind: IncrementKind.Minor, - version: "1.0.0-pre.0", - pre: "pre", + version: parse("1.0.0-pre.0"), + prerelease: "pre", expected: "1.1.0-pre.1", }, { kind: IncrementKind.Patch, - version: "1.0.0-pre.0", - pre: "pre", + version: parse("1.0.0-pre.0"), + prerelease: "pre", expected: "1.0.1-pre.1", }, { kind: IncrementKind.None, - version: "1.0.0-pre.0", - pre: "pre", + version: parse("1.0.0-pre.0"), + prerelease: "pre", expected: "1.0.0-pre.1", }, { kind: IncrementKind.Major, - version: "1.0.0-pre.0", - pre: "rc", + version: parse("1.0.0-pre.0"), + prerelease: "rc", expected: "2.0.0-rc.0", }, { kind: IncrementKind.Minor, - version: "1.0.0-pre.0", - pre: "rc", + version: parse("1.0.0-pre.0"), + prerelease: "rc", expected: "1.1.0-rc.0", }, { kind: IncrementKind.Patch, - version: "1.0.0-pre.0", - pre: "rc", + version: parse("1.0.0-pre.0"), + prerelease: "rc", expected: "1.0.1-rc.0", }, { kind: IncrementKind.None, - version: "1.0.0-pre.0", - pre: "rc", + version: parse("1.0.0-pre.0"), + prerelease: "rc", expected: "1.0.0-rc.0", }, ]; testCases.forEach((testCases, i) => { - const { kind, version, pre, expected } = testCases; + const { kind, version, prerelease, expected } = testCases; Deno.test({ - name: `INC${ - i.toLocaleString(undefined, { minimumIntegerDigits: 2 }) - } - ${version}:${kind}:${pre} -> ${expected}`, + name: `INC${i.toLocaleString(undefined, { minimumIntegerDigits: 2 })} - ${ + format(version) + }:${kind}:${prerelease} -> ${expected}`, fn: () => { - const result = increment({ kind, version, pre }); + const result = increment({ kind, version, prerelease }); assertEquals(format(result.current), expected); }, }); diff --git a/src/util/increment.ts b/src/util/increment.ts index 27f0fd2..91c3b7e 100644 --- a/src/util/increment.ts +++ b/src/util/increment.ts @@ -1,5 +1,4 @@ -import { increment as inc, parse, SemVer } from "../../deps/semver.ts"; -import { InvalidVersionError } from "../errors/mod.ts"; +import { increment as inc, SemVer } from "semver"; export enum IncrementKind { Major = "major", @@ -8,74 +7,41 @@ export enum IncrementKind { None = "none", } -export type IncrementOptions = { - version: string | SemVer; +export interface IncrementOptions { + version: SemVer; kind: IncrementKind; - pre?: string; - value?: string; + prerelease?: string; build?: string; -}; +} export function increment(options: IncrementOptions) { - const { kind, version, pre, value, build } = options; - const semver = parse(version); - if (!semver) { - throw new InvalidVersionError(version.toString()); - } + const { kind, version, prerelease, build } = options; return { - previous: semver, + previous: version, current: (() => { switch (kind) { case IncrementKind.Major: - return pre && value - ? { - ...inc(semver, "major", undefined, build), - prerelease: [...pre.split("."), parseInt(value)], - } - : pre - ? inc(semver, "premajor", pre, build) - : inc(semver, "major", undefined, build); + return prerelease + ? inc(version, "premajor", { prerelease, build }) + : inc(version, "major", { build }); case IncrementKind.Minor: - return pre && value !== undefined - ? { - ...inc(semver, "minor", undefined, build), - prerelease: [...pre.split("."), parseInt(value)], - } - : pre - ? inc(semver, "preminor", pre, build) - : inc(semver, "minor", undefined, build); + return prerelease + ? inc(version, "preminor", { prerelease, build }) + : inc(version, "minor", { build }); case IncrementKind.Patch: - return pre && value - ? { - ...inc(semver, "patch", undefined, build), - prerelease: [...pre.split("."), parseInt(value)], - } - : pre - ? inc(semver, "prepatch", pre, build) - : inc(semver, "patch", undefined, build); - case IncrementKind.None: { - if (pre && value && build != undefined) { - return { - ...semver, - prerelease: [...pre.split("."), parseInt(value)], - build: build.split(".").map((b) => b.trim()), - }; - } else if (pre && value) { - return { - ...semver, - prerelease: [...pre.split("."), parseInt(value)], - }; - } else if (pre) { - return inc(semver, "pre", pre, build); - } else if (build !== undefined) { - return { - ...semver, - build: build.split(".").map((b) => b.trim()), - }; - } else { - return semver; - } - } + return prerelease + ? inc(version, "prepatch", { prerelease, build }) + : inc(version, "patch", { build }); + case IncrementKind.None: + return prerelease ? inc(version, "pre", { prerelease, build }) : { + ...version, + prerelease: prerelease + ? prerelease.split(".") + : version.prerelease ?? [], + build: build ? build.split(".") : version.build ?? [], + }; + default: + throw new Error(`Unknown increment kind: ${kind}`); } })(), }; diff --git a/src/util/testContext.ts b/src/util/testContext.ts index bafce52..fd301e2 100644 --- a/src/util/testContext.ts +++ b/src/util/testContext.ts @@ -1,4 +1,5 @@ -import { afterEach, beforeEach, Spy } from "../../deps/std.ts"; +import { afterEach, beforeEach } from "testing/bdd"; +import type { Spy } from "testing/mock"; export function testContext< // deno-lint-ignore no-explicit-any diff --git a/src/util/variant.ts b/src/util/variant.ts index 473be22..fdd01c2 100644 --- a/src/util/variant.ts +++ b/src/util/variant.ts @@ -1,4 +1,4 @@ -import { format, SemVer } from "../../deps/semver.ts"; +import { format, SemVer } from "semver"; export enum FormatKind { Original = "original", diff --git a/src/util/version.test.ts b/src/util/version.test.ts index 544c8cd..0392508 100644 --- a/src/util/version.test.ts +++ b/src/util/version.test.ts @@ -1,12 +1,6 @@ -import { format, parse } from "../../deps/semver.ts"; -import { - assertEquals, - AssertionError, - assertRejects, - assertSpyCall, - resolvesNext, - stub, -} from "../../deps/std.ts"; +import { format, parse } from "semver"; +import { assertEquals, AssertionError, assertRejects } from "assert"; +import { assertSpyCall, resolvesNext, stub } from "testing/mock"; import { IContext } from "../context.ts"; import { printVersion, readVersionFile, writeVersionFile } from "./version.ts"; diff --git a/src/util/version.ts b/src/util/version.ts index b298779..cbf9109 100644 --- a/src/util/version.ts +++ b/src/util/version.ts @@ -1,5 +1,5 @@ -import { path } from "../../deps/std.ts"; -import { format, parse, SemVer } from "../../deps/semver.ts"; +import * as path from "path"; +import { format, parse, SemVer } from "semver"; import { IContext } from "../context.ts"; import { semverFormats } from "./variant.ts"; @@ -27,7 +27,7 @@ export async function printVersion( full = false, ) { const formatted = format(semver); - const { major, minor, patch, prerelease, build } = semver; + const { major, minor, patch, prerelease = [], build = [] } = semver; const pre = prerelease.join("."); const b = build.join("."); const { dotnet, docker } = semverFormats(semver); @@ -69,11 +69,11 @@ export async function printVersion( * version then the default version `0.0.0` is returned. * @returns The parsed version or default version */ -export async function readVersionFile() { +export async function readVersionFile(): Promise { try { const versionText = await Deno.readTextFile("VERSION"); const trimmed = versionText.trim(); - return parse(trimmed || DEFAULT_VERSION) || DEFAULT_VERSION; + return trimmed ? parse(trimmed) : DEFAULT_VERSION; } catch (err) { if (err instanceof Deno.errors.NotFound) { return DEFAULT_VERSION; diff --git a/test/dotnet/VERSION b/test/dotnet/VERSION index 63242e5..cf7fbdf 100644 --- a/test/dotnet/VERSION +++ b/test/dotnet/VERSION @@ -1 +1 @@ -0.4.0-lambda.2+ghi.789 +0.10.0-lambda.8+ghi.789 diff --git a/test/dotnet/example.csproj b/test/dotnet/example.csproj index b283d8e..35684e0 100644 --- a/test/dotnet/example.csproj +++ b/test/dotnet/example.csproj @@ -4,7 +4,7 @@ net7.0 enable example - 0.4.0-lambda.2-ghi.789 + 0.10.0-lambda.8-ghi.789 Justin Chase Optum ./nupkg diff --git a/test/dotnet/example.targets b/test/dotnet/example.targets index b3c1c5f..a20d30f 100644 --- a/test/dotnet/example.targets +++ b/test/dotnet/example.targets @@ -1,5 +1,5 @@ - 0.4.0-lambda.2-ghi.789 + 0.10.0-lambda.8-ghi.789 diff --git a/test/dotnet/src/lib.cs b/test/dotnet/src/lib.cs index 2804914..467144c 100644 --- a/test/dotnet/src/lib.cs +++ b/test/dotnet/src/lib.cs @@ -4,6 +4,6 @@ public class Hello { public string Version() { - return "0.4.0-lambda.2+ghi.789"; + return "0.10.0-lambda.8+ghi.789"; } } diff --git a/test/helm/Chart.yaml b/test/helm/Chart.yaml index 6697f69..03e057e 100644 --- a/test/helm/Chart.yaml +++ b/test/helm/Chart.yaml @@ -3,5 +3,5 @@ apiVersion: v2 type: application name: . description: A Helm chart for Kubernetes -version: 0.6.0-beta.3+abc.123 +version: 0.12.0-beta.9+abc.123 appVersion: 1.16.0 diff --git a/test/helm/VERSION b/test/helm/VERSION index 8e28d44..0947c7d 100644 --- a/test/helm/VERSION +++ b/test/helm/VERSION @@ -1 +1 @@ -0.6.0-beta.3+abc.123 +0.12.0-beta.9+abc.123 diff --git a/test/maven/VERSION b/test/maven/VERSION index 714b919..0802d88 100644 --- a/test/maven/VERSION +++ b/test/maven/VERSION @@ -1 +1 @@ -0.4.0-omega.2+def.456 +0.12.0-omega.10+def.456 diff --git a/test/maven/pom.xml b/test/maven/pom.xml index 6f0b65c..420727a 100644 --- a/test/maven/pom.xml +++ b/test/maven/pom.xml @@ -2,5 +2,5 @@ 4.0.0 com.optum.example example - 0.4.0-omega.2+def.456 + 0.12.0-omega.10+def.456 diff --git a/test/node/VERSION b/test/node/VERSION index 6e27363..fbb1aa3 100644 --- a/test/node/VERSION +++ b/test/node/VERSION @@ -1 +1 @@ -1.23.0-alpha.3+xyz.987 +1.29.0-alpha.9+xyz.987 diff --git a/test/node/package-lock.json b/test/node/package-lock.json index d2f1de3..19f58c4 100644 --- a/test/node/package-lock.json +++ b/test/node/package-lock.json @@ -1,12 +1,12 @@ { "name": "test", - "version": "1.23.0-alpha.3+xyz.987", + "version": "1.29.0-alpha.9+xyz.987", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "test", - "version": "1.23.0-alpha.3+xyz.987" + "version": "1.29.0-alpha.9+xyz.987" } } } diff --git a/test/node/package.json b/test/node/package.json index 5a82792..4707f76 100644 --- a/test/node/package.json +++ b/test/node/package.json @@ -1,4 +1,4 @@ { "name": "test", - "version": "1.23.0-alpha.3+xyz.987" + "version": "1.29.0-alpha.9+xyz.987" }