Skip to content
Draft
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
115 changes: 115 additions & 0 deletions .github/actions/build-and-test/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Build and Test
description: Builds and tests dotnet-interactive on Windows or Linux

inputs:
build-config:
default: Release
description: 'Build configuration (Release or Debug)'
node-version:
default: '22.22.3'
description: 'Node.js version to use'
npm-version:
default: '11.14.1'
description: 'npm CLI version to install globally'

runs:
using: composite
steps:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v5
with:
global-json-file: global.json

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node-version }}
registry-url: https://registry.npmjs.org/
cache: npm
cache-dependency-path: src/**/package-lock.json

- name: Cache NuGet packages
uses: actions/cache@v5
with:
# CI scripts use a repo-local NuGet cache to keep restore inputs deterministic.
path: ${{ github.workspace }}/.packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json', 'global.json', 'Directory.Packages.props') }}
restore-keys: ${{ runner.os }}-nuget-

- name: Ensure symlinks (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: . "${{ github.workspace }}\src\ensure-symlinks.ps1"

- name: Upgrade npm
shell: pwsh
run: npm install -g npm@${{ inputs.npm-version }}

- name: Copy build resources (Windows)
if: runner.os == 'Windows'
shell: cmd
# robocopy exit codes 0-7 are all success variants; 8+ indicate errors
run: |
robocopy "eng\resources" "${{ github.workspace }}\artifacts" /E
if %errorlevel% leq 7 exit /b 0
exit /b 1

- name: Build (Windows)
if: runner.os == 'Windows'
shell: cmd
run: eng\CIBuild.cmd -configuration ${{ inputs.build-config }} /p:SignType=Test
env:
BUILD_BUILDNUMBER: ${{ github.run_number }}
NUGET_PACKAGES: ${{ github.workspace }}\.packages
POCKETLOGGER_LOG_PATH: ${{ github.workspace }}\artifacts\TestResults\${{ inputs.build-config }}\pocketlogger.test.log

- name: Copy build resources (Linux)
if: runner.os == 'Linux'
shell: bash
run: |
if [[ ! -d eng/resources ]]; then
echo "eng/resources directory not found" >&2; exit 1
fi
mkdir -p artifacts
# Allow empty resources directory, but fail if the directory itself is missing.
shopt -s nullglob
resources=(eng/resources/*)
if (( ${#resources[@]} > 0 )); then
cp -r "${resources[@]}" artifacts/
else
echo "eng/resources is empty; nothing to copy."
fi

- name: Build (Linux)
if: runner.os == 'Linux'
shell: bash
run: ./eng/cibuild.sh --configuration ${{ inputs.build-config }} /p:SignType=Test
env:
BUILD_BUILDNUMBER: ${{ github.run_number }}
NUGET_PACKAGES: ${{ github.workspace }}/.packages
POCKETLOGGER_LOG_PATH: ${{ github.workspace }}/artifacts/TestResults/${{ inputs.build-config }}/pocketlogger.test.log

- name: Run tests
shell: pwsh
run: ./test-retry-runner.ps1 -buildConfig ${{ inputs.build-config }}
env:
DisableArcade: '1'
POCKETLOGGER_LOG_PATH: ${{ github.workspace }}/artifacts/TestResults/${{ inputs.build-config }}/pocketlogger.test.log

- name: Report test results
# Fork PRs get a read-only GITHUB_TOKEN regardless of permissions declarations,
# so dorny/test-reporter cannot create check runs for fork PRs.
if: ${{ !cancelled() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
uses: dorny/test-reporter@v3
with:
name: ${{ runner.os }} Tests
path: artifacts/TestResults/${{ inputs.build-config }}/**/*.trx
reporter: dotnet-trx
fail-on-error: false

- name: Convert failed tests to VS playlist
if: ${{ failure() }}
uses: BenjaminMichaelis/trx-to-vsplaylist@v4
with:
trx-file-path: artifacts/TestResults/${{ inputs.build-config }}/**/*.trx
artifact-name: ${{ runner.os }}-failed-tests
37 changes: 37 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: 2
updates:
# Keep GitHub Actions up to date in workflows and composite actions
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
groups:
github-actions:
patterns:
- '*'
labels:
- dependencies

# Keep npm packages up to date
- package-ecosystem: npm
directories:
- /src/polyglot-notebooks
- /src/polyglot-notebooks-ui-components
- /src/polyglot-notebooks-vscode
- /src/polyglot-notebooks-vscode-insiders
- /src/polyglot-notebooks-browser
schedule:
interval: weekly
day: monday
labels:
- dependencies

# Keep NuGet packages up to date
- package-ecosystem: nuget
directory: /
schedule:
interval: weekly
day: monday
labels:
- dependencies
158 changes: 158 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
name: CI

on:
push:
branches:
- main
- 'feature/**'
- 'hotfix/**'
- 'release/**'
# NOTE: paths-ignore is duplicated under push and pull_request because
# GitHub Actions does not support YAML anchors. Keep both lists in sync.
paths-ignore:
- '**/*.md'
- '.config/**'
- '.devcontainer/**'
- '.vscode/**'
- 'assets/**'
- 'docs/**'
- 'images/**'
- '.editorconfig'
- '.gitignore'
- '*.txt'
- '*.github-issues'
pull_request:
branches:
- main
- 'feature/**'
- 'hotfix/**'
- 'release/**'
paths-ignore:
- '**/*.md'
- '.config/**'
- '.devcontainer/**'
- '.vscode/**'
- 'assets/**'
- 'docs/**'
- 'images/**'
- '.editorconfig'
- '.gitignore'
- '*.txt'
- '*.github-issues'
workflow_dispatch:
schedule:
- cron: '0 8 * * Mon'
- cron: '0 8 * * Wed'

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

permissions:
contents: read

env:
NPM_CONFIG_REGISTRY: https://registry.npmjs.org/
DOTNET_INTERACTIVE_FRONTEND_NAME: CI
DOTNET_INTERACTIVE_SIGN_TYPE: Test

jobs:
build:
strategy:
fail-fast: false
matrix:
runner: [windows-latest, ubuntu-latest]
runs-on: ${{ matrix.runner }}
timeout-minutes: 200
permissions:
contents: read
checks: write # required by dorny/test-reporter (inside composite action)
steps:
# core.symlinks must be configured before checkout so git materialises
# symlinks as real reparse points on Windows. ensure-symlinks.ps1 also
# recreates them explicitly as a belt-and-suspenders measure.
- name: Configure git symlinks and long paths (Windows)
if: runner.os == 'Windows'
run: |
git config --global core.symlinks true
git config --global core.longpaths true
shell: pwsh

- uses: actions/checkout@v6

- uses: ./.github/actions/build-and-test

- name: Extract package version (Windows)
if: runner.os == 'Windows'
id: version
shell: pwsh
run: |
$packagePattern = '^Microsoft\.dotnet-interactive\.(?<version>\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)\.nupkg$'
$packages = @(Get-ChildItem artifacts\packages\Release\Shipping\Microsoft.dotnet-interactive.*.nupkg -File -ErrorAction SilentlyContinue |
Where-Object { $_.Name -notlike '*.symbols.nupkg' -and $_.Name -match $packagePattern })
if ($packages.Count -eq 0) {
Write-Error "No bare Microsoft.dotnet-interactive package with a SemVer filename found"
exit 1
}
if ($packages.Count -gt 1) {
Write-Error "Multiple bare Microsoft.dotnet-interactive packages found: $($packages.Name -join ', ')"
exit 1
}
$match = [regex]::Match($packages[0].Name, $packagePattern)
if (-not $match.Success) {
Write-Error "Package filename '$($packages[0].Name)' did not match expected SemVer pattern"
exit 1
}
$ver = $match.Groups['version'].Value
Write-Host "Detected version: $ver"
echo "version=$ver" >> $env:GITHUB_OUTPUT

- name: Pack VSCode extensions (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
${{ github.workspace }}\eng\package\PackVSCodeExtension.ps1 `
-stableToolVersionNumber '${{ steps.version.outputs.version }}' `
-outDir '${{ runner.temp }}\staging\vscode'
working-directory: src

- name: Pack NPM package (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
${{ github.workspace }}\eng\package\PackNpmPackage.ps1 `
-packageVersionNumber '${{ steps.version.outputs.version }}' `
-outDir '${{ runner.temp }}\staging\npm'
working-directory: src/polyglot-notebooks

- name: Upload packages (Windows)
uses: actions/upload-artifact@v7
if: always() && runner.os == 'Windows'
with:
name: Windows-packages
path: artifacts/packages/Release/Shipping
retention-days: 30

- name: Upload VSCode packages (Windows)
uses: actions/upload-artifact@v7
if: always() && runner.os == 'Windows'
with:
name: Windows-vscode
path: '${{ runner.temp }}\staging\vscode'
retention-days: 30

- name: Upload NPM package (Windows)
uses: actions/upload-artifact@v7
if: always() && runner.os == 'Windows'
with:
name: Windows-npm
path: '${{ runner.temp }}\staging\npm'
retention-days: 30

- name: Upload test results
uses: actions/upload-artifact@v7
if: always()
with:
name: ${{ runner.os }}-test-results
path: artifacts/TestResults/Release
retention-days: 30
Loading