From 18ab421dc0626bca1d81820118ee45f1875a840f Mon Sep 17 00:00:00 2001 From: b6k <39600846+b6k-dev@users.noreply.github.com> Date: Sat, 14 Mar 2026 11:24:02 +0100 Subject: [PATCH 1/8] - fix package coordinates - enhance pom with repository metadata --- pom.xml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 08ca6d3..580db38 100644 --- a/pom.xml +++ b/pom.xml @@ -4,9 +4,18 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - dev.b6k + io.github.b6k-dev outcome - 1.0-SNAPSHOT + 1.0.0-SNAPSHOT + Outcome + Functional Result type for Java + https://github.com/b6k-dev/outcome + + + scm:git:git://github.com/b6k-dev/outcome.git + scm:git:ssh://git@github.com/b6k-dev/outcome.git + https://github.com/b6k-dev/outcome + 25 From 2b01665fe7ebdaee887329ecd463a1e75f93eaa7 Mon Sep 17 00:00:00 2001 From: b6k <39600846+b6k-dev@users.noreply.github.com> Date: Sat, 14 Mar 2026 11:28:21 +0100 Subject: [PATCH 2/8] add license and maven metadata --- LICENSE | 21 +++++++++++++++++++++ pom.xml | 21 +++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fe27a60 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Maciej Bartczak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/pom.xml b/pom.xml index 580db38..7086353 100644 --- a/pom.xml +++ b/pom.xml @@ -8,13 +8,30 @@ outcome 1.0.0-SNAPSHOT Outcome - Functional Result type for Java + Lightweight Result type for Java with Ok, Err, and Panic https://github.com/b6k-dev/outcome + + + MIT License + https://opensource.org/licenses/MIT + repo + + + + + + b6k-dev + Maciej Bartczak + https://github.com/b6k-dev + + + - scm:git:git://github.com/b6k-dev/outcome.git + scm:git:https://github.com/b6k-dev/outcome.git scm:git:ssh://git@github.com/b6k-dev/outcome.git https://github.com/b6k-dev/outcome + HEAD From 9bc5c995c351581ad0363f778c8df3ac1577af83 Mon Sep 17 00:00:00 2001 From: b6k <39600846+b6k-dev@users.noreply.github.com> Date: Sat, 14 Mar 2026 11:32:56 +0100 Subject: [PATCH 3/8] pin java version to 17+ --- pom.xml | 37 ++++++++++++++++++- src/test/java/b6k/dev/outcome/ResultTest.java | 32 ++++++++-------- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index 7086353..6c810fc 100644 --- a/pom.xml +++ b/pom.xml @@ -35,10 +35,12 @@ - 25 - 25 + 17 + 3.9.0 5.12.0 3.27.7 + 3.14.1 + 3.5.0 3.5.2 UTF-8 @@ -60,6 +62,37 @@ + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.release} + + + + org.apache.maven.plugins + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + enforce-build-environment + + enforce + + + + + [17,) + + + [${maven.version},) + + + + + + org.apache.maven.plugins maven-surefire-plugin diff --git a/src/test/java/b6k/dev/outcome/ResultTest.java b/src/test/java/b6k/dev/outcome/ResultTest.java index c24377e..7387337 100644 --- a/src/test/java/b6k/dev/outcome/ResultTest.java +++ b/src/test/java/b6k/dev/outcome/ResultTest.java @@ -346,7 +346,7 @@ void panicsWhenSupplierThrows() { @Test void panicsWhenErrorMapperThrows() { - assertThatThrownBy(() -> errResult().unwrapOrElse(_ -> { + assertThatThrownBy(() -> errResult().unwrapOrElse(error -> { throw new IllegalStateException("boom"); })) .isInstanceOf(Panic.class) @@ -363,7 +363,7 @@ class OrElse { void preservesValueForOk() { var called = new AtomicBoolean(false); - var result = okResult().orElse(_ -> { + var result = okResult().orElse(error -> { called.set(true); return Result.ok(23); }); @@ -389,7 +389,7 @@ void recoversErrToOk() { @Test void transformsErrToDifferentErrorType() { - Result result = errResult().orElse(_ -> Result.err(new IllegalStateException("new error"))); + Result result = errResult().orElse(error -> Result.err(new IllegalStateException("new error"))); assertThat(result.unwrapError()) .isInstanceOf(IllegalStateException.class) @@ -419,7 +419,7 @@ void rejectsNullFallback() { @Test void rejectsNullFallbackResult() { - assertThatThrownBy(() -> errResult().orElse(_ -> null)) + assertThatThrownBy(() -> errResult().orElse(error -> null)) .isInstanceOf(NullPointerException.class) .hasMessage("fallback result must not be null"); } @@ -470,7 +470,7 @@ void rejectsNullMapper() { @Test void panicsWhenMapperThrows() { - assertThatThrownBy(() -> errResult().orThrow(_ -> { + assertThatThrownBy(() -> errResult().orThrow(error -> { throw new IllegalStateException("boom"); })) .isInstanceOf(Panic.class) @@ -482,7 +482,7 @@ void panicsWhenMapperThrows() { @Test void rejectsNullMappedThrowable() { - assertThatThrownBy(() -> errResult().orThrow(_ -> null)) + assertThatThrownBy(() -> errResult().orThrow(error -> null)) .isInstanceOf(NullPointerException.class) .hasMessage("errorMapper result must not be null"); } @@ -526,7 +526,7 @@ void rejectsNullMapper() { @Test void rejectsNullMappedValue() { - assertThatThrownBy(() -> okResult().map(_ -> null)) + assertThatThrownBy(() -> okResult().map(value -> null)) .isInstanceOf(NullPointerException.class) .hasMessage("value must not be null"); } @@ -570,7 +570,7 @@ void rejectsNullMapper() { @Test void rejectsNullMappedError() { - assertThatThrownBy(() -> errResult().mapError(_ -> null)) + assertThatThrownBy(() -> errResult().mapError(error -> null)) .isInstanceOf(NullPointerException.class) .hasMessage("error must not be null"); } @@ -595,7 +595,7 @@ void preservesErrorForErr() { @Test void propagatesErrorFromMapper() { - var result = okResult().flatMap(_ -> Result.err("mapper failed")); + var result = okResult().flatMap(value -> Result.err("mapper failed")); assertTrue(result.isErr()); assertEquals("mapper failed", result.unwrapError()); @@ -633,7 +633,7 @@ void rejectsNullMapper() { @Test void rejectsNullMappedResult() { - assertThatThrownBy(() -> okResult().flatMap(_ -> null)) + assertThatThrownBy(() -> okResult().flatMap(value -> null)) .isInstanceOf(NullPointerException.class) .hasMessage("mapper result must not be null"); } @@ -658,7 +658,7 @@ void observesValueForOk() { void preservesErrorForErrWithoutCallingObserver() { var called = new AtomicBoolean(false); - var result = errResult().peek(_ -> called.set(true)); + var result = errResult().peek(value -> called.set(true)); assertEquals(errResult(), result); assertFalse(called.get()); @@ -676,7 +676,7 @@ void rejectsNullObserver() { @Test void panicsWhenObserverThrows() { - assertThatThrownBy(() -> okResult().peek(_ -> { + assertThatThrownBy(() -> okResult().peek(value -> { throw new IllegalStateException("boom"); })) .isInstanceOf(Panic.class) @@ -706,7 +706,7 @@ void observesErrorForErr() { void preservesValueForOkWithoutCallingObserver() { var called = new AtomicBoolean(false); - var result = okResult().peekErr(_ -> called.set(true)); + var result = okResult().peekErr(error -> called.set(true)); assertEquals(okResult(), result); assertFalse(called.get()); @@ -724,7 +724,7 @@ void rejectsNullObserver() { @Test void panicsWhenObserverThrows() { - assertThatThrownBy(() -> errResult().peekErr(_ -> { + assertThatThrownBy(() -> errResult().peekErr(error -> { throw new IllegalStateException("boom"); })) .isInstanceOf(Panic.class) @@ -841,7 +841,7 @@ void rejectsNullMappers() { @Test void panicsWhenOkMapperThrows() { - assertThatThrownBy(() -> okResult().fold(_ -> { + assertThatThrownBy(() -> okResult().fold(value -> { throw new IllegalStateException("boom"); }, String::length)) .isInstanceOf(Panic.class) @@ -853,7 +853,7 @@ void panicsWhenOkMapperThrows() { @Test void panicsWhenErrorMapperThrows() { - assertThatThrownBy(() -> errResult().fold(value -> value * 2, _ -> { + assertThatThrownBy(() -> errResult().fold(value -> value * 2, error -> { throw new IllegalStateException("boom"); })) .isInstanceOf(Panic.class) From 78883554a49a5166b60b3e63d0dd33755666e573 Mon Sep 17 00:00:00 2001 From: b6k <39600846+b6k-dev@users.noreply.github.com> Date: Sat, 14 Mar 2026 12:48:13 +0100 Subject: [PATCH 4/8] setup maven release plugins --- .mvn/settings.xml | 9 ++++++ pom.xml | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 .mvn/settings.xml diff --git a/.mvn/settings.xml b/.mvn/settings.xml new file mode 100644 index 0000000..60300f8 --- /dev/null +++ b/.mvn/settings.xml @@ -0,0 +1,9 @@ + + + + central + ${env.MAVEN_CENTRAL_USERNAME} + ${env.MAVEN_CENTRAL_PASSWORD} + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6c810fc..f70721c 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,11 @@ 3.27.7 3.14.1 3.5.0 + 3.3.1 + 3.11.2 + 3.2.8 3.5.2 + 0.9.0 UTF-8 @@ -101,4 +105,74 @@ + + + release + + + + org.apache.maven.plugins + maven-source-plugin + ${maven-source-plugin.version} + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + ${maven.compiler.release} + ${project.build.sourceEncoding} + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + ${maven-gpg-plugin.version} + + + sign-artifacts + verify + + sign + + + + + bc + + + + org.sonatype.central + central-publishing-maven-plugin + ${central-publishing-maven-plugin.version} + true + + central + ${project.artifactId}-${project.version} + false + false + validated + + + + + + + From 12bc34c094aca1d41fe8b19f296db447655cf57e Mon Sep 17 00:00:00 2001 From: b6k <39600846+b6k-dev@users.noreply.github.com> Date: Sat, 14 Mar 2026 12:56:38 +0100 Subject: [PATCH 5/8] release workflow --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 95 +++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2abc37..1b475c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: uses: actions/setup-java@v5 with: distribution: temurin - java-version: '25' + java-version: '17' cache: maven - name: Make Maven wrapper executable diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..040825e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,95 @@ +name: Release + +on: + workflow_dispatch: + inputs: + release_tag: + description: Release tag in MAJOR.MINOR.PATCH format + required: true + type: string + push: + tags: + - '*.*.*' + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: write + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + steps: + - name: Check out repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }} + + - name: Set up Java and Maven Central credentials + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: '17' + cache: maven + server-id: central + server-username: ${{ secrets.SONATYPE_USERNAME }} + server-password: ${{ secrets.SONATYPE_PASSWORD }} + gpg-private-key: ${{ secrets.GPG_KEY_CONTENTS }} + gpg-passphrase: ${{ secrets.SIGNING_PASSWORD }} + + - name: Make Maven wrapper executable + run: chmod +x ./mvnw + + - name: Derive release and next snapshot versions from tag + env: + GITHUB_EVENT_NAME: ${{ github.event_name }} + GITHUB_REF_NAME: ${{ github.ref_name }} + RELEASE_TAG_INPUT: ${{ inputs.release_tag }} + run: | + if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then + RELEASE_VERSION="${RELEASE_TAG_INPUT}" + else + RELEASE_VERSION="${GITHUB_REF_NAME}" + fi + + if ! [[ "${RELEASE_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Release tag '${RELEASE_VERSION}' is not in the expected MAJOR.MINOR.PATCH format." >&2 + exit 1 + fi + + IFS='.' read -r major minor patch <> "${GITHUB_ENV}" + echo "NEXT_SNAPSHOT_VERSION=${NEXT_SNAPSHOT_VERSION}" >> "${GITHUB_ENV}" + + - name: Set release version from tag + run: ./mvnw -B versions:set -DnewVersion="${RELEASE_VERSION}" -DgenerateBackupPoms=false + + - name: Build, sign, and publish release bundle + run: ./mvnw -B -Prelease deploy + + - name: Check out default branch for next snapshot bump + uses: actions/checkout@v6 + with: + ref: ${{ env.DEFAULT_BRANCH }} + path: default-branch + + - name: Bump default branch to next snapshot version + working-directory: /home/runner/work/outcome/outcome/default-branch + run: | + chmod +x ./mvnw + ./mvnw -B versions:set -DnewVersion="${NEXT_SNAPSHOT_VERSION}" -DgenerateBackupPoms=false + git config user.name "github-actions" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add pom.xml + if git diff --cached --quiet; then + echo "${DEFAULT_BRANCH} is already at ${NEXT_SNAPSHOT_VERSION}; nothing to commit." + exit 0 + fi + git commit -m "Bump version to ${NEXT_SNAPSHOT_VERSION}" + git push origin HEAD:"${DEFAULT_BRANCH}" From 86efa2befe94200bb94b6675b003cbed85b78599 Mon Sep 17 00:00:00 2001 From: b6k <39600846+b6k-dev@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:24:39 +0100 Subject: [PATCH 6/8] delete settings.xml --- .mvn/settings.xml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 .mvn/settings.xml diff --git a/.mvn/settings.xml b/.mvn/settings.xml deleted file mode 100644 index 60300f8..0000000 --- a/.mvn/settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - central - ${env.MAVEN_CENTRAL_USERNAME} - ${env.MAVEN_CENTRAL_PASSWORD} - - - \ No newline at end of file From 95e5662e2a69d453a5cf2a5761f736cf8bb1c8c3 Mon Sep 17 00:00:00 2001 From: b6k <39600846+b6k-dev@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:24:55 +0100 Subject: [PATCH 7/8] readme improvements --- README.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/README.md b/README.md index f6d7415..58260b3 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ Inspired by [better-result](https://github.com/dmmulroy/better-result). ## Contents +- [Installation](#installation) +- [Java Compatibility](#java-compatibility) +- [Quick Start](#quick-start) - [The Core Types](#the-core-types) - [Creating Results](#creating-results) - [Transforming Success Values](#transforming-success-values) @@ -17,6 +20,65 @@ Inspired by [better-result](https://github.com/dmmulroy/better-result). - [Panic](#panic) - [API Reference](#api-reference) +## Installation + +Maven: + +```xml + + io.github.b6k-dev + outcome + 1.0.0 + +``` + +Gradle (Groovy DSL): + +```groovy +implementation 'io.github.b6k-dev:outcome:1.0.0' +``` + +Gradle (Kotlin DSL): + +```kotlin +implementation("io.github.b6k-dev:outcome:1.0.0") +``` + +## Java Compatibility + +Outcome targets Java 17 and newer. The library API is compiled with `--release 17`, and examples in this README use sealed types, records, and pattern matching features available in modern Java. + +## Quick Start + +```java +import b6k.dev.outcome.Result; + +sealed interface CreateUserError permits InvalidEmail, DuplicateEmail {} +record InvalidEmail(String value) implements CreateUserError {} +record DuplicateEmail(String value) implements CreateUserError {} +record User(String id, String email) {} + +Result createUser(String email) { + if (email == null || email.isBlank() || !email.contains("@")) { + return Result.err(new InvalidEmail(String.valueOf(email))); + } + if (email.equals("ada@example.com")) { + return Result.err(new DuplicateEmail(email)); + } + return Result.ok(new User("u-123", email)); +} + +String message = createUser("ada@example.com").fold( + user -> "Created user " + user.email(), + error -> switch (error) { + case InvalidEmail e -> "Invalid email: " + e.value(); + case DuplicateEmail e -> "Email already exists: " + e.email(); + } +); +``` + +Use `Result.ok(...)` and `Result.err(...)` to model expected outcomes, then compose them with methods like `map`, `flatMap`, `orElse`, and `fold` instead of mixing nullable values, sentinel states, and exceptions. + ## The Core Types Outcome revolves around four ideas: From b82c6a8b49647e6e861f083d86cb019f42bea6da Mon Sep 17 00:00:00 2001 From: b6k <39600846+b6k-dev@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:40:23 +0100 Subject: [PATCH 8/8] finalize release workflow --- .github/workflows/release.yml | 97 ++++++++++++++++++++++------------- docs/releases/1.0.0.md | 23 +++++++++ 2 files changed, 84 insertions(+), 36 deletions(-) create mode 100644 docs/releases/1.0.0.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 040825e..fcdecfa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,13 +3,14 @@ name: Release on: workflow_dispatch: inputs: - release_tag: - description: Release tag in MAJOR.MINOR.PATCH format + release_version: + description: Release version in MAJOR.MINOR.PATCH format required: true type: string - push: - tags: - - '*.*.*' + +concurrency: + group: release-${{ github.event.repository.default_branch }} + cancel-in-progress: false jobs: publish: @@ -19,11 +20,11 @@ jobs: env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} steps: - - name: Check out repository + - name: Check out default branch uses: actions/checkout@v6 with: fetch-depth: 0 - ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }} + ref: ${{ github.event.repository.default_branch }} - name: Set up Java and Maven Central credentials uses: actions/setup-java@v5 @@ -40,20 +41,14 @@ jobs: - name: Make Maven wrapper executable run: chmod +x ./mvnw - - name: Derive release and next snapshot versions from tag + - name: Derive release metadata env: - GITHUB_EVENT_NAME: ${{ github.event_name }} - GITHUB_REF_NAME: ${{ github.ref_name }} - RELEASE_TAG_INPUT: ${{ inputs.release_tag }} + RELEASE_VERSION_INPUT: ${{ inputs.release_version }} run: | - if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then - RELEASE_VERSION="${RELEASE_TAG_INPUT}" - else - RELEASE_VERSION="${GITHUB_REF_NAME}" - fi + RELEASE_VERSION="${RELEASE_VERSION_INPUT}" if ! [[ "${RELEASE_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Release tag '${RELEASE_VERSION}' is not in the expected MAJOR.MINOR.PATCH format." >&2 + echo "Release version '${RELEASE_VERSION}' is not in the expected MAJOR.MINOR.PATCH format." >&2 exit 1 fi @@ -63,33 +58,63 @@ jobs: NEXT_PATCH=$((patch + 1)) NEXT_SNAPSHOT_VERSION="${major}.${minor}.${NEXT_PATCH}-SNAPSHOT" + RELEASE_NOTES_FILE="docs/releases/${RELEASE_VERSION}.md" echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "${GITHUB_ENV}" echo "NEXT_SNAPSHOT_VERSION=${NEXT_SNAPSHOT_VERSION}" >> "${GITHUB_ENV}" + echo "RELEASE_NOTES_FILE=${RELEASE_NOTES_FILE}" >> "${GITHUB_ENV}" - - name: Set release version from tag - run: ./mvnw -B versions:set -DnewVersion="${RELEASE_VERSION}" -DgenerateBackupPoms=false + - name: Verify release tag does not already exist + run: | + if git rev-parse -q --verify "refs/tags/${RELEASE_VERSION}" >/dev/null; then + echo "Tag ${RELEASE_VERSION} already exists locally." >&2 + exit 1 + fi + if git ls-remote --exit-code --tags origin "refs/tags/${RELEASE_VERSION}" >/dev/null; then + echo "Tag ${RELEASE_VERSION} already exists on origin." >&2 + exit 1 + fi - - name: Build, sign, and publish release bundle - run: ./mvnw -B -Prelease deploy + - name: Configure git author + run: | + git config user.name "github-actions" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - name: Check out default branch for next snapshot bump - uses: actions/checkout@v6 - with: - ref: ${{ env.DEFAULT_BRANCH }} - path: default-branch + - name: Create release commit and tag + run: | + ./mvnw -B versions:set -DnewVersion="${RELEASE_VERSION}" -DgenerateBackupPoms=false + git add pom.xml + git commit -m "Release ${RELEASE_VERSION}" + git tag -a "${RELEASE_VERSION}" -m "Release ${RELEASE_VERSION}" - - name: Bump default branch to next snapshot version - working-directory: /home/runner/work/outcome/outcome/default-branch + - name: Create next snapshot commit run: | - chmod +x ./mvnw ./mvnw -B versions:set -DnewVersion="${NEXT_SNAPSHOT_VERSION}" -DgenerateBackupPoms=false - git config user.name "github-actions" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add pom.xml - if git diff --cached --quiet; then - echo "${DEFAULT_BRANCH} is already at ${NEXT_SNAPSHOT_VERSION}; nothing to commit." - exit 0 - fi git commit -m "Bump version to ${NEXT_SNAPSHOT_VERSION}" - git push origin HEAD:"${DEFAULT_BRANCH}" + + - name: Push release tag and default branch + run: | + git push --atomic origin HEAD:"${DEFAULT_BRANCH}" "refs/tags/${RELEASE_VERSION}" + + - name: Check out release tag for publishing + run: git checkout --detach "${RELEASE_VERSION}" + + - name: Build, sign, and publish release bundle + run: ./mvnw -B -Prelease deploy + + - name: Create draft GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + if [ -f "${RELEASE_NOTES_FILE}" ]; then + gh release create "${RELEASE_VERSION}" \ + --draft \ + --title "${RELEASE_VERSION}" \ + --notes-file "${RELEASE_NOTES_FILE}" + else + gh release create "${RELEASE_VERSION}" \ + --draft \ + --title "${RELEASE_VERSION}" \ + --generate-notes + fi diff --git a/docs/releases/1.0.0.md b/docs/releases/1.0.0.md new file mode 100644 index 0000000..25864eb --- /dev/null +++ b/docs/releases/1.0.0.md @@ -0,0 +1,23 @@ +# Outcome 1.0.0 Release Notes + +## Highlights + +- First public release of Outcome, a lightweight `Result` type for Java + +## Coordinates + +Maven: + +```xml + + io.github.b6k-dev + outcome + 1.0.0 + +``` + +Gradle: + +```groovy +implementation 'io.github.b6k-dev:outcome:1.0.0' +``` \ No newline at end of file