diff --git a/.github/actions/build-docs/action.yml b/.github/actions/build-docs/action.yml new file mode 100644 index 0000000..f94fd61 --- /dev/null +++ b/.github/actions/build-docs/action.yml @@ -0,0 +1,21 @@ +name: Build Documentation +description: 'Build Documentation.' + +runs: + using: composite + steps: + - name: Setup dotnet build tools + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0 + - name: Install docfx + shell: bash + run: dotnet tool update -g docfx + + # Note: in the docfx.json file, the 'Configuration' property is set to Debug so that we don't require + # signing to happen just to build docs. + - name: Build docs + shell: bash + run: | + docfx metadata + docfx build diff --git a/.github/actions/publish-docs/action.yml b/.github/actions/publish-docs/action.yml new file mode 100644 index 0000000..17a6a40 --- /dev/null +++ b/.github/actions/publish-docs/action.yml @@ -0,0 +1,24 @@ +name: Publish Documentation +description: 'Publish the documentation to Github pages' +inputs: + dry_run: + description: 'Is this a dry run. If so no package will be published.' + required: true + token: + description: 'Token to use for publishing.' + required: true + +runs: + using: composite + steps: + - uses: launchdarkly/gh-actions/actions/publish-pages@publish-pages-v1.0.2 + if: ${{ inputs.dry_run == 'false' }} + name: 'Publish to Github pages' + with: + docs_path: docs + github_token: ${{ inputs.token }} + - name: Dry Run Publish + if: ${{ inputs.dry_run == 'true' }} + shell: bash + run: | + echo "This is a dry run and docs are not being published." diff --git a/.github/actions/publish/action.yml b/.github/actions/publish/action.yml new file mode 100644 index 0000000..a259f11 --- /dev/null +++ b/.github/actions/publish/action.yml @@ -0,0 +1,50 @@ +name: Publish Package +description: 'Packs DLLs into unsigned Nuget package and publishes to Nuget.' +inputs: + dry_run: + description: 'Is this a dry run. If so no package will be published.' + required: true +outputs: + hashes: + description: sha256sum hashes of built artifacts + value: ${{ steps.hash.outputs.hashes }} + +runs: + using: composite + steps: + - name: Setup dotnet build tools + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0 + + - name: Create Nuget Package + shell: bash + run: | + dotnet restore ./src/LaunchDarkly.EventSource/LaunchDarkly.EventSource.csproj + dotnet pack --no-build --output nupkgs --configuration Release ./src/LaunchDarkly.EventSource/LaunchDarkly.EventSource.csproj + + - name: Publish Package + if: ${{ inputs.dry_run == 'false' }} + shell: bash + run: | + for pkg in $(find ./nupkgs -name '*.nupkg' -o -name '*.snupkg'); do + echo "publishing ${pkg}" + dotnet nuget push "${pkg}" --api-key ${{ env.NUGET_API_KEY }} --source https://www.nuget.org + echo "published ${pkg}" + done + + - name: Hash nuget packages + id: hash + if: ${{ inputs.dry_run == 'false' }} + shell: bash + run: | + echo "hashes=$(sha256sum ./nupkgs/*.nupkg ./nupkgs/*.snupkg | base64 -w0)" >> "$GITHUB_OUTPUT" + + - name: Dry Run Publish + if: ${{ inputs.dry_run == 'true' }} + shell: bash + run: | + echo "This is a dry run and packages are not being published." + for pkg in $(find ./nupkgs -name '*.nupkg' -o -name '*.snupkg'); do + echo "detected package ${pkg}" + done diff --git a/.github/actions/release-build/action.yml b/.github/actions/release-build/action.yml new file mode 100644 index 0000000..45a5be1 --- /dev/null +++ b/.github/actions/release-build/action.yml @@ -0,0 +1,18 @@ +name: Release Build +description: 'Build in Release Configuration' + +runs: + using: composite + steps: + - name: Setup dotnet build tools + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0 + + - name: Restore Packages + shell: bash + run: dotnet restore + + - name: Build + shell: bash + run: dotnet build /p:Configuration=Release ./src/LaunchDarkly.EventSource/LaunchDarkly.EventSource.csproj diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 921cc1a..09f9490 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,3 +35,6 @@ jobs: - run: dotnet build src/LaunchDarkly.EventSource/LaunchDarkly.EventSource.csproj - run: dotnet test test/LaunchDarkly.EventSource.Tests/LaunchDarkly.EventSource.Tests.csproj + + - name: build docs + uses: ./.github/actions/build-docs diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..7b99445 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,86 @@ +name: Publish Package + +on: + workflow_dispatch: + inputs: + dry_run: + description: 'Is this a dry run. If so no package will be published.' + type: boolean + required: true + tag: + description: 'Tag for provenance. For a dry run the value does not matter.' + type: string + required: true + + workflow_call: + inputs: + dry_run: + description: 'Is this a dry run. If so no package will be published.' + type: boolean + required: true + tag: + description: 'Tag for provenance' + type: string + required: true + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + id-token: write # Needed if using OIDC to get release secrets. + contents: write # Contents and pull-requests are for release-please to make releases. + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0 + name: Get secrets + with: + aws_assume_role: ${{ vars.AWS_ROLE_ARN }} + ssm_parameter_pairs: '/production/common/releasing/digicert/host = DIGICERT_HOST, + /production/common/releasing/digicert/api_key = DIGICERT_API_KEY, + /production/common/releasing/digicert/client_cert_file_b64 = DIGICERT_CLIENT_CERT_FILE_B64, + /production/common/releasing/digicert/client_cert_password = DIGICERT_CLIENT_CERT_PASSWORD, + /production/common/releasing/digicert/code_signing_cert_sha1_hash = DIGICERT_CODE_SIGNING_CERT_SHA1_HASH, + /production/common/releasing/nuget/api_key = NUGET_API_KEY' + s3_path_pairs: 'launchdarkly-releaser/dotnet/LaunchDarkly.EventSource.snk = LaunchDarkly.EventSource.snk' + + + - name: Build Release + uses: ./.github/actions/release-build + + - name: Build Documentation + uses: ./.github/actions/build-docs + + - name: Sign DLLs + uses: launchdarkly/gh-actions/actions/sign-dlls@sign-dlls-v1.0.0 + with: + build_configuration_path: ./src/LaunchDarkly.EventSource/bin/Release + dll_name: LaunchDarkly.EventSource.Microsoft.dll + + - name: Publish Nupkg + id: publish + uses: ./.github/actions/publish + with: + dry_run: ${{ inputs.dry_run }} + + - name: Publish Documentation + uses: ./.github/actions/publish-docs + with: + token: ${{ secrets.GITHUB_TOKEN }} + dry_run: ${{ inputs.dry_run }} + + provenance: + permissions: + actions: read + id-token: write + contents: write + if: ${{ inputs.dry_run == 'false' }} + needs: ['publish'] + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.10.0 + with: + base64-subjects: "${{ needs.publish.outputs.hashes }}" + upload-assets: true + upload-tag-name: ${{ inputs.tag }} + provenance-name: ${{ format('LaunchDarkly.EventSource-{0}_provenance.intoto.jsonl', inputs.tag) }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..522eb94 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,36 @@ +name: Release Please + +on: + push: + branches: + - main + +jobs: + release-please: + outputs: + releases_created: ${{ steps.release.outputs.releases_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + runs-on: ubuntu-latest + permissions: + id-token: write # Needed if using OIDC to get release secrets. + contents: write # Contents and pull-requests are for release-please to make releases. + pull-requests: write + + steps: + - uses: googleapis/release-please-action@v4 + id: release + with: + token: ${{secrets.GITHUB_TOKEN}} + default-branch: main + + ci: + needs: ['release-please'] + if: ${{ needs.release-please.outputs.releases_created == 'true' }} + uses: ./.github/workflows/ci.yml + publish: + needs: ['release-please', 'ci'] + if: ${{ needs.release-please.outputs.releases_created == 'true' }} + uses: ./.github/workflows/publish.yml + with: + dry_run: false + tag: ${{ needs.release-please.outputs.tag_name }} diff --git a/.gitignore b/.gitignore index 2a2eec5..341abce 100644 --- a/.gitignore +++ b/.gitignore @@ -97,9 +97,6 @@ DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html -# Click-Once directory -publish - # Others [Bb]in [Oo]bj @@ -179,3 +176,6 @@ project.lock.json *.snk *.p12 + +api/ +docs/ diff --git a/.ldrelease/config.yml b/.ldrelease/config.yml deleted file mode 100644 index a58dc66..0000000 --- a/.ldrelease/config.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: 2 - -publications: - - url: https://nuget.org/packages/LaunchDarkly.EventSource - description: NuGet - -branches: - - name: main - description: 5.x - for server-side .NET SDK 7.0+ and client-side .NET SDK 3.0+ - - name: 4.x - description: for .NET SDK 6.0+ and Xamarin SDK 2.0+ - - name: 3.x - description: for earlier .NET and Xamarin SDKs - -jobs: - - template: - name: dotnet6-linux - env: - LD_RELEASE_DOCS_TARGET_FRAMEWORK: netstandard2.0 - LD_RELEASE_TEST_TARGET_FRAMEWORK: net6.0 - -documentation: - gitHubPages: true - title: LaunchDarkly .NET EventSource Client diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..affd1ab --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "5.1.0" +} diff --git a/docfx.json b/docfx.json new file mode 100644 index 0000000..990436b --- /dev/null +++ b/docfx.json @@ -0,0 +1,48 @@ +{ + "metadata": [ + { + "src": [ + { + "src": "./src", + "files": [ + "**/*.csproj", + "**/bin/**/**LaunchDarkly**.dll" + ] + } + ], + "dest": "./api", + "properties" : { + "Configuration": "Debug" + } + } + ], + "build": { + "content": [ + { + "files": [ + "**/*.{md,yml}" + ], + "exclude": [ + "docs/**" + ] + } + ], + "resource": [ + { + "files": [ + "images/**" + ] + } + ], + "output": "docs", + "template": [ + "default" + ], + "globalMetadata": { + "_appName": "LaunchDarkly EventSource for .NET", + "_appTitle": "LaunchDarkly EventSource for .NET", + "_enableSearch": true, + "pdf": false + } + } +} diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..1f0b85a --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,10 @@ +{ + "packages": { + ".": { + "release-type": "simple", + "bootstrap-sha": "42cd339937a4affdbe94ab0d49694a86eb85c75f", + "include-v-in-tag": false, + "include-component-in-tag": false + } + } +}