Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
name: CI/CD

on:
push:
branches: [ main ]
tags: [ 'v*.*.*' ]
pull_request:
branches: [ main ]
workflow_dispatch:

jobs:
build-and-test:
name: Build and Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest]
permissions:
contents: read
pull-requests: write # needed for sticky-pull-request-comment

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for SourceLink

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
10.0.x

# Windows: restore full solution (includes Windows-only CDT.Viz)
- name: Restore dependencies
if: runner.os == 'Windows'
run: dotnet restore

# Linux: restore only cross-platform projects (CDT.Viz targets Windows only)
- name: Restore dependencies
if: runner.os == 'Linux'
run: |
dotnet restore src/CDT.Core/CDT.Core.csproj
dotnet restore test/CDT.Tests/CDT.Tests.csproj

# Windows: build full solution
- name: Build
if: runner.os == 'Windows'
run: dotnet build --no-restore -c Release

# Linux: build only cross-platform projects
- name: Build
if: runner.os == 'Linux'
run: |
dotnet build --no-restore -c Release src/CDT.Core/CDT.Core.csproj
dotnet build --no-restore -c Release test/CDT.Tests/CDT.Tests.csproj

# Windows: test full solution
- name: Test
if: runner.os == 'Windows'
run: dotnet test --no-build -c Release --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=${{ github.workspace }}/coverage/coverage.cobertura.xml

# Linux: test only CDT.Tests (CDT.Viz has no tests; benchmark is not a test project)
- name: Test
if: runner.os == 'Linux'
run: dotnet test --no-build -c Release --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=${{ github.workspace }}/coverage/coverage.cobertura.xml test/CDT.Tests/CDT.Tests.csproj

- name: Generate coverage report
uses: danielpalme/ReportGenerator-GitHub-Action@5
with:
reports: ${{ github.workspace }}/coverage/coverage.cobertura.xml
targetdir: coveragereport
reporttypes: MarkdownSummaryGithub

- name: Write coverage to job summary (Windows)
if: runner.os == 'Windows'
run: Get-Content coveragereport/SummaryGithub.md >> $env:GITHUB_STEP_SUMMARY
shell: pwsh

- name: Add coverage PR comment
uses: marocchino/sticky-pull-request-comment@v2
if: runner.os == 'Windows' && github.event_name == 'pull_request'
with:
recreate: true
path: coveragereport/SummaryGithub.md

- name: Write coverage to job summary (Linux)
if: runner.os == 'Linux'
run: cat coveragereport/SummaryGithub.md >> $GITHUB_STEP_SUMMARY

publish:
name: Publish to NuGet
needs: build-and-test
runs-on: windows-latest
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for SourceLink

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
10.0.x

- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet build --no-restore -c Release

- name: Pack
run: dotnet pack src/CDT.Core/CDT.Core.csproj --no-build -c Release -o ./artifacts

- name: Push to NuGet.org
# Requires a NUGET_API_KEY secret configured in:
# GitHub → Repository Settings → Secrets and variables → Actions → New repository secret
run: dotnet nuget push ./artifacts/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
114 changes: 114 additions & 0 deletions .github/workflows/upstream-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: Upstream Sync

on:
schedule:
# Run daily at 06:00 UTC
- cron: '0 6 * * *'
workflow_dispatch:

jobs:
check-upstream:
name: Check for upstream changes
runs-on: ubuntu-latest
permissions:
contents: write # needed to update .last-sync-commit on main
issues: write # needed to create the issue that triggers Copilot

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main

- name: Get last synced commit
id: last-sync
run: echo "sha=$(cat .last-sync-commit | tr -d '[:space:]')" >> "$GITHUB_OUTPUT"

- name: Get latest upstream commit
id: upstream
run: |
# git ls-remote reads public repos without any auth or API calls
LATEST=$(git ls-remote https://github.com/artem-ogre/CDT.git refs/heads/master | cut -f1)
if [ -z "$LATEST" ]; then
echo "::error::Could not resolve latest upstream commit SHA"
exit 1
fi
echo "sha=$LATEST" >> "$GITHUB_OUTPUT"
echo "Latest upstream commit: $LATEST"

- name: Create Copilot porting issue
if: steps.last-sync.outputs.sha != steps.upstream.outputs.sha
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
LAST="${{ steps.last-sync.outputs.sha }}"
LATEST="${{ steps.upstream.outputs.sha }}"
DATE=$(date -u +"%Y-%m-%d")

echo "Upstream has new commits since ${LAST:0:7} (latest: ${LATEST:0:7})"

# Shallow-clone the upstream history (metadata only) to build a commit list
git clone --depth 50 --no-checkout https://github.com/artem-ogre/CDT.git /tmp/CDT-upstream
COMMITS=$(git -C /tmp/CDT-upstream log \
--pretty=format:"- [%h](https://github.com/artem-ogre/CDT/commit/%H) %s" \
"${LAST}..${LATEST}" 2>/dev/null || echo "- (see compare link below)")
[ -z "$COMMITS" ] && COMMITS="- (see compare link below)"

# Update .last-sync-commit on main so we don't re-open the issue next run
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
echo "$LATEST" > .last-sync-commit
git add .last-sync-commit
git commit -m "chore: advance upstream sync marker to ${LATEST:0:7}"
git push origin main

# Ensure the auto-sync label exists
gh label create "auto-sync" \
--description "Automatically generated upstream sync issue" \
--color "0075ca" 2>/dev/null || true

# Create an issue assigned to the Copilot coding agent.
# Assigning to @Copilot triggers the coding agent to pick it up
# and create a PR with the ported C# changes.
ISSUE_BODY=$(cat <<'EOF'
## Upstream Sync Task

@Copilot please port the upstream changes listed below to C# and open a pull request.

New commits have been pushed to [artem-ogre/CDT](https://github.com/artem-ogre/CDT) since the last sync.

**Previous synced commit:** [`LAST_SHA`](https://github.com/artem-ogre/CDT/commit/LAST_FULL)
**New upstream commit:** [`LATEST_SHA`](https://github.com/artem-ogre/CDT/commit/LATEST_FULL)
**Full diff:** https://github.com/artem-ogre/CDT/compare/LAST_FULL...LATEST_FULL

### Upstream commits to port

COMMIT_LIST

### What to port

Please port all upstream C++ changes to C# and open a pull request.

Key files to check in the upstream diff:
- `CDT/include/CDT.h` and `CDT/include/CDT.hpp` → port any algorithm changes to `src/CDT.Core/`
- `CDT/include/Predicates.h` → port to `src/CDT.Core/Predicates.cs`
- `CDT/include/KDTree.h` → port to `src/CDT.Core/KdTree.cs`
- Any new types or utilities → port to `src/CDT.Core/Types.cs` or new files as appropriate

After porting:
1. Run `dotnet test` and ensure all tests pass
2. Update test inputs/expected outputs if needed
EOF
)
# Replace placeholders with actual values
ISSUE_BODY="${ISSUE_BODY//LAST_SHA/${LAST:0:7}}"
ISSUE_BODY="${ISSUE_BODY//LAST_FULL/${LAST}}"
ISSUE_BODY="${ISSUE_BODY//LATEST_SHA/${LATEST:0:7}}"
ISSUE_BODY="${ISSUE_BODY//LATEST_FULL/${LATEST}}"
ISSUE_BODY="${ISSUE_BODY//COMMIT_LIST/$COMMITS}"

gh issue create \
--title "Port upstream CDT changes to C# (${LATEST:0:7}) — ${DATE}" \
--label "auto-sync" \
--assignee "Copilot" \
--body "$ISSUE_BODY"
1 change: 1 addition & 0 deletions .last-sync-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7bd85e41a7b2e6e6e3bf82f36bcbc2bcec6441c5
Loading
Loading