diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..7d7863a
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,57 @@
+name: CI
+
+on:
+ pull_request:
+ branches: [ master ]
+
+# PR validation only reads the repo.
+permissions:
+ contents: read
+
+# Cancel superseded runs for the same PR.
+concurrency:
+ group: ci-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ DOTNET_NOLOGO: true
+ DOTNET_CLI_TELEMETRY_OPTOUT: true
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+ NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
+
+jobs:
+ build-test:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: src # global.json (Microsoft.Testing.Platform opt-in) lives here
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # MinVer needs full history + tags to compute the version
+
+ - name: Setup .NET (8 + 10)
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 10.0.x
+ # Build uses the SDK pinned by src/global.json (10.0.100); the 8.0 runtime
+ # installed here is what actually runs the net8.0 test target.
+
+ - name: Cache NuGet packages
+ uses: actions/cache@v4
+ with:
+ path: ${{ github.workspace }}/.nuget/packages
+ key: nuget-${{ runner.os }}-${{ hashFiles('src/Directory.Packages.props') }}
+ restore-keys: nuget-${{ runner.os }}-
+
+ - name: Restore
+ run: dotnet restore ExistAll.SimpleConfig.slnx
+
+ - name: Build (Release, deterministic)
+ run: dotnet build ExistAll.SimpleConfig.slnx -c Release --no-restore -p:ContinuousIntegrationBuild=true
+
+ - name: Test (net8.0 + net10.0)
+ run: dotnet test ExistAll.SimpleConfig.slnx -c Release --no-build
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
deleted file mode 100644
index 5a087da..0000000
--- a/.github/workflows/dotnet.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: .NET
-
-on:
- push:
- branches: [ master ]
-
-jobs:
- build:
- runs-on: ubuntu-latest
- environment:
- name: testing
- steps:
- - uses: actions/checkout@v2
- build1:
- needs: [build]
- runs-on: ubuntu-latest
- environment:
- name: prod
- steps:
- - uses: actions/checkout@v2
-
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..b17eeae
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,250 @@
+name: Release
+
+on:
+ push:
+ branches: [ master ] # every merge -> fresh alpha prerelease
+ workflow_dispatch:
+ inputs:
+ channel:
+ description: Release channel
+ type: choice
+ options: [ beta, rc, stable ]
+ default: beta
+ bump:
+ description: SemVer part to bump (relative to the latest stable tag; ignored on the first release)
+ type: choice
+ options: [ patch, minor, major ]
+ default: minor
+ dry_run:
+ description: Build/pack/upload only - do NOT tag, push to NuGet, or create a Release
+ type: boolean
+ default: false
+
+permissions:
+ contents: read
+
+# Serialize releases; never cancel an in-flight publish.
+concurrency:
+ group: release
+ cancel-in-progress: false
+
+env:
+ DOTNET_NOLOGO: true
+ DOTNET_CLI_TELEMETRY_OPTOUT: true
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+ NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
+ ARTIFACTS: ${{ github.workspace }}/artifacts
+ NUGET_SOURCE: https://api.nuget.org/v3/index.json
+ TAG_PREFIX: v # deliberately NOT "version-": those tags are the dead ExistAll.SimpleConfig line
+ BASELINE_VERSION: 2.0.0 # first release on the v* line (modernized, breaking vs published 1.0.0)
+
+jobs:
+ # ---------------------------------------------------------------------------
+ # A) Automatic ALPHA prerelease on every push to master.
+ # MinVer stamps a height-based prerelease, e.g. 2.0.0-alpha.0.7.
+ # ---------------------------------------------------------------------------
+ prerelease:
+ if: github.event_name == 'push'
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read # no tag/release here
+ id-token: write # OIDC for NuGet trusted publishing
+ defaults:
+ run:
+ working-directory: src
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 10.0.x
+
+ - uses: actions/cache@v4
+ with:
+ path: ${{ github.workspace }}/.nuget/packages
+ key: nuget-${{ runner.os }}-${{ hashFiles('src/Directory.Packages.props') }}
+ restore-keys: nuget-${{ runner.os }}-
+
+ - name: Restore
+ run: dotnet restore ExistAll.SimpleConfig.slnx
+
+ - name: Build
+ run: dotnet build ExistAll.SimpleConfig.slnx -c Release --no-restore -p:ContinuousIntegrationBuild=true
+
+ - name: Test
+ run: dotnet test ExistAll.SimpleConfig.slnx -c Release --no-build
+
+ - name: Pack (MinVer -> height-based alpha)
+ run: dotnet pack ExistAll.SimpleConfig.slnx -c Release --no-build -p:ContinuousIntegrationBuild=true -o "$ARTIFACTS"
+
+ - name: List packages
+ run: ls -1 "$ARTIFACTS"
+
+ - name: Upload packages
+ uses: actions/upload-artifact@v4
+ with:
+ name: nuget-prerelease
+ path: |
+ ${{ env.ARTIFACTS }}/*.nupkg
+ ${{ env.ARTIFACTS }}/*.snupkg
+
+ - name: NuGet login (OIDC -> short-lived API key)
+ uses: NuGet/login@v1
+ id: login
+ with:
+ user: ${{ secrets.NUGET_USER }}
+
+ # dotnet nuget push globs natively; each .nupkg also pushes its adjacent .snupkg.
+ - name: Push to NuGet.org
+ run: dotnet nuget push "$ARTIFACTS/*.nupkg" --api-key "${{ steps.login.outputs.NUGET_API_KEY }}" --source "$NUGET_SOURCE" --skip-duplicate
+
+ # ---------------------------------------------------------------------------
+ # B) Manual, curated RELEASE (beta.N / rc.N / stable) via workflow_dispatch.
+ # Tag is created LOCALLY (MinVer reads it), pushed only AFTER a successful
+ # NuGet push, then a GitHub Release is created.
+ # ---------------------------------------------------------------------------
+ release:
+ if: github.event_name == 'workflow_dispatch'
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write # push tag + create GitHub Release
+ id-token: write # OIDC for NuGet trusted publishing
+ environment:
+ name: nuget.org # add a Required reviewer here to gate stable publishes
+ defaults:
+ run:
+ working-directory: src
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # all tags -> correct next-version computation
+
+ - uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 10.0.x
+
+ - uses: actions/cache@v4
+ with:
+ path: ${{ github.workspace }}/.nuget/packages
+ key: nuget-${{ runner.os }}-${{ hashFiles('src/Directory.Packages.props') }}
+ restore-keys: nuget-${{ runner.os }}-
+
+ - name: Compute next version tag
+ id: ver
+ env:
+ BUMP: ${{ inputs.bump }}
+ CHANNEL: ${{ inputs.channel }}
+ run: |
+ set -euo pipefail
+ PREFIX="$TAG_PREFIX"
+ git fetch --tags --force --quiet
+
+ # Highest STABLE tag under the "v" prefix: vMAJOR.MINOR.PATCH (no pre-release).
+ # The "v[0-9]" glob excludes the legacy "version-*" tags by construction.
+ latest_stable="$(
+ git tag --list "${PREFIX}[0-9]*" \
+ | grep -E "^${PREFIX}[0-9]+\.[0-9]+\.[0-9]+$" \
+ | sed "s/^${PREFIX}//" \
+ | sort -V | tail -n1 || true
+ )"
+
+ if [ -z "$latest_stable" ]; then
+ # First release on the v* line -> the baseline itself (bump ignored).
+ TARGET="$BASELINE_VERSION"
+ echo "No v* stable tag yet -> first release targets baseline $TARGET (bump '$BUMP' ignored)."
+ else
+ IFS='.' read -r MA MI PA <<< "$latest_stable"
+ case "$BUMP" in
+ major) MA=$((MA+1)); MI=0; PA=0 ;;
+ minor) MI=$((MI+1)); PA=0 ;;
+ patch) PA=$((PA+1)) ;;
+ *) echo "::error::invalid bump '$BUMP'"; exit 1 ;;
+ esac
+ TARGET="${MA}.${MI}.${PA}"
+ echo "Latest stable $latest_stable + $BUMP -> $TARGET"
+ fi
+
+ if [ "$CHANNEL" = "stable" ]; then
+ NEW_TAG="${PREFIX}${TARGET}"
+ if git rev-parse -q --verify "refs/tags/${NEW_TAG}" >/dev/null; then
+ echo "::error::tag ${NEW_TAG} already exists"; exit 1
+ fi
+ PRERELEASE=false
+ else
+ # Continue the -beta.N / -rc.N series for this target base.
+ last_n="$(
+ git tag --list "${PREFIX}${TARGET}-${CHANNEL}.*" \
+ | sed -E "s/^${PREFIX}${TARGET}-${CHANNEL}\.([0-9]+)$/\1/" \
+ | grep -E '^[0-9]+$' | sort -n | tail -n1 || true
+ )"
+ next_n=$(( ${last_n:-0} + 1 ))
+ NEW_TAG="${PREFIX}${TARGET}-${CHANNEL}.${next_n}"
+ PRERELEASE=true
+ fi
+
+ echo "Computed tag: $NEW_TAG (prerelease=$PRERELEASE)"
+ {
+ echo "tag=$NEW_TAG"
+ echo "prerelease=$PRERELEASE"
+ } >> "$GITHUB_OUTPUT"
+
+ - name: Create local tag (MinVer reads it at pack time)
+ run: |
+ set -euo pipefail
+ git config user.name "github-actions[bot]"
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+ git tag -a "${{ steps.ver.outputs.tag }}" -m "Release ${{ steps.ver.outputs.tag }}"
+
+ - name: Restore
+ run: dotnet restore ExistAll.SimpleConfig.slnx
+
+ - name: Build
+ run: dotnet build ExistAll.SimpleConfig.slnx -c Release --no-restore -p:ContinuousIntegrationBuild=true
+
+ - name: Test
+ run: dotnet test ExistAll.SimpleConfig.slnx -c Release --no-build
+
+ - name: Pack (MinVer -> exact tagged version)
+ run: dotnet pack ExistAll.SimpleConfig.slnx -c Release --no-build -p:ContinuousIntegrationBuild=true -o "$ARTIFACTS"
+
+ - name: Upload packages
+ uses: actions/upload-artifact@v4
+ with:
+ name: nuget-${{ steps.ver.outputs.tag }}
+ path: |
+ ${{ env.ARTIFACTS }}/*.nupkg
+ ${{ env.ARTIFACTS }}/*.snupkg
+
+ - name: NuGet login (OIDC -> short-lived API key)
+ if: ${{ !inputs.dry_run }}
+ uses: NuGet/login@v1
+ id: login
+ with:
+ user: ${{ secrets.NUGET_USER }}
+
+ # dotnet nuget push globs natively; each .nupkg also pushes its adjacent .snupkg.
+ - name: Push to NuGet.org
+ if: ${{ !inputs.dry_run }}
+ run: dotnet nuget push "$ARTIFACTS/*.nupkg" --api-key "${{ steps.login.outputs.NUGET_API_KEY }}" --source "$NUGET_SOURCE" --skip-duplicate
+
+ - name: Push git tag (only after a successful publish)
+ if: ${{ !inputs.dry_run }}
+ run: git push origin "${{ steps.ver.outputs.tag }}"
+
+ - name: Create GitHub Release
+ if: ${{ !inputs.dry_run }}
+ uses: softprops/action-gh-release@v3
+ with:
+ tag_name: ${{ steps.ver.outputs.tag }}
+ name: ${{ steps.ver.outputs.tag }}
+ prerelease: ${{ steps.ver.outputs.prerelease }}
+ generate_release_notes: true
+ files: |
+ ${{ env.ARTIFACTS }}/*.nupkg
+ ${{ env.ARTIFACTS }}/*.snupkg
diff --git a/icon.png b/icon.png
new file mode 100644
index 0000000..9391ae6
Binary files /dev/null and b/icon.png differ
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 8b5f4f9..1525c1f 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -4,20 +4,52 @@
enable
enable
- latest
+
-
+
- 1.0.0
Guy Ludvig
ExistsForAll
SimpleSettings allow applications to use configurations values from any data store in the type of interfaces, thus decouples the frameworks from your appliaction and allowing application to inject interfaces and nothing else. This framework should be used instead of .Net Core IOptions<T>.
- https://github.com/existall/SimpleConfig
- https://github.com/existall/SimpleConfig
- GIT
+ https://github.com/existall/SimpleSettings
+ https://github.com/existall/SimpleSettings
+ git
MIT
Configuration, Settings, Ioc, DI, ExistsForAll, Dependency injection, Options, SimpleConfig
+ icon.png
+ README.md
+
+
+
+
+
+
+
+
+ v
+ 2.0
+
+
+
+
+ true
+ snupkg
+ true
+ true
+ true
+
+
+
+
+
+
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index c15f5d1..b940f83 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -21,4 +21,9 @@
+
+
+
+
+