diff --git a/.github/workflows/cd-build-test-pack.yml b/.github/workflows/cd-build-test-pack.yml new file mode 100644 index 0000000..b60b5e8 --- /dev/null +++ b/.github/workflows/cd-build-test-pack.yml @@ -0,0 +1,52 @@ +name: "Build, Test & Pack (Reusable)" + +on: + workflow_call: + inputs: + version: + required: true + type: string + configuration: + required: true + type: string + default: Release + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Sanitize version + id: sanitize + run: | + v='${{ inputs.version }}' + # Remove leading v or V if present + v="${v#v}" + v="${v#V}" + echo "sanitized_version=$v" >> $GITHUB_OUTPUT + + - name: Build + run: dotnet build --configuration ${{ inputs.configuration }} /p:Version=${{ steps.sanitize.outputs.sanitized_version }} + + - name: Test + run: dotnet test --configuration ${{ inputs.configuration }} /p:Version=${{ steps.sanitize.outputs.sanitized_version }} --no-build + + - name: Pack + run: dotnet pack --configuration ${{ inputs.configuration }} /p:Version=${{ steps.sanitize.outputs.sanitized_version }} --output . + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: nuget-packages + path: | + *.nupkg + *.snupkg \ No newline at end of file diff --git a/.github/workflows/cd-release-preview.yml b/.github/workflows/cd-release-preview.yml index 02102ef..23dc8d7 100644 --- a/.github/workflows/cd-release-preview.yml +++ b/.github/workflows/cd-release-preview.yml @@ -6,26 +6,18 @@ on: - "v[0-9]+\\.[0-9]+\\.[0-9]+-preview*" jobs: - build: - runs-on: ubuntu-latest - timeout-minutes: 15 + build-and-pack: + uses: ./.github/workflows/cd-build-test-pack.yml + with: + version: ${{ github.ref_name }} + configuration: Release + publish: + needs: build-and-pack + runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - - name: Set VERSION variable from tag - run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_ENV - - - name: Pack - run: dotnet pack --configuration Release /p:Version=${VERSION} --output . + - name: Download artifacts + uses: actions/download-artifact@v4 - - name: Push - run: dotnet nuget push CryptoNet.${VERSION}.nupkg --source https://api.nuget.org/v3/index.json --api-key ${NUGET_TOKEN} - env: - NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }} + - name: Push to NuGet + run: dotnet nuget push nuget-packages/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_TOKEN }} diff --git a/.github/workflows/cd-release.yml b/.github/workflows/cd-release.yml index 520a867..bc160fc 100644 --- a/.github/workflows/cd-release.yml +++ b/.github/workflows/cd-release.yml @@ -6,11 +6,8 @@ on: - "v[0-9]+.[0-9]+.[0-9]+" jobs: - build: + prepare: runs-on: ubuntu-latest - - timeout-minutes: 15 - steps: - name: Checkout uses: actions/checkout@v4 @@ -24,24 +21,25 @@ jobs: run: | git log --pretty=format:'%d %s' ${GITHUB_REF} | perl -pe 's| \(.*tag: v(\d+.\d+.\d+(-preview\d{3})?)(, .*?)*\)|\n## \1\n|g' > RELEASE-NOTES - - name: Setup .NET - uses: actions/setup-dotnet@v4 + - name: Upload release notes + uses: actions/upload-artifact@v4 with: - dotnet-version: 8.0.x - - - name: Set VERSION variable from tag - run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_ENV - - - name: Build - run: dotnet build --configuration Release /p:Version=${VERSION} - - - name: Test - run: dotnet test --configuration Release /p:Version=${VERSION} --no-build - - - name: Pack - run: dotnet pack --configuration Release /p:Version=${VERSION} --output . + name: release-notes + path: RELEASE-NOTES + + build-and-pack: + needs: prepare + uses: ./.github/workflows/cd-build-test-pack.yml + with: + version: ${{ github.ref_name }} + configuration: Release + + publish: + needs: build-and-pack + runs-on: ubuntu-latest + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 - - name: Push - run: dotnet nuget push CryptoNet.${VERSION}.nupkg --source https://api.nuget.org/v3/index.json --api-key ${NUGET_TOKEN} - env: - NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }} + - name: Push to NuGet + run: dotnet nuget push nuget-packages/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_TOKEN }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a965657 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,100 @@ +# Contributing Guidelines + +## Purpose + +This document explains project-level development and CI/CD conventions +contributors must follow to avoid common build and packaging failures. + +## Workflow Reuse Guidelines + +### Calling a Reusable Workflow + +- When invoking a reusable workflow using `uses:` at **job level**, + **do NOT specify `runs-on`** in the caller. +- The **reusable workflow must**: + - Declare `on: workflow_call` + - Define `runs-on` for its internal jobs +- Inputs are passed via `with:`, and secrets via `secrets:`. + +### Example: Caller (no `runs-on`) + +``` yaml +jobs: + call-build: + uses: ./.github/workflows/cd-build-test-pack.yml + with: + version: ${{ github.ref_name }} + configuration: Release +``` + +### Example: Reusable Workflow + +``` yaml +on: + workflow_call: + inputs: + version: + required: true + type: string + configuration: + required: true + type: string + default: Release + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + # … +``` + +## Versioning and Git Tag Guidelines + +- Tags used for packaging and publishing---whether passed to + `/p:Version=` or `dotnet pack`---**must be valid SemVer/NuGet + version strings**. +- **Do NOT include a leading `v`** when passing the version into + `dotnet` commands. + +### Valid Examples + +- `3.2.6` +- `3.2.6-preview` +- `3.2.6-preview20251130229` +- `3.2.6-alpha.1+build.123` + +### Invalid Examples + +- `v3.2.6-preview20251130229` +- `3.2.6 preview` + +### Recommended Tagging Practice + +- Tag with leading `v` locally if desired, but CI must sanitize it. + +## CI Behavior and Version Sanitization + +### Sanitization Example + +``` yaml +- name: Sanitize version + id: sanitize + run: | + v="${{ inputs.version }}" + v="${v#v}" + v="${v#V}" + echo "sanitized_version=$v" >> "$GITHUB_OUTPUT" +``` + +Use via: `${{ steps.sanitize.outputs.sanitized_version }}` + +## Troubleshooting + +- If CI reports "not a valid version string," check for leading `v` or + invalid characters. + +## Maintenance + +- Keep conventions aligned with GitHub Actions and NuGet rules. diff --git a/CryptoNet.sln b/CryptoNet.sln index de449c6..ca2ae6a 100644 --- a/CryptoNet.sln +++ b/CryptoNet.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.3.11222.16 d18.3 +VisualStudioVersion = 18.3.11222.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CryptoNet", "CryptoNet\CryptoNet.csproj", "{8F85375C-A0DC-4B67-B934-F58ED4114F5A}" EndProject @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevOps", "DevOps", "{1733D1 .gitattributes = .gitattributes .gitignore = .gitignore build.ps1 = build.ps1 + .github\workflows\cd-build-test-pack.yml = .github\workflows\cd-build-test-pack.yml .github\workflows\cd-release-preview.yml = .github\workflows\cd-release-preview.yml .github\workflows\cd-release.yml = .github\workflows\cd-release.yml .github\workflows\ci.yml = .github\workflows\ci.yml