diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..eb3a0bf --- /dev/null +++ b/.editorconfig @@ -0,0 +1,61 @@ +# Top-most EditorConfig file +root = true + +# All files +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +# C# files +[*.cs] +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +# Wrapping preferences +csharp_preserve_single_line_statements = true +csharp_preserve_single_line_blocks = true + +# Go files +[*.go] +indent_style = tab +indent_size = 4 + +# Markdown files +[*.md] +trim_trailing_whitespace = false + +# JSON files +[*.json] +indent_size = 2 + +# YAML files +[*.{yml,yaml}] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..594b9bc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,57 @@ +# Set default behavior to automatically normalize line endings. +* text=auto + +# Force batch scripts to always use CRLF line endings so that if a repo is accessed +# in Windows via a file share from Linux, the scripts will work. +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf + +# Force bash scripts to always use LF line endings so that if a repo is accessed +# in Unix via a file share from Windows, the scripts will work. +*.sh text eol=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.mov binary +*.mp4 binary +*.mp3 binary +*.flv binary +*.fla binary +*.swf binary +*.gz binary +*.zip binary +*.7z binary +*.ttf binary +*.eot binary +*.woff binary +*.pyc binary +*.pdf binary + +# Treat these files as text and ensure they use LF line endings +*.cs text diff=csharp +*.csproj text +*.sln text +*.md text +*.json text +*.yml text +*.yaml text +*.xml text +*.txt text +*.sql text +*.html text +*.css text +*.js text +*.ts text + +# Go files +*.go text eol=lf + +# Declare files that will always have CRLF line endings on checkout. +*.sln text eol=crlf + +# Declare files that will always have LF line endings on checkout. +*.sh text eol=lf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..7b77cad --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,34 @@ +# This file defines who is responsible for reviewing and approving changes to different parts of the codebase. + +# Global owners (if no other rule matches) +* @AlrikOlson + +# C# code owners +/src/D2Sharp/*.cs @AlrikOlson + +# Go wrapper code owners +/src/D2Sharp/d2wrapper/ @AlrikOlson + +# CI/CD workflow owners +/.github/workflows/ @AlrikOlson + +# Documentation owners +/docs/ @AlrikOlson +README.md @AlrikOlson + +# Test code owners +/tests/ @AlrikOlson + +# Build script owners +*.csproj @AlrikOlson +*.sln @AlrikOlson + +# Dependency management +/src/D2Sharp/packages.config @AlrikOlson +/src/D2Sharp/d2wrapper/go.mod @AlrikOlson +/src/D2Sharp/d2wrapper/go.sum @AlrikOlson + +# Configuration file owners +.editorconfig @AlrikOlson +.gitattributes @AlrikOlson +.gitignore @AlrikOlson diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..79eada0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + + # Maintain dependencies for NuGet + - package-ecosystem: "nuget" + directory: "/" + schedule: + interval: "weekly" + + # Maintain dependencies for Go modules + - package-ecosystem: "gomod" + directory: "/src/D2Sharp/d2wrapper" + schedule: + interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..4f39534 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,24 @@ +## Description +[Provide a brief description of the changes in this PR] + +## Type of change +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +## How Has This Been Tested? +[Describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration] + +## Checklist: +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published in downstream modules + +## Additional context +[Add any other context or screenshots about the pull request here] diff --git a/.github/workflows/build-and-package.yml b/.github/workflows/build-and-package.yml index dabe840..0c019e7 100644 --- a/.github/workflows/build-and-package.yml +++ b/.github/workflows/build-and-package.yml @@ -1,4 +1,4 @@ -name: Build, Package, and Release +name: CI/CD Pipeline on: push: @@ -17,189 +17,206 @@ env: CI: true jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Run dotnet format + run: dotnet format --verify-no-changes + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + working-directory: src/D2Sharp/d2wrapper + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Setup Go + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + - name: Run tests + run: dotnet test --collect:"XPlat Code Coverage" + - name: Upload coverage + uses: codecov/codecov-action@v3 + build: + needs: [lint, test] strategy: matrix: os: [windows-latest, ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v3 - - - name: Setup .NET - uses: actions/setup-dotnet@v3 - with: - dotnet-version: ${{ env.DOTNET_VERSION }} - - - name: Setup Go - uses: actions/setup-go@v4 - with: - go-version: ${{ env.GO_VERSION }} - - - name: Cache NuGet packages - uses: actions/cache@v3 - with: - path: ~/.nuget/packages - key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} - restore-keys: | - ${{ runner.os }}-nuget- - - - name: Install GCC (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: sudo apt-get update && sudo apt-get install -y gcc - - - name: Install dependencies - run: dotnet restore - - - name: Build - run: dotnet build --configuration Release --no-restore - - - name: Test - run: dotnet test --no-restore --verbosity normal - - - name: Build native library - run: | - cd src/D2Sharp/d2wrapper - go build -buildmode=c-shared -o d2wrapper${{ runner.os == 'Windows' && '.dll' || runner.os == 'macOS' && '.dylib' || '.so' }} . - - - name: Upload D2Sharp build artifact - uses: actions/upload-artifact@v3 - with: - name: d2net-${{ matrix.os }} - path: src/D2Sharp/bin/Release/net8.0/D2Sharp.* - - - name: Upload native library - uses: actions/upload-artifact@v3 - with: - name: d2wrapper-${{ matrix.os }} - path: src/D2Sharp/d2wrapper/d2wrapper* - - - name: Upload build logs on failure - if: failure() - uses: actions/upload-artifact@v3 - with: - name: build-logs-${{ matrix.os }} - path: | - **/*.log - **/*.trx + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Setup Go + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + - name: Cache NuGet packages + uses: actions/cache@v3 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} + restore-keys: | + ${{ runner.os }}-nuget- + - name: Install GCC (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: sudo apt-get update && sudo apt-get install -y gcc + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore + - name: Build native library + run: | + cd src/D2Sharp/d2wrapper + go build -buildmode=c-shared -o d2wrapper${{ runner.os == 'Windows' && '.dll' || runner.os == 'macOS' && '.dylib' || '.so' }} . + - name: Upload D2Sharp build artifact + uses: actions/upload-artifact@v3 + with: + name: d2net-${{ matrix.os }} + path: src/D2Sharp/bin/Release/net8.0/D2Sharp.* + - name: Upload native library + uses: actions/upload-artifact@v3 + with: + name: d2wrapper-${{ matrix.os }} + path: src/D2Sharp/d2wrapper/d2wrapper* package: needs: build runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.VERSION }} steps: - - uses: actions/checkout@v3 - - - name: Setup .NET - uses: actions/setup-dotnet@v3 - with: - dotnet-version: ${{ env.DOTNET_VERSION }} - - - name: Download artifacts - uses: actions/download-artifact@v3 - with: - path: artifacts - - - name: Prepare files for packaging - run: | - mkdir -p package/lib/net8.0 - mkdir -p package/runtimes/win-x64/native - mkdir -p package/runtimes/linux-x64/native - mkdir -p package/runtimes/osx-x64/native - - cp artifacts/d2net-ubuntu-latest/D2Sharp.dll package/lib/net8.0/ - cp artifacts/d2wrapper-windows-latest/d2wrapper.dll package/runtimes/win-x64/native/ - cp artifacts/d2wrapper-ubuntu-latest/d2wrapper.so package/runtimes/linux-x64/native/ - cp artifacts/d2wrapper-macos-latest/d2wrapper.dylib package/runtimes/osx-x64/native/ - - - name: Get version - id: get_version - run: | - VERSION=$(grep -oP '(?<=).*(?=)' src/D2Sharp/D2Sharp.csproj) - SUFFIX=$(grep -oP '(?<=).*(?=)' src/D2Sharp/D2Sharp.csproj) - if [ ! -z "$SUFFIX" ]; then - VERSION="$VERSION-$SUFFIX" - fi - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - - name: Create nuspec file - run: | - cat << EOF > D2Sharp.nuspec - - - - D2Sharp - ${{ steps.get_version.outputs.VERSION }} - Alrik Olson - A .NET wrapper for the D2 library - https://github.com/AlrikOlson/D2Sharp - - d2 diagram visualization - README.nuget.md - - - - - - - - - - - - - EOF - - - name: Pack NuGet package - run: nuget pack D2Sharp.nuspec -BasePath package - - - name: Upload NuGet package - uses: actions/upload-artifact@v3 - with: - name: nuget-package - path: ./*.nupkg + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + path: artifacts + - name: Prepare files for packaging + run: | + mkdir -p package/lib/net8.0 + mkdir -p package/runtimes/win-x64/native + mkdir -p package/runtimes/linux-x64/native + mkdir -p package/runtimes/osx-x64/native + + cp artifacts/d2net-ubuntu-latest/D2Sharp.dll package/lib/net8.0/ + cp artifacts/d2wrapper-windows-latest/d2wrapper.dll package/runtimes/win-x64/native/ + cp artifacts/d2wrapper-ubuntu-latest/d2wrapper.so package/runtimes/linux-x64/native/ + cp artifacts/d2wrapper-macos-latest/d2wrapper.dylib package/runtimes/osx-x64/native/ + - name: Get version + id: get_version + run: | + VERSION=$(grep -oP '(?<=).*(?=)' src/D2Sharp/D2Sharp.csproj) + SUFFIX=$(grep -oP '(?<=).*(?=)' src/D2Sharp/D2Sharp.csproj) + if [ ! -z "$SUFFIX" ]; then + VERSION="$VERSION-$SUFFIX" + fi + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + - name: Create nuspec file + run: | + cat << EOF > D2Sharp.nuspec + + + + D2Sharp + ${{ steps.get_version.outputs.VERSION }} + Alrik Olson + A .NET wrapper for the D2 library + https://github.com/AlrikOlson/D2Sharp + + d2 diagram visualization + README.nuget.md + + + + + + + + + + + + + EOF + - name: Pack NuGet package + run: nuget pack D2Sharp.nuspec -BasePath package + - name: Upload NuGet package + uses: actions/upload-artifact@v3 + with: + name: nuget-package + path: ./*.nupkg release: needs: package runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' steps: - - uses: actions/checkout@v3 - - - name: Download NuGet package - uses: actions/download-artifact@v3 - with: - name: nuget-package - - - name: Get version - id: get_version - run: | - VERSION=$(grep -oP '(?<=).*(?=)' src/D2Sharp/D2Sharp.csproj) - SUFFIX=$(grep -oP '(?<=).*(?=)' src/D2Sharp/D2Sharp.csproj) - if [ ! -z "$SUFFIX" ]; then - VERSION="$VERSION-$SUFFIX" - fi - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: v${{ steps.get_version.outputs.VERSION }} - release_name: Release ${{ steps.get_version.outputs.VERSION }} - draft: false - prerelease: true - - - name: Upload Release Asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./${{ env.NUGET_PACKAGE_NAME }}.${{ steps.get_version.outputs.VERSION }}.nupkg - asset_name: ${{ env.NUGET_PACKAGE_NAME }}.${{ steps.get_version.outputs.VERSION }}.nupkg - asset_content_type: application/octet-stream - - - name: Publish to NuGet - run: dotnet nuget push ./*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Download NuGet package + uses: actions/download-artifact@v3 + with: + name: nuget-package + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Semantic Release + uses: cycjimmy/semantic-release-action@v3 + id: semantic + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + extra_plugins: | + @semantic-release/git + @semantic-release/changelog + @semantic-release/exec + - name: Create Release + if: steps.semantic.outputs.new_release_published == 'true' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create v${{ steps.semantic.outputs.new_release_version }} \ + --title "Release ${{ steps.semantic.outputs.new_release_version }}" \ + --notes "$(cat CHANGELOG.md)" \ + *.nupkg + - name: Publish to NuGet + if: steps.semantic.outputs.new_release_published == 'true' + run: dotnet nuget push ./*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json + + deploy-docs: + needs: release + runs-on: ubuntu-latest + if: needs.release.result == 'success' + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Generate docs + run: dotnet tool install -g docfx && docfx docs/docfx.json + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: docs/_site diff --git a/.releaserc.json b/.releaserc.json new file mode 100644 index 0000000..51fa60a --- /dev/null +++ b/.releaserc.json @@ -0,0 +1,17 @@ +{ + "branches": ["main"], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/changelog", + ["@semantic-release/exec", { + "prepareCmd": "sed -i 's/.*<\\/Version>/${nextRelease.version}<\\/Version>/' src/D2Sharp/D2Sharp.csproj" + }], + ["@semantic-release/git", { + "assets": ["CHANGELOG.md", "src/D2Sharp/D2Sharp.csproj"], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + }], + "@semantic-release/github" + ] + } + \ No newline at end of file diff --git a/docs/docfx.json b/docs/docfx.json new file mode 100644 index 0000000..61db027 --- /dev/null +++ b/docs/docfx.json @@ -0,0 +1,69 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "src/D2Sharp/**.csproj" + ], + "exclude": [ + "**/bin/**", + "**/obj/**" + ] + } + ], + "dest": "api", + "disableGitFeatures": false, + "disableDefaultFilter": false + } + ], + "build": { + "content": [ + { + "files": [ + "api/**.yml", + "api/index.md" + ] + }, + { + "files": [ + "articles/**.md", + "articles/**/toc.yml", + "toc.yml", + "*.md" + ] + } + ], + "resource": [ + { + "files": [ + "images/**" + ] + } + ], + "overwrite": [ + { + "files": [ + "apidoc/**.md" + ], + "exclude": [ + "obj/**", + "_site/**" + ] + } + ], + "dest": "_site", + "globalMetadataFiles": [], + "fileMetadataFiles": [], + "template": [ + "default" + ], + "postProcessors": [], + "markdownEngineName": "markdig", + "noLangKeyword": false, + "keepFileLink": false, + "cleanupCacheHistory": false, + "disableGitFeatures": false + } + } + \ No newline at end of file diff --git a/src/D2Sharp/D2Wrapper.cs b/src/D2Sharp/D2Wrapper.cs index 1a6ce0c..97ceb5d 100644 --- a/src/D2Sharp/D2Wrapper.cs +++ b/src/D2Sharp/D2Wrapper.cs @@ -1,4 +1,4 @@ -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions;