added CI
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
# The check every pull request goes through: the solution builds and the tests pass.
|
||||
#
|
||||
# The runner has to be a Windows one with the .NET 10 SDK: the application is
|
||||
# WPF, so neither the build nor the tests happen anywhere else. The tests raise
|
||||
# real windows and ask Windows for the foreground one, so the runner has to work
|
||||
# in an interactive desktop session — as a service in session 0 the end-to-end
|
||||
# checks have no window to wait for.
|
||||
name: Pull request
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
# A new push into the branch makes the previous run pointless
|
||||
concurrency:
|
||||
group: pull-request-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: pwsh
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-x64
|
||||
|
||||
steps:
|
||||
# lfs: true is not a nicety: the exe icon lives in Git LFS, and without it
|
||||
# the checkout leaves a text pointer that the build cannot read as an icon
|
||||
- name: Check out the sources
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
- name: Show the toolchain
|
||||
run: dotnet --info
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore CursorLang.sln --nologo
|
||||
|
||||
- name: Build
|
||||
run: dotnet build CursorLang.sln --configuration Release --no-restore --nologo
|
||||
|
||||
# The tests take the application from bin\Release, which is why the whole
|
||||
# run is a Release one: in Debug they would find no executable and skip
|
||||
# themselves — a green run that checked nothing
|
||||
- name: Test
|
||||
run: >
|
||||
dotnet test CursorLang.sln
|
||||
--configuration Release
|
||||
--no-build
|
||||
--nologo
|
||||
--settings CursorLang.Tests/coverage.runsettings
|
||||
@@ -0,0 +1,133 @@
|
||||
# The release: a tag of the form v1.2.3.0 builds the solution, runs the tests
|
||||
# and packs the MSIX with the version taken from the tag.
|
||||
#
|
||||
# The same requirements to the runner as in pull-request.yml apply: Windows, the
|
||||
# .NET 10 SDK and an interactive desktop session for the tests. makeappx comes
|
||||
# with a NuGet package (Packaging\Tools\SdkTools.csproj), so the Windows SDK does
|
||||
# not have to be installed.
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: pwsh
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: windows-x64
|
||||
|
||||
steps:
|
||||
# lfs: true is not a nicety: the exe icon and the MSIX logos live in Git
|
||||
# LFS, and without it the checkout leaves text pointers in their place —
|
||||
# the build fails on the icon and the package would carry broken logos
|
||||
- name: Check out the sources
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
# The tag is the only place the version comes from: the Store takes four
|
||||
# numbers ending in zero, so anything else is stopped here rather than
|
||||
# halfway through the packaging
|
||||
- name: Read the version from the tag
|
||||
id: version
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$tag = '${{ github.ref_name }}'
|
||||
|
||||
if ($tag -notmatch '^v\d+\.\d+\.\d+\.0$') {
|
||||
throw "The tag '$tag' does not fit: a release is tagged as v1.2.3.0 — four numbers ending in zero."
|
||||
}
|
||||
|
||||
"version=$($tag.Substring(1))" | Out-File $env:GITHUB_OUTPUT -Append -Encoding utf8
|
||||
|
||||
- name: Show the toolchain
|
||||
run: dotnet --info
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore CursorLang.sln --nologo
|
||||
|
||||
- name: Build
|
||||
run: dotnet build CursorLang.sln --configuration Release --no-restore --nologo
|
||||
|
||||
- name: Test
|
||||
run: >
|
||||
dotnet test CursorLang.sln
|
||||
--configuration Release
|
||||
--no-build
|
||||
--nologo
|
||||
--settings CursorLang.Tests/coverage.runsettings
|
||||
|
||||
# The package comes out as Partner Center wants it — the Store puts its own
|
||||
# signature on it. The identity comes from repository variables and falls
|
||||
# back to the defaults of the script when a variable is not set.
|
||||
- name: Pack the MSIX
|
||||
env:
|
||||
IDENTITY_NAME: ${{ vars.MSIX_IDENTITY_NAME }}
|
||||
PUBLISHER: ${{ vars.MSIX_PUBLISHER }}
|
||||
PUBLISHER_DISPLAY_NAME: ${{ vars.MSIX_PUBLISHER_DISPLAY_NAME }}
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$arguments = @{ Version = '${{ steps.version.outputs.version }}' }
|
||||
|
||||
# An empty variable is left out rather than passed on: the script has
|
||||
# defaults of its own, and an empty string would wipe them
|
||||
$variables = @{
|
||||
IdentityName = $env:IDENTITY_NAME
|
||||
Publisher = $env:PUBLISHER
|
||||
PublisherDisplayName = $env:PUBLISHER_DISPLAY_NAME
|
||||
}
|
||||
|
||||
foreach ($name in $variables.Keys) {
|
||||
if ($variables[$name]) { $arguments[$name] = $variables[$name] }
|
||||
}
|
||||
|
||||
./Packaging/build-msix.ps1 @arguments
|
||||
|
||||
- name: Keep the packages
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: msix-${{ steps.version.outputs.version }}
|
||||
path: artifacts/packages/
|
||||
if-no-files-found: error
|
||||
|
||||
# Gitea creates a release of its own for a pushed tag, so the release is
|
||||
# looked up first and only made when it is not there
|
||||
- name: Publish the release
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# The GITHUB_ names are what Gitea itself hands to the workflow — its
|
||||
# actions repeat those of GitHub, and the addresses in them point at
|
||||
# this Gitea instance. GITHUB_API_URL used not to reach the steps at
|
||||
# all, so the address is put together from the server one when empty
|
||||
$root = if ($env:GITHUB_API_URL) { $env:GITHUB_API_URL } else { "$env:GITHUB_SERVER_URL/api/v1" }
|
||||
$api = "$root/repos/$env:GITHUB_REPOSITORY/releases"
|
||||
$headers = @{ Authorization = "token $env:GITEA_TOKEN" }
|
||||
|
||||
$release = $null
|
||||
try { $release = Invoke-RestMethod "$api/tags/$env:TAG" -Headers $headers } catch { }
|
||||
|
||||
if (-not $release) {
|
||||
$body = @{ tag_name = $env:TAG; name = $env:TAG; draft = $false; prerelease = $false } | ConvertTo-Json
|
||||
$release = Invoke-RestMethod $api -Method Post -Headers $headers -ContentType 'application/json' -Body $body
|
||||
}
|
||||
|
||||
foreach ($file in Get-ChildItem artifacts/packages -File) {
|
||||
# A tag can be pushed again after it was deleted; the old file of
|
||||
# the same name is dropped, otherwise the upload is refused
|
||||
$existing = $release.assets | Where-Object { $_.name -eq $file.Name }
|
||||
foreach ($asset in $existing) {
|
||||
Invoke-RestMethod "$api/$($release.id)/assets/$($asset.id)" -Method Delete -Headers $headers | Out-Null
|
||||
}
|
||||
|
||||
Write-Host "Uploading $($file.Name)"
|
||||
Invoke-RestMethod "$api/$($release.id)/assets?name=$($file.Name)" -Method Post -Headers $headers -Form @{ attachment = $file } | Out-Null
|
||||
}
|
||||
@@ -4,6 +4,21 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CursorLang", "CursorLang\Cu
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CursorLang.Tests", "CursorLang.Tests\CursorLang.Tests.csproj", "{558F7646-AC3F-4E5E-853D-9F2A09E89C06}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Packaging", "Packaging", "{E927F87B-A585-A586-52B2-1371051E189F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Packaging\AppxManifest.xml = Packaging\AppxManifest.xml
|
||||
Packaging\build-msix.ps1 = Packaging\build-msix.ps1
|
||||
Packaging\New-Assets.ps1 = Packaging\New-Assets.ps1
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CI", "CI", "{3F1B9C24-7A0E-4C55-9E2D-6B41A8D5E713}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.gitea\workflows\pull-request.yml = .gitea\workflows\pull-request.yml
|
||||
.gitea\workflows\release.yml = .gitea\workflows\release.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SdkTools", "Packaging\Tools\SdkTools.csproj", "{788339D3-F0C3-4F1A-9216-501814C7BF78}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -38,8 +53,17 @@ Global
|
||||
{558F7646-AC3F-4E5E-853D-9F2A09E89C06}.Release|x64.Build.0 = Release|Any CPU
|
||||
{558F7646-AC3F-4E5E-853D-9F2A09E89C06}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{558F7646-AC3F-4E5E-853D-9F2A09E89C06}.Release|x86.Build.0 = Release|Any CPU
|
||||
{788339D3-F0C3-4F1A-9216-501814C7BF78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{788339D3-F0C3-4F1A-9216-501814C7BF78}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{788339D3-F0C3-4F1A-9216-501814C7BF78}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{788339D3-F0C3-4F1A-9216-501814C7BF78}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{788339D3-F0C3-4F1A-9216-501814C7BF78}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{788339D3-F0C3-4F1A-9216-501814C7BF78}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{788339D3-F0C3-4F1A-9216-501814C7BF78} = {E927F87B-A585-A586-52B2-1371051E189F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Reference in New Issue
Block a user