From b493328b85bacf1489f01c3f34f1b0a482ad0280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20J=C3=B6rg?= Date: Thu, 29 Jan 2026 13:18:41 +0100 Subject: [PATCH] Add Semantic Release --- build-dotnet/README.md | 3 + build-dotnet/action.yaml | 80 ++++++++++++++++++++++++ sr/action.yaml | 129 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 build-dotnet/README.md create mode 100644 build-dotnet/action.yaml create mode 100644 sr/action.yaml diff --git a/build-dotnet/README.md b/build-dotnet/README.md new file mode 100644 index 0000000..154a030 --- /dev/null +++ b/build-dotnet/README.md @@ -0,0 +1,3 @@ +# build-dotnet + +A Gitea Action which builds a .NET project. diff --git a/build-dotnet/action.yaml b/build-dotnet/action.yaml new file mode 100644 index 0000000..6fe7dfc --- /dev/null +++ b/build-dotnet/action.yaml @@ -0,0 +1,80 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-action.json +name: "publish-nuget" +description: "Publishes a NuGet package to a Gitea-hosted NuGet registry and attests to its contents." +inputs: + package-path: + description: "Path to the package directory relative to src/, e.g. Oceanbox.FvcomKit" + required: true + nuget-key: + description: "API key with which to authenticate to the NuGet registry." + required: true + registry: + description: "Gitea registry domain, e.g. git.oceanbox.io" + required: true + default: "git.oceanbox.io" + registry-owner: + description: "Registry owner/organization name, e.g. oceanbox" + required: true + default: "oceanbox" + source-name: + description: "Name to use for the NuGet source when adding it." + required: false + default: "gitea-nuget" + nupkg-dir: + description: "Directory where .nupkg files will be output" + required: false + default: "./nupkgs" + configuration: + description: "Build configuration (Release or Debug)" + required: false + default: "Release" + dotnet-restore-args: + description: "Additional arguments to pass to dotnet restore" + required: false + default: "" + dotnet-build-args: + description: "Additional arguments to pass to dotnet build" + required: false + default: "" + dotnet-pack-args: + description: "Additional arguments to pass to dotnet pack" + required: false + default: "-p:TargetsForTfmSpecificContentInPackage=" +runs: + using: "composite" + steps: + - name: Prep NuGet source + shell: bash + run: | + nix-shell --run 'set -o pipefail; set -o nounset; set -o errexit; + dotnet nuget add source --name ${{ inputs.source-name }} "https://${{ inputs.registry }}/api/packages/${{ inputs.registry-owner }}/nuget/index.json"' + + - name: Restore dependencies + shell: bash + run: | + nix-shell --run "set -o pipefail; set -o nounset; set -o errexit; + dotnet restore src/${{ inputs.package-path }} ${{ inputs.dotnet-restore-args }}" + + - name: Build + shell: bash + run: | + nix-shell --run "set -o pipefail; set -o nounset; set -o errexit; + dotnet build --no-restore --configuration ${{ inputs.configuration }} src/${{ inputs.package-path }} ${{ inputs.dotnet-build-args }}" + + - name: Pack + shell: bash + run: | + nix-shell --run "set -o pipefail; set -o nounset; set -o errexit; + dotnet pack src/${{ inputs.package-path }} --no-restore ${{ inputs.dotnet-pack-args }} --configuration ${{ inputs.configuration }} -o ${{ inputs.nupkg-dir }}" + + - name: Publish NuGet package + shell: bash + run: | + nix-shell --run "set -o pipefail; set -o nounset; set -o errexit; + dotnet nuget push ${{ inputs.nupkg-dir }}/${{ inputs.package-path }}.*.nupkg --api-key ${{ inputs.nuget-key }} --source '${{ inputs.source-name }}' --skip-duplicate" + + # TODO: Add attestation + # - name: Attest Build Provenance + # uses: actions/attest-build-provenance@v1 + # with: + # subject-path: ${{ inputs.nupkg-dir }}/${{ inputs.package-path }}.*.nupkg diff --git a/sr/action.yaml b/sr/action.yaml new file mode 100644 index 0000000..7162636 --- /dev/null +++ b/sr/action.yaml @@ -0,0 +1,129 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-action.json +name: semantic-release +description: Run Semantic Release against a Gitea repository + +inputs: + gitea-url: + description: Gitea instance URL + required: true + default: https://git.oceanbox.io + + gitea-token: + description: Gitea access token + required: true + + nix-shell: + description: Nix shell attribute to use + required: false + default: ci + +outputs: + new_release_published: + description: Whether a new release was published + value: ${{ steps.semantic.outputs.new_release_published }} + + new_release_version: + description: Version that was released + value: ${{ steps.semantic.outputs.new_release_version }} + +runs: + using: composite + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Create package.json + shell: bash + run: | + cat > package.json << 'EOF' + { + "private": true, + "type": "module", + "devDependencies": { + "@semantic-release/changelog": "^6.0.3", + "@semantic-release/exec": "^6.0.3", + "@semantic-release/git": "^10.0.1", + "@markwylde/semantic-release-gitea": "^2.2.0", + "semantic-release-dotnet": "^1.0.0" + } + } + EOF + + - name: Install semantic-release dependencies + shell: bash + run: | + nix-shell -A "${{ inputs.nix-shell }}" --run ' + set -o pipefail + set -o nounset + set -o errexit + npm install + ' + + - name: Create .releaserc.json + shell: bash + run: | + cat > .releaserc.json << 'EOF' + { + "branches": [ + "main", + "master", + { "name": "develop", "prerelease": true } + ], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + ["@semantic-release/changelog", { + "changelogFile": "RELEASE_NOTES.md", + "changelogTitle": "# Changelog" + }], + ["semantic-release-dotnet", { + "paths": ["src/*.fsproj", "src/*/**.fsproj"] + }], + ["@semantic-release/exec", { + "generateNotesCmd": "echo ${nextRelease.version} > VERSION" + }], + ["@semantic-release/git", { + "message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}", + "assets": [ + "RELEASE_NOTES.md", + ".version", + "src/*.fsproj", + "src/*/**.fsproj" + ] + }], + ["@markwylde/semantic-release-gitea", { + "giteaUrl": "${{ inputs.gitea-url }}", + "assets": [] + }] + ], + "analyzeCommits": [ + { + "path": "@semantic-release/commit-analyzer", + "releaseRules": [ + { "type": "fix", "release": "patch" }, + { "type": "patch", "release": "patch" }, + { "type": "feat", "release": "minor" }, + { "type": "feature", "release": "minor" }, + { "type": "minor", "release": "minor" }, + { "type": "breaking", "release": "major" }, + { "type": "major", "release": "major" } + ] + } + ] + } + EOF + + - name: Run semantic-release + id: semantic + shell: bash + env: + GITEA_TOKEN: ${{ inputs.gitea-token }} + GITEA_URL: ${{ inputs.gitea-url }} + FORCE_COLOR: "1" + run: | + nix-shell -A "${{ inputs.nix-shell }}" --run ' + set -o pipefail + set -o nounset + set -o errexit + semantic-release + '