From e1f36d1017ae2878446def6cb303c32d756d2343 Mon Sep 17 00:00:00 2001 From: seraphx2 Date: Wed, 9 Sep 2026 11:37:48 -0400 Subject: [PATCH 1/2] ci: CalVer release automation + dev/master branch flow Mirrors the versioning/CI system from the dev-prompt project, adapted for a NuGet library. Branch model: - dev is the long-lived integration branch; everything targets it. - master is the release branch. A dev->master merge cuts exactly one release. Versioning (scripts/compute-version.sh): - CalVer YYYY.(MM*100+DD).BUILD, e.g. 2026.909.1. - Computed at release time from today's date + existing git tags (build = highest same-day tag + 1, else 1). Nothing is hand-incremented. - Tags are un-prefixed to match this repo's existing history; the version is passed to `dotnet pack -p:Version=` so no file is mutated or committed. - csproj is now a 0.0.0-dev placeholder. Workflows: - ci.yml PR gate on master + dev; aggregating `check` job for branch protection. Replaces build-check.yml. - ci-dev.yml per-commit build on push to dev. - release.yml push to master (or manual dispatch) -> compute version, pack, push to NuGet, GitHub Release (creates the tag), Discord. Skips on [skip release] / doc- and CI-only changes. A manual draft run packs without pushing to NuGet. Replaces deploy.yml. - .github/actions/ci-dotnet shared restore + all-TFM Release build. dependabot.yml: grouped weekly nuget + github-actions updates targeting dev; semver-majors ignored (taken by hand). Removed GetBuildVersion.psm1 (dead Azure-DevOps-era snippet) and the SAK source-control junk PropertyGroup. .gitattributes keeps *.sh / *.yml LF-only for the Linux runners. Co-Authored-By: Claude Sonnet 5 --- .gitattributes | 8 +++ .github/actions/ci-dotnet/action.yml | 22 +++++++ .github/dependabot.yml | 36 ++++++++++ .github/workflows/build-check.yml | 29 -------- .github/workflows/ci-dev.yml | 26 ++++++++ .github/workflows/ci.yml | 29 ++++++++ .github/workflows/deploy.yml | 96 --------------------------- .github/workflows/release.yml | 98 ++++++++++++++++++++++++++++ ESI.NET/ESI.NET.csproj | 17 +---- ESI.NET/GetBuildVersion.psm1 | 34 ---------- scripts/compute-version.sh | 37 +++++++++++ 11 files changed, 259 insertions(+), 173 deletions(-) create mode 100644 .github/actions/ci-dotnet/action.yml create mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/build-check.yml create mode 100644 .github/workflows/ci-dev.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/deploy.yml create mode 100644 .github/workflows/release.yml delete mode 100644 ESI.NET/GetBuildVersion.psm1 create mode 100755 scripts/compute-version.sh diff --git a/.gitattributes b/.gitattributes index 1ff0c42..832757f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -61,3 +61,11 @@ #*.PDF diff=astextplain #*.rtf diff=astextplain #*.RTF diff=astextplain + +############################################################################### +# Keep shell scripts and CI YAML LF-only for the Linux CI runners, regardless +# of the checkout platform's autocrlf setting. +############################################################################### +*.sh text eol=lf +*.yml text eol=lf +*.yaml text eol=lf diff --git a/.github/actions/ci-dotnet/action.yml b/.github/actions/ci-dotnet/action.yml new file mode 100644 index 0000000..b226c8a --- /dev/null +++ b/.github/actions/ci-dotnet/action.yml @@ -0,0 +1,22 @@ +name: CI — .NET +description: > + Restore and Release-build ESI.NET across every target framework. Runs on + Linux; the net46x/net47x/net48 targets build against the .NET Framework + reference assemblies the SDK restores, no Mono needed. Assumes the repo is + already checked out. + +runs: + using: composite + steps: + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Restore + shell: bash + run: dotnet restore ESI.NET.sln + + - name: Build (Release, all target frameworks) + shell: bash + run: dotnet build ESI.NET.sln --configuration Release --no-restore diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ad56938 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,36 @@ +# Dependabot version updates. Each ecosystem is grouped, so a run opens at most +# one PR per ecosystem (plus stragglers that can't be grouped). PRs target `dev` +# — the integration branch, where CI (ci-dev.yml) runs. Security alerts are a +# separate repo setting and open PRs only for actual advisories. +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + target-branch: dev + schedule: + interval: weekly + commit-message: + prefix: ci + groups: + actions: + patterns: + - "*" + + - package-ecosystem: nuget + directory: "/ESI.NET" + target-branch: dev + schedule: + interval: weekly + commit-message: + prefix: deps + groups: + nuget: + patterns: + - "*" + # Majors (Microsoft.IdentityModel 7.x/8.x, Microsoft.Extensions.* 9.x, …) + # tend to need code changes — take those by hand; grouped minor/patch keep + # the package graph fresh in the meantime. + ignore: + - dependency-name: "*" + update-types: + - version-update:semver-major diff --git a/.github/workflows/build-check.yml b/.github/workflows/build-check.yml deleted file mode 100644 index a8bd659..0000000 --- a/.github/workflows/build-check.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: PR Build Check - -on: - pull_request: - branches: - - master - -jobs: - build: - runs-on: ubuntu-latest - env: - BUILD_PLATFORM: 'Any CPU' - BUILD_CONFIGURATION: 'Release' - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup .NET SDK - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '7.0.x' - - - name: Restore dependencies - run: dotnet restore - - - name: Build solution - run: | - dotnet build "**/*.sln" --configuration ${{ env.BUILD_CONFIGURATION }} --no-restore diff --git a/.github/workflows/ci-dev.yml b/.github/workflows/ci-dev.yml new file mode 100644 index 0000000..466e28e --- /dev/null +++ b/.github/workflows/ci-dev.yml @@ -0,0 +1,26 @@ +name: CI (dev) + +# Per-commit coverage on the long-lived dev branch, so a break is pinned to the +# commit that caused it instead of surfacing across a whole delta at PR time. +# Separate workflow (not the `check` context) so it never touches the dev->master +# PR gate. Skips doc-only pushes. +on: + push: + branches: [dev] + paths-ignore: + - 'docs/**' + - '**.md' + +concurrency: + group: ci-dev-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/ci-dotnet diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1e5c054 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: CI + +# PR gate for both branches: dev->master (the release gate) and feature->dev +# (contributor PRs). The `check` job aggregates the build and is the required +# status check on master (branch protection) — keep its name stable. +on: + pull_request: + branches: [master, dev] + +# Newer commits on the PR branch supersede an in-flight run. +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/ci-dotnet + + check: + needs: [build] + runs-on: ubuntu-latest + steps: + - run: echo "build passed" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 9708669..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,96 +0,0 @@ -name: Build and Release ESI.NET - -on: - push: - tags: - - '*.*.*' - workflow_dispatch: - inputs: - manual_tag: - description: 'Version tag (example 2025.1.1 (..)' - required: true - -jobs: - build: - runs-on: ubuntu-latest - env: - BUILD_PLATFORM: 'Any CPU' - BUILD_CONFIGURATION: 'Release' - - outputs: - version: ${{ steps.get_version.outputs.version }} - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup .NET SDK - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '7.0.x' - - - name: Extract version from tag or input - id: get_version - shell: bash - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - echo "version=${{ github.event.inputs.manual_tag }}" >> $GITHUB_OUTPUT - else - echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT - fi - - - name: Restore dependencies - run: dotnet restore - - - name: Build solution - run: | - dotnet build ESI.NET.sln --configuration ${{ env.BUILD_CONFIGURATION }} --no-restore - - - name: Create Package - shell: bash - run: | - dotnet pack ESI.NET/ESI.NET.csproj \ - --configuration ${{ env.BUILD_CONFIGURATION }} \ - --output ./nupkgs \ - -p:PackageVersion=${{ steps.get_version.outputs.version }} - - - name: Upload package artifact - uses: actions/upload-artifact@v4 - with: - name: nuget-package - path: ./nupkgs/*.nupkg - - deploy: - needs: build - runs-on: ubuntu-latest - - steps: - - name: Download package artifact - uses: actions/download-artifact@v4 - with: - name: nuget-package - - - name: Push to NuGet.org - run: | - dotnet nuget push "nupkgs/*.nupkg" \ - --api-key ${{ secrets.NUGET_API_KEY }} \ - --source https://api.nuget.org/v3/index.json - - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ github.event.inputs.manual_tag || github.ref_name }} - name: ESI.NET ${{ needs.build.outputs.version }} - body: | - Release for version ${{ needs.build.outputs.version }}. - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Send Discord Webhook - if: success() - env: - DISCORD_WEBHOOK: ${{ github.event_name == 'workflow_dispatch' && secrets.DISCORD_TEST_WEBHOOK_URL || secrets.DISCORD_WEBHOOK_URL }} - uses: Ilshidur/action-discord@0.3.2 - with: - args: | - **ESI.NET ${{ needs.build.outputs.version }} NuGet package released** diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3c71c75 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,98 @@ +name: Release + +# Fires on every push to master — i.e. every dev->master merge — and publishes a +# release: a CalVer version from today's date + existing tags, the NuGet package +# pushed to nuget.org, and a GitHub Release (which creates the tag). Doc-only and +# CI-only merges are skipped (paths-ignore); to opt any other merge out, put +# "[skip release]" in the merge-commit message. workflow_dispatch stays for +# manual drafts / re-runs — a draft build packs and attaches the .nupkg but does +# not push to NuGet. +on: + push: + branches: [master] + paths-ignore: + - 'docs/**' + - '**.md' + - '.github/**' + workflow_dispatch: + inputs: + draft: + description: "Draft: pack + attach the .nupkg, but don't push to NuGet" + type: boolean + default: false + +# One release at a time; never cancel a run that may have already published. +concurrency: + group: release + cancel-in-progress: false + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + # push: skip when the merge commit opts out. dispatch: always run. + if: >- + github.event_name == 'workflow_dispatch' || + !contains(github.event.head_commit.message, '[skip release]') + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # need all tags so the CalVer build segment is correct + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Compute version + id: version + shell: bash + run: echo "value=$(bash scripts/compute-version.sh)" >> "$GITHUB_OUTPUT" + + - name: Pack + shell: bash + run: >- + dotnet pack ESI.NET/ESI.NET.csproj + --configuration Release + --output ./nupkgs + -p:Version=${{ steps.version.outputs.value }} + -p:ContinuousIntegrationBuild=true + + - name: Upload package artifact + uses: actions/upload-artifact@v4 + with: + name: nuget-package + path: ./nupkgs/*.nupkg + + - name: Push to NuGet.org + if: ${{ !inputs.draft }} + shell: bash + run: >- + dotnet nuget push "nupkgs/*.nupkg" + --api-key ${{ secrets.NUGET_API_KEY }} + --source https://api.nuget.org/v3/index.json + --skip-duplicate + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.version.outputs.value }} + name: ESI.NET ${{ steps.version.outputs.value }} + draft: ${{ inputs.draft || false }} + generate_release_notes: true + files: ./nupkgs/*.nupkg + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Send Discord webhook + if: ${{ success() && !inputs.draft }} + env: + DISCORD_WEBHOOK: ${{ github.event_name == 'workflow_dispatch' && secrets.DISCORD_TEST_WEBHOOK_URL || secrets.DISCORD_WEBHOOK_URL }} + uses: Ilshidur/action-discord@0.3.2 + with: + args: | + **ESI.NET ${{ steps.version.outputs.value }} NuGet package released** diff --git a/ESI.NET/ESI.NET.csproj b/ESI.NET/ESI.NET.csproj index cb1585f..b010daa 100644 --- a/ESI.NET/ESI.NET.csproj +++ b/ESI.NET/ESI.NET.csproj @@ -1,16 +1,11 @@  - - SAK - SAK - SAK - SAK - - netcoreapp3.1;netstandard2.0;net462;net47;net471;net472;net48;net6.0;net7.0 true - 2023.12.12 + + 0.0.0-dev Psianna Archeia Sukebe Corporation .NET Wrapper for the Eve Online API @@ -40,10 +35,4 @@ - - - Always - - - diff --git a/ESI.NET/GetBuildVersion.psm1 b/ESI.NET/GetBuildVersion.psm1 deleted file mode 100644 index 7c8b304..0000000 --- a/ESI.NET/GetBuildVersion.psm1 +++ /dev/null @@ -1,34 +0,0 @@ -Function GetBuildVersion { - Param ( - [string]$VersionString - ) - - # Process through regex - $VersionString -match "(?\d+)(\.(?\d+))?(\.(?\d+))?(\-(?
[0-9A-Za-z\-\.]+))?(\+(?\d+))?" | Out-Null
-
-    if ($matches -eq $null) {
-        return "1.0.0-build"
-    }
-
-    # Extract the build metadata
-    $BuildRevision = [uint64]$matches['build']
-    # Extract the pre-release tag
-    $PreReleaseTag = [string]$matches['pre']
-    # Extract the patch
-    $Patch = [uint64]$matches['patch']
-    # Extract the minor
-    $Minor = [uint64]$matches['minor']
-    # Extract the major
-    $Major = [uint64]$matches['major']
-
-    $Version = [string]$Major + '.' + [string]$Minor + '.' + [string]$Patch;
-    if ($PreReleaseTag -ne [string]::Empty) {
-        $Version = $Version + '-' + $PreReleaseTag
-    }
-
-    if ($BuildRevision -ne 0) {
-        $Version = $Version + '.' + [string]$BuildRevision
-    }
-
-    return $Version
-}
\ No newline at end of file
diff --git a/scripts/compute-version.sh b/scripts/compute-version.sh
new file mode 100755
index 0000000..1b2ece2
--- /dev/null
+++ b/scripts/compute-version.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+# CalVer generator: YYYY.(MM*100+DD).BUILD
+#
+#   major = calendar year            e.g. 2026
+#   minor = month*100 + day          e.g. Sep 9 -> 909, Jan 5 -> 105
+#   build = 1 for the day's first release, then +1 per additional same-day build
+#
+# The build segment is derived from existing git tags (..*), so
+# nothing needs to be committed or hand-incremented. Prints just the version
+# string to stdout for the release workflow to consume; diagnostics go to stderr
+# so VERSION=$(scripts/compute-version.sh) stays clean.
+#
+# Tags here are un-prefixed (2026.909.1), matching this repo's existing tag
+# history and the release workflow's tag_name — dev-prompt prefixes them with a
+# leading `v`, this is the one intentional deviation.
+set -euo pipefail
+
+major=$(date -u +%Y)
+month=$(date -u +%m)
+day=$(date -u +%d)
+# 10# forces base-10 so a leading zero (08, 09) isn't read as octal.
+minor=$(( 10#$month * 100 + 10#$day ))
+
+build=1
+tags=$(git tag --list "${major}.${minor}.*" || true)
+if [ -n "$tags" ]; then
+  highest=$(printf '%s\n' "$tags" \
+    | sed -n "s/^${major}\.${minor}\.\([0-9][0-9]*\)$/\1/p" \
+    | sort -n | tail -1)
+  if [ -n "$highest" ]; then
+    build=$(( highest + 1 ))
+  fi
+fi
+
+version="${major}.${minor}.${build}"
+echo "computed version: ${version}" >&2
+printf '%s' "$version"

From 3e0877a3e418c2a4b7b146cecead690e47d0e073 Mon Sep 17 00:00:00 2001
From: seraphx2 
Date: Wed, 9 Sep 2026 11:42:57 -0400
Subject: [PATCH 2/2] ci: bump actions/checkout and actions/setup-dotnet to v5

Clears the Node 20 deprecation warning on the runners.

Co-Authored-By: Claude Sonnet 5 
---
 .github/actions/ci-dotnet/action.yml | 2 +-
 .github/workflows/ci-dev.yml         | 2 +-
 .github/workflows/ci.yml             | 2 +-
 .github/workflows/release.yml        | 4 ++--
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/actions/ci-dotnet/action.yml b/.github/actions/ci-dotnet/action.yml
index b226c8a..e730642 100644
--- a/.github/actions/ci-dotnet/action.yml
+++ b/.github/actions/ci-dotnet/action.yml
@@ -9,7 +9,7 @@ runs:
   using: composite
   steps:
     - name: Setup .NET SDK
-      uses: actions/setup-dotnet@v4
+      uses: actions/setup-dotnet@v5
       with:
         dotnet-version: '8.0.x'
 
diff --git a/.github/workflows/ci-dev.yml b/.github/workflows/ci-dev.yml
index 466e28e..7165e9f 100644
--- a/.github/workflows/ci-dev.yml
+++ b/.github/workflows/ci-dev.yml
@@ -22,5 +22,5 @@ jobs:
   build:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
       - uses: ./.github/actions/ci-dotnet
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1e5c054..9445fc6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -19,7 +19,7 @@ jobs:
   build:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
       - uses: ./.github/actions/ci-dotnet
 
   check:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3c71c75..0e3f5c0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -39,12 +39,12 @@ jobs:
 
     steps:
       - name: Checkout
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
         with:
           fetch-depth: 0 # need all tags so the CalVer build segment is correct
 
       - name: Setup .NET SDK
-        uses: actions/setup-dotnet@v4
+        uses: actions/setup-dotnet@v5
         with:
           dotnet-version: '8.0.x'