mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-07 14:50:55 +00:00
Compare commits
167 Commits
dev/lhecke
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11cf895e17 | ||
|
|
086c388147 | ||
|
|
1cd877932b | ||
|
|
48db06ea81 | ||
|
|
ec0b257c1e | ||
|
|
ce2a9aca38 | ||
|
|
63addccfb0 | ||
|
|
a6ce08a4cf | ||
|
|
aced0fdabe | ||
|
|
ffaff175b4 | ||
|
|
50adbcab54 | ||
|
|
bf72b707bc | ||
|
|
afd3d9802e | ||
|
|
5a1b737efe | ||
|
|
005af47054 | ||
|
|
c3bdf74538 | ||
|
|
293105d885 | ||
|
|
a2a86239ed | ||
|
|
a0619c4e49 | ||
|
|
4997c518af | ||
|
|
54950185f2 | ||
|
|
4247381bd2 | ||
|
|
78294b30d6 | ||
|
|
18c6d2722a | ||
|
|
3edbcf9331 | ||
|
|
ef81022c17 | ||
|
|
2778cdd1e9 | ||
|
|
369b7fa36b | ||
|
|
6ea4ce6b07 | ||
|
|
bb06648d32 | ||
|
|
280be8286e | ||
|
|
20c1d563fc | ||
|
|
770af0ae1b | ||
|
|
5ce63b923b | ||
|
|
4b71d7b470 | ||
|
|
73244461cc | ||
|
|
d056f22219 | ||
|
|
e9074fe138 | ||
|
|
8b9f807391 | ||
|
|
e967ad772d | ||
|
|
4977fc9883 | ||
|
|
3ec5fe4eee | ||
|
|
752df35cf5 | ||
|
|
526704b725 | ||
|
|
8108f22262 | ||
|
|
9e3cc9d379 | ||
|
|
0db21e8904 | ||
|
|
b4fcf28b92 | ||
|
|
8a4def793f | ||
|
|
95636b976d | ||
|
|
5ca7991ded | ||
|
|
31dc6d80c5 | ||
|
|
9ba0636590 | ||
|
|
57264e0b2a | ||
|
|
f4da9c0e98 | ||
|
|
4d4111b9ed | ||
|
|
5d1ecce97c | ||
|
|
dd02ef0666 | ||
|
|
cd28ed7a4a | ||
|
|
a1882ce852 | ||
|
|
d48870c49b | ||
|
|
0eafd10e3d | ||
|
|
436c037021 | ||
|
|
99ac5f632f | ||
|
|
55f7bec9d1 | ||
|
|
9c9e8ecc91 | ||
|
|
65324d6049 | ||
|
|
87333f79ed | ||
|
|
30419b99df | ||
|
|
c16e5d99cc | ||
|
|
9523d6ad20 | ||
|
|
799d48ffea | ||
|
|
acd32f252d | ||
|
|
9b4fbff1a2 | ||
|
|
d6d35610bc | ||
|
|
31ae78d1bc | ||
|
|
d8c8e780b6 | ||
|
|
a33fdcfd75 | ||
|
|
31aa23f717 | ||
|
|
9670230925 | ||
|
|
c9a4ab7624 | ||
|
|
986ced95c1 | ||
|
|
0631bf5bd7 | ||
|
|
0e2b3e6079 | ||
|
|
6edaa15d4c | ||
|
|
dd9e0148c2 | ||
|
|
f0b09421da | ||
|
|
7083738146 | ||
|
|
80c529aced | ||
|
|
ab79a85381 | ||
|
|
b9089d9d1d | ||
|
|
272e7b0905 | ||
|
|
7326eaaa6f | ||
|
|
72be9a95af | ||
|
|
596d0c5155 | ||
|
|
79eb9b3d3c | ||
|
|
eab1c239a9 | ||
|
|
96a9dd5209 | ||
|
|
6278a2d9bf | ||
|
|
16fe2e5905 | ||
|
|
f2b82cd054 | ||
|
|
7813953b23 | ||
|
|
47f38e31a1 | ||
|
|
0fe0868f98 | ||
|
|
179bb9bded | ||
|
|
90485e4c79 | ||
|
|
29ef49252b | ||
|
|
5614116c6e | ||
|
|
a1865b9cf7 | ||
|
|
c79298d3fd | ||
|
|
8e041692b3 | ||
|
|
4c7879bfb5 | ||
|
|
f3439e201e | ||
|
|
d3264964a9 | ||
|
|
dd2736f334 | ||
|
|
020746d93d | ||
|
|
dc6d82e9bc | ||
|
|
239b4d16b9 | ||
|
|
fb485a2b40 | ||
|
|
45a36cf83a | ||
|
|
09273be1c8 | ||
|
|
f1090a07f5 | ||
|
|
b7e537e5e7 | ||
|
|
7b9ec0ed6a | ||
|
|
06baead9ea | ||
|
|
21a62c5fef | ||
|
|
2d66dc44f5 | ||
|
|
547349af77 | ||
|
|
7ab0e982c7 | ||
|
|
165d3edde9 | ||
|
|
a3c7bc3349 | ||
|
|
772ed3a7b7 | ||
|
|
dbc27ab041 | ||
|
|
286fdfea79 | ||
|
|
decbc0f5a4 | ||
|
|
f9a36f1ff7 | ||
|
|
6a763bcd41 | ||
|
|
69728632eb | ||
|
|
3a122bf420 | ||
|
|
28d28cb469 | ||
|
|
274bbf0e44 | ||
|
|
68cce101bc | ||
|
|
58ce22d484 | ||
|
|
2668273616 | ||
|
|
a5f9c85c39 | ||
|
|
84bb98bc81 | ||
|
|
4d27a05318 | ||
|
|
86aa666903 | ||
|
|
031271f824 | ||
|
|
a5c5b8a50e | ||
|
|
c5d417fcaf | ||
|
|
b9c3b5cd1e | ||
|
|
79c47f64a2 | ||
|
|
c0e4689e77 | ||
|
|
da2b80bc0a | ||
|
|
32bf894f14 | ||
|
|
b89c8ced22 | ||
|
|
4d9a266c12 | ||
|
|
391abafc2e | ||
|
|
3c78e01ab5 | ||
|
|
4bbe3a388c | ||
|
|
62ffa4ba41 | ||
|
|
37aa29545b | ||
|
|
52cc523ed2 | ||
|
|
0eff8c06e3 | ||
|
|
437914807a | ||
|
|
d1fbbb8a83 |
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,20 +1,14 @@
|
||||
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
|
||||
## Summary of the Pull Request
|
||||
|
||||
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
|
||||
## References
|
||||
## References and Relevant Issues
|
||||
|
||||
<!-- Please review the items on the PR checklist before submitting-->
|
||||
## PR Checklist
|
||||
* [ ] Closes #xxx
|
||||
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
|
||||
* [ ] Tests added/passed
|
||||
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
|
||||
* [ ] Schema updated.
|
||||
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
|
||||
|
||||
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
|
||||
## Detailed Description of the Pull Request / Additional comments
|
||||
|
||||
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
|
||||
## Validation Steps Performed
|
||||
|
||||
## PR Checklist
|
||||
- [ ] Closes #xxx
|
||||
- [ ] Tests added/passed
|
||||
- [ ] Documentation updated
|
||||
- If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
|
||||
- [ ] Schema updated (if necessary)
|
||||
|
||||
8
.github/actions/spelling/allow/allow.txt
vendored
8
.github/actions/spelling/allow/allow.txt
vendored
@@ -2,6 +2,7 @@ admins
|
||||
allcolors
|
||||
Apc
|
||||
apc
|
||||
backpressure
|
||||
breadcrumb
|
||||
breadcrumbs
|
||||
bsd
|
||||
@@ -12,18 +13,23 @@ clickable
|
||||
clig
|
||||
CMMI
|
||||
copyable
|
||||
CtrlDToClose
|
||||
cybersecurity
|
||||
dalet
|
||||
Dcs
|
||||
dcs
|
||||
deselection
|
||||
dialytika
|
||||
diffing
|
||||
dje
|
||||
downside
|
||||
downsides
|
||||
dze
|
||||
dzhe
|
||||
DTo
|
||||
EDDB
|
||||
EDDC
|
||||
Emacspeak
|
||||
Enum'd
|
||||
Fitt
|
||||
formattings
|
||||
@@ -60,6 +66,7 @@ lol
|
||||
lorem
|
||||
Lorigin
|
||||
maxed
|
||||
megathread
|
||||
minimalistic
|
||||
mkmk
|
||||
mnt
|
||||
@@ -85,6 +92,7 @@ shcha
|
||||
slnt
|
||||
Sos
|
||||
ssh
|
||||
stakeholders
|
||||
timeline
|
||||
timelines
|
||||
timestamped
|
||||
|
||||
9
.github/actions/spelling/allow/apis.txt
vendored
9
.github/actions/spelling/allow/apis.txt
vendored
@@ -29,6 +29,7 @@ Dacl
|
||||
dataobject
|
||||
dcomp
|
||||
DERR
|
||||
delayimp
|
||||
dlldata
|
||||
DNE
|
||||
DONTADDTORECENT
|
||||
@@ -55,6 +56,8 @@ GETMOUSEHOVERTIME
|
||||
Hashtable
|
||||
HIGHCONTRASTON
|
||||
HIGHCONTRASTW
|
||||
hinternet
|
||||
HINTERNET
|
||||
hotkeys
|
||||
href
|
||||
hrgn
|
||||
@@ -74,6 +77,7 @@ IConnection
|
||||
ICustom
|
||||
IDialog
|
||||
IDirect
|
||||
Idn
|
||||
IExplorer
|
||||
IFACEMETHOD
|
||||
IFile
|
||||
@@ -163,6 +167,7 @@ roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
schandle
|
||||
SEH
|
||||
semver
|
||||
serializer
|
||||
SETVERSION
|
||||
@@ -210,10 +215,13 @@ UOI
|
||||
UPDATEINIFILE
|
||||
userenv
|
||||
USEROBJECTFLAGS
|
||||
Vcpp
|
||||
Viewbox
|
||||
virtualalloc
|
||||
wcsstr
|
||||
wcstoui
|
||||
WDJ
|
||||
winhttp
|
||||
winmain
|
||||
winsta
|
||||
winstamin
|
||||
@@ -221,6 +229,7 @@ wmemcmp
|
||||
wpc
|
||||
WSF
|
||||
wsregex
|
||||
WWH
|
||||
wwinmain
|
||||
xchg
|
||||
XDocument
|
||||
|
||||
5
.github/actions/spelling/allow/microsoft.txt
vendored
5
.github/actions/spelling/allow/microsoft.txt
vendored
@@ -33,6 +33,7 @@ libucrtd
|
||||
LKG
|
||||
LOCKFILE
|
||||
Lxss
|
||||
makepri
|
||||
mfcribbon
|
||||
microsoft
|
||||
microsoftonline
|
||||
@@ -50,12 +51,16 @@ pgo
|
||||
pgosweep
|
||||
powerrename
|
||||
powershell
|
||||
priconfig
|
||||
PRIINFO
|
||||
propkey
|
||||
pscustomobject
|
||||
QWORD
|
||||
regedit
|
||||
resfiles
|
||||
robocopy
|
||||
SACLs
|
||||
segoe
|
||||
sdkddkver
|
||||
Shobjidl
|
||||
Skype
|
||||
|
||||
12
.github/actions/spelling/allow/names.txt
vendored
12
.github/actions/spelling/allow/names.txt
vendored
@@ -1,6 +1,6 @@
|
||||
Anup
|
||||
austdi
|
||||
arkthur
|
||||
austdi
|
||||
Ballmer
|
||||
bhoj
|
||||
Bhojwani
|
||||
@@ -23,6 +23,7 @@ Griese
|
||||
Hernan
|
||||
Howett
|
||||
Illhardt
|
||||
Imms
|
||||
iquilezles
|
||||
italo
|
||||
jantari
|
||||
@@ -30,10 +31,11 @@ jerrysh
|
||||
Kaiyu
|
||||
kimwalisch
|
||||
KMehrain
|
||||
KODELIFE
|
||||
Kodelife
|
||||
KODELIFE
|
||||
Kourosh
|
||||
kowalczyk
|
||||
leonardder
|
||||
leonmsft
|
||||
Lepilleur
|
||||
lhecker
|
||||
@@ -59,6 +61,7 @@ oising
|
||||
oldnewthing
|
||||
opengl
|
||||
osgwiki
|
||||
Ottosson
|
||||
pabhojwa
|
||||
panos
|
||||
paulcam
|
||||
@@ -77,15 +80,18 @@ sonpham
|
||||
stakx
|
||||
talo
|
||||
thereses
|
||||
Thysell
|
||||
Walisch
|
||||
WDX
|
||||
Wellons
|
||||
Westerman
|
||||
Wirt
|
||||
Wojciech
|
||||
zadjii
|
||||
Zamor
|
||||
Zamora
|
||||
zamora
|
||||
Zamora
|
||||
zljubisic
|
||||
Zoey
|
||||
zorio
|
||||
Zverovich
|
||||
|
||||
1
.github/actions/spelling/excludes.txt
vendored
1
.github/actions/spelling/excludes.txt
vendored
@@ -111,6 +111,7 @@
|
||||
^src/tools/pixels/pixels\.bat$
|
||||
^src/tools/texttests/fira\.txt$
|
||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||
^src/types/ColorFix.cpp
|
||||
^src/types/ut_types/UtilsTests.cpp$
|
||||
^tools/ReleaseEngineering/ServicingPipeline.ps1$
|
||||
ignore$
|
||||
|
||||
33
.github/actions/spelling/expect/expect.txt
vendored
33
.github/actions/spelling/expect/expect.txt
vendored
@@ -41,6 +41,7 @@ antialiasing
|
||||
ANull
|
||||
anycpu
|
||||
APARTMENTTHREADED
|
||||
APCA
|
||||
APCs
|
||||
APIENTRY
|
||||
apiset
|
||||
@@ -61,7 +62,6 @@ argb
|
||||
ARRAYSIZE
|
||||
ARROWKEYS
|
||||
asan
|
||||
ASBRST
|
||||
ASBSET
|
||||
ASDF
|
||||
asdfghjkl
|
||||
@@ -195,6 +195,8 @@ chk
|
||||
CHT
|
||||
Cic
|
||||
CLA
|
||||
cielab
|
||||
Cielab
|
||||
Clcompile
|
||||
CLE
|
||||
cleartype
|
||||
@@ -219,6 +221,7 @@ cmt
|
||||
cmw
|
||||
cmyk
|
||||
CNL
|
||||
cnn
|
||||
cnt
|
||||
CNTRL
|
||||
Codeflow
|
||||
@@ -252,6 +255,7 @@ conattrs
|
||||
conbufferout
|
||||
concfg
|
||||
conclnt
|
||||
concretizations
|
||||
conddkrefs
|
||||
condrv
|
||||
conechokey
|
||||
@@ -311,7 +315,6 @@ CPLINFO
|
||||
cplusplus
|
||||
CPPCORECHECK
|
||||
cppcorecheckrules
|
||||
cpprest
|
||||
cpprestsdk
|
||||
cppwinrt
|
||||
CProc
|
||||
@@ -410,20 +413,24 @@ DECAWM
|
||||
DECBKM
|
||||
DECCARA
|
||||
DECCKM
|
||||
DECCKSR
|
||||
DECCOLM
|
||||
DECCRA
|
||||
DECCTR
|
||||
DECDHL
|
||||
decdld
|
||||
DECDMAC
|
||||
DECDWL
|
||||
DECEKBD
|
||||
DECERA
|
||||
DECFRA
|
||||
DECID
|
||||
DECINVM
|
||||
DECKPAM
|
||||
DECKPM
|
||||
DECKPNM
|
||||
DECLRMM
|
||||
DECMSR
|
||||
DECNKM
|
||||
DECNRCM
|
||||
DECOM
|
||||
@@ -433,6 +440,7 @@ DECRARA
|
||||
DECRC
|
||||
DECREQTPARM
|
||||
DECRLM
|
||||
DECRPM
|
||||
DECRQM
|
||||
DECRQSS
|
||||
DECRQTSR
|
||||
@@ -453,6 +461,7 @@ DECSLRM
|
||||
DECSMKR
|
||||
DECSR
|
||||
DECSTBM
|
||||
DECSTGLT
|
||||
DECSTR
|
||||
DECSWL
|
||||
DECTCEM
|
||||
@@ -575,6 +584,7 @@ ENU
|
||||
ENUMLOGFONT
|
||||
ENUMLOGFONTEX
|
||||
enumranges
|
||||
EOK
|
||||
eplace
|
||||
EPres
|
||||
EQU
|
||||
@@ -792,7 +802,6 @@ HIBYTE
|
||||
hicon
|
||||
HIDEWINDOW
|
||||
hinst
|
||||
Hirots
|
||||
HISTORYBUFS
|
||||
HISTORYNODUP
|
||||
HISTORYSIZE
|
||||
@@ -807,10 +816,13 @@ hlsl
|
||||
hmod
|
||||
hmodule
|
||||
hmon
|
||||
homeglyphs
|
||||
homoglyph
|
||||
HORZ
|
||||
hostable
|
||||
hostlib
|
||||
HPA
|
||||
hpcon
|
||||
HPCON
|
||||
hpj
|
||||
HPR
|
||||
@@ -1262,7 +1274,6 @@ nullability
|
||||
nullness
|
||||
nullonfailure
|
||||
nullopts
|
||||
NULs
|
||||
numlock
|
||||
numpad
|
||||
NUMSCROLL
|
||||
@@ -1277,6 +1288,8 @@ OEMFONT
|
||||
OEMFORMAT
|
||||
OEMs
|
||||
offboarded
|
||||
oklab
|
||||
Oklab
|
||||
OLEAUT
|
||||
OLECHAR
|
||||
onecore
|
||||
@@ -1430,7 +1443,6 @@ PPEB
|
||||
ppf
|
||||
ppguid
|
||||
ppidl
|
||||
pplx
|
||||
PPROC
|
||||
PPROCESS
|
||||
ppropvar
|
||||
@@ -1570,6 +1582,7 @@ replatformed
|
||||
Replymessage
|
||||
repositorypath
|
||||
Requiresx
|
||||
rerasterize
|
||||
rescap
|
||||
Resequence
|
||||
RESETCONTENT
|
||||
@@ -1758,7 +1771,6 @@ somefile
|
||||
SOURCEBRANCH
|
||||
sourced
|
||||
spammy
|
||||
spand
|
||||
SRCCODEPAGE
|
||||
SRCCOPY
|
||||
SRCINVERT
|
||||
@@ -1766,10 +1778,13 @@ srcsrv
|
||||
SRCSRVTRG
|
||||
srctool
|
||||
srect
|
||||
srgb
|
||||
Srgb
|
||||
srv
|
||||
srvinit
|
||||
srvpipe
|
||||
ssa
|
||||
startdir
|
||||
STARTF
|
||||
STARTUPINFO
|
||||
STARTUPINFOEX
|
||||
@@ -1818,6 +1833,7 @@ SYSCOMMAND
|
||||
SYSDEADCHAR
|
||||
SYSKEYDOWN
|
||||
SYSKEYUP
|
||||
SYSLIB
|
||||
SYSLINK
|
||||
SYSMENU
|
||||
sysparams
|
||||
@@ -1942,6 +1958,7 @@ trx
|
||||
tsattrs
|
||||
tsf
|
||||
tsgr
|
||||
tsm
|
||||
TStr
|
||||
TSTRFORMAT
|
||||
TSub
|
||||
@@ -2106,7 +2123,6 @@ WDDMCONSOLECONTEXT
|
||||
wdm
|
||||
webpage
|
||||
websites
|
||||
websockets
|
||||
wekyb
|
||||
wex
|
||||
wextest
|
||||
@@ -2183,6 +2199,7 @@ wnd
|
||||
WNDALLOC
|
||||
WNDCLASS
|
||||
WNDCLASSEX
|
||||
WNDCLASSEXW
|
||||
WNDCLASSW
|
||||
Wndproc
|
||||
WNegative
|
||||
@@ -2277,7 +2294,6 @@ xunit
|
||||
xutr
|
||||
XVIRTUALSCREEN
|
||||
XWalk
|
||||
xwwyzz
|
||||
xxyyzz
|
||||
yact
|
||||
YCast
|
||||
@@ -2288,6 +2304,7 @@ YOffset
|
||||
YSubstantial
|
||||
YVIRTUALSCREEN
|
||||
YWalk
|
||||
zabcd
|
||||
Zabcdefghijklmnopqrstuvwxyz
|
||||
ZCmd
|
||||
ZCtrl
|
||||
|
||||
@@ -35,7 +35,7 @@ ROY\sG\.\sBIV
|
||||
# hit-count: 71 file-count: 35
|
||||
# Compiler flags
|
||||
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
|
||||
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
(?:^|[\t ,"'`=(])-[X](?!aml)(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# hit-count: 41 file-count: 28
|
||||
# version suffix <word>v#
|
||||
|
||||
1
.github/workflows/addToProject.yml
vendored
1
.github/workflows/addToProject.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
- labeled
|
||||
- unlabeled
|
||||
|
||||
permissions: {}
|
||||
jobs:
|
||||
add-to-project:
|
||||
name: Add issue to project
|
||||
|
||||
24
.github/workflows/winget.yml
vendored
Normal file
24
.github/workflows/winget.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Publish to Winget
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
env:
|
||||
REGEX: 'Microsoft\.WindowsTerminal(?:Preview)?_Win10_([\d.]+)_8wekyb3d8bbwe\.msixbundle$'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: windows-latest # Action can only run on Windows
|
||||
steps:
|
||||
- name: Publish Windows Terminal ${{ github.event.release.prerelease && 'Preview' || 'Stable' }}
|
||||
run: |
|
||||
$assets = '${{ toJSON(github.event.release.assets) }}' | ConvertFrom-Json
|
||||
$wingetRelevantAsset = $assets | Where-Object { $_.name -like '*Win10*' } | Select-Object -First 1
|
||||
$regex = [Regex]::New($env:REGEX)
|
||||
$version = $regex.Match($wingetRelevantAsset.name).Groups[1].Value
|
||||
|
||||
$wingetPackage = "Microsoft.WindowsTerminal${{ github.event.release.prerelease && '.Preview' || '' }}"
|
||||
|
||||
& curl.exe -JLO https://aka.ms/wingetcreate/latest
|
||||
& .\wingetcreate.exe update $wingetPackage -s -v $version -u $wingetRelevantAsset.browser_download_url -t "${{ secrets.WINGET_TOKEN }}"
|
||||
@@ -101,7 +101,7 @@ If you don't have any additional info/context to add but would like to indicate
|
||||
|
||||
If you're able & willing to help fix issues and/or implement features, we'd love your contribution!
|
||||
|
||||
The best place to start is the list of ["Easy Starter"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+label%3A%22Easy+Starter%22+) issues. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue your interested in and hop in!
|
||||
The best place to start is the list of ["good first issue"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22++label%3A%22good+first+issue%22+)s. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue you're interested in and hop in!
|
||||
|
||||
Generally, we categorize issues in the following way, which is largely derived from our old internal work tracking system:
|
||||
* ["Bugs"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Bug%22+) are parts of the Terminal & Console that are not quite working the right way. There's code to already support some scenario, but it's not quite working right. Fixing these is generally a matter of debugging the broken functionality and fixing the wrong code.
|
||||
|
||||
49
NOTICE.md
49
NOTICE.md
@@ -276,41 +276,28 @@ OTHER DEALINGS IN THE SOFTWARE.
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
```
|
||||
|
||||
## ConEmu
|
||||
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
|
||||
## Oklab
|
||||
**Source**: [https://bottosson.github.io/posts/oklab/](https://bottosson.github.io/posts/oklab/)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2009-2017, Maximus5 <ConEmu.Maximus5@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Copyright (c) 2020 Björn Ottosson
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
# Microsoft Open Source
|
||||
|
||||
780
OpenConsole.sln
780
OpenConsole.sln
File diff suppressed because it is too large
Load Diff
@@ -1,175 +0,0 @@
|
||||
function GetAzureDevOpsBaseUri
|
||||
{
|
||||
Param(
|
||||
[string]$CollectionUri,
|
||||
[string]$TeamProject
|
||||
)
|
||||
|
||||
return $CollectionUri + $TeamProject
|
||||
}
|
||||
|
||||
function GetQueryTestRunsUri
|
||||
{
|
||||
Param(
|
||||
[string]$CollectionUri,
|
||||
[string]$TeamProject,
|
||||
[string]$BuildUri,
|
||||
[switch]$IncludeRunDetails
|
||||
)
|
||||
|
||||
if ($IncludeRunDetails)
|
||||
{
|
||||
$includeRunDetailsParameter = "&includeRunDetails=true"
|
||||
}
|
||||
else
|
||||
{
|
||||
$includeRunDetailsParameter = ""
|
||||
}
|
||||
|
||||
$baseUri = GetAzureDevOpsBaseUri -CollectionUri $CollectionUri -TeamProject $TeamProject
|
||||
$queryUri = "$baseUri/_apis/test/runs?buildUri=$BuildUri$includeRunDetailsParameter&api-version=5.0"
|
||||
return $queryUri
|
||||
}
|
||||
|
||||
function Get-HelixJobTypeFromTestRun
|
||||
{
|
||||
Param ($testRun)
|
||||
|
||||
$testRunSingleResultUri = "$($testRun.url)/results?`$top=1&`$skip=0&api-version=5.1"
|
||||
$singleTestResult = Invoke-RestMethod -Uri $testRunSingleResultUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
$count = $singleTestResult.value.Length
|
||||
if($count -eq 0)
|
||||
{
|
||||
# If the count is 0, then results have not yet been reported for this run.
|
||||
# We only care about completed runs with results, so it is ok to just return 'UNKNOWN' for this run.
|
||||
return "UNKNOWN"
|
||||
}
|
||||
else
|
||||
{
|
||||
$info = ConvertFrom-Json $singleTestResult.value.comment
|
||||
$helixJobId = $info.HelixJobId
|
||||
$job = Invoke-RestMethodWithRetries "https://helix.dot.net/api/2019-06-17/jobs/${helixJobId}?access_token=${HelixAccessToken}"
|
||||
return $job.Type
|
||||
}
|
||||
}
|
||||
|
||||
function Append-HelixAccessTokenToUrl
|
||||
{
|
||||
Param ([string]$url, [string]$token)
|
||||
if($url.Contains("?"))
|
||||
{
|
||||
$url = "$($url)&access_token=$($token)"
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = "$($url)?access_token=$($token)"
|
||||
}
|
||||
return $url
|
||||
}
|
||||
|
||||
|
||||
# The Helix Rest api is sometimes unreliable. So we call these apis with retry logic.
|
||||
# Note: The Azure DevOps apis are stable and do not need to be called with this retry logic.
|
||||
$helixApiRetries = 0
|
||||
$helixApiRetriesMax = 10
|
||||
|
||||
function Download-StringWithRetries
|
||||
{
|
||||
Param ([string]$fileName, [string]$url)
|
||||
|
||||
$result = ""
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
Write-Host "Downloading $fileName"
|
||||
$result = (New-Object System.Net.WebClient).DownloadString($url)
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to download $fileName $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry download of $fileName"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to download $fileName"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
function Invoke-RestMethodWithRetries
|
||||
{
|
||||
Param ([string]$url,$Headers)
|
||||
|
||||
$result = @()
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
$result = Invoke-RestMethod -Uri $url -Method Get -Headers $Headers
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to invoke Rest method $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry invoke"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to invoke Rest method"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
function Download-FileWithRetries
|
||||
{
|
||||
Param ([string]$fileurl, [string]$destination)
|
||||
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
Write-Host "Downloading $destination"
|
||||
$webClient.DownloadFile($fileurl, $destination)
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to download $destination $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry download of $destination"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to download $destination"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
$scriptDirectory = $script:MyInvocation.MyCommand.Path | Split-Path -Parent
|
||||
|
||||
# List all processes to aid debugging:
|
||||
Write-Host "All processes running:"
|
||||
Get-Process
|
||||
|
||||
tasklist /svc
|
||||
|
||||
# Add this test directory as an exclusion for Windows Defender
|
||||
Write-Host "Add $scriptDirectory as Exclusion Path"
|
||||
Add-MpPreference -ExclusionPath $scriptDirectory
|
||||
Write-Host "Add $($env:HELIX_CORRELATION_PAYLOAD) as Exclusion Path"
|
||||
Add-MpPreference -ExclusionPath $env:HELIX_CORRELATION_PAYLOAD
|
||||
Get-MpPreference
|
||||
Get-MpComputerStatus
|
||||
|
||||
|
||||
# Minimize all windows:
|
||||
$shell = New-Object -ComObject "Shell.Application"
|
||||
$shell.minimizeall()
|
||||
|
||||
# Kill any instances of Windows Security Alert:
|
||||
$windowTitleToMatch = "*Windows Security Alert*"
|
||||
$procs = Get-Process | Where {$_.MainWindowTitle -like "*Windows Security Alert*"}
|
||||
foreach ($proc in $procs)
|
||||
{
|
||||
Write-Host "Found process with '$windowTitleToMatch' title: $proc"
|
||||
$proc.Kill();
|
||||
}
|
||||
|
||||
# Kill processes by name that are known to interfere with our tests:
|
||||
$processNamesToStop = @("Microsoft.Photos", "WinStore.App", "SkypeApp", "SkypeBackgroundHost", "OneDriveSetup", "OneDrive")
|
||||
foreach($procName in $processNamesToStop)
|
||||
{
|
||||
Write-Host "Attempting to kill $procName if it is running"
|
||||
Stop-Process -ProcessName $procName -Verbose -ErrorAction Ignore
|
||||
}
|
||||
Write-Host "All processes running after attempting to kill unwanted processes:"
|
||||
Get-Process
|
||||
|
||||
tasklist /svc
|
||||
|
||||
$platform = $env:testbuildplatform
|
||||
if(!$platform)
|
||||
{
|
||||
$platform = "x86"
|
||||
}
|
||||
|
||||
function UninstallApps {
|
||||
Param([string[]]$appsToUninstall)
|
||||
|
||||
foreach($pkgName in $appsToUninstall)
|
||||
{
|
||||
foreach($pkg in (Get-AppxPackage $pkgName).PackageFullName)
|
||||
{
|
||||
Write-Output "Removing: $pkg"
|
||||
Remove-AppxPackage $pkg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function UninstallTestApps {
|
||||
Param([string[]]$appsToUninstall)
|
||||
|
||||
foreach($pkgName in $appsToUninstall)
|
||||
{
|
||||
foreach($pkg in (Get-AppxPackage $pkgName).PackageFullName)
|
||||
{
|
||||
Write-Output "Removing: $pkg"
|
||||
Remove-AppxPackage $pkg
|
||||
}
|
||||
|
||||
# Sometimes an app can get into a state where it is no longer returned by Get-AppxPackage, but it is still present
|
||||
# which prevents other versions of the app from being installed.
|
||||
# To handle this, we can directly call Remove-AppxPackage against the full name of the package. However, without
|
||||
# Get-AppxPackage to find the PackageFullName, we just have to manually construct the name.
|
||||
$packageFullName = "$($pkgName)_1.0.0.0_$($platform)__8wekyb3d8bbwe"
|
||||
Write-Host "Removing $packageFullName if installed"
|
||||
Remove-AppPackage $packageFullName -ErrorVariable appxerror -ErrorAction SilentlyContinue
|
||||
if($appxerror)
|
||||
{
|
||||
foreach($error in $appxerror)
|
||||
{
|
||||
# In most cases, Remove-AppPackage will fail due to the package not being found. Don't treat this as an error.
|
||||
if(!($error.Exception.Message -match "0x80073CF1"))
|
||||
{
|
||||
Write-Error $error
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Successfully removed $packageFullName"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Uninstall AppX packages that are known to cause issues with our tests"
|
||||
UninstallApps("*Skype*", "*Windows.Photos*")
|
||||
|
||||
Write-Host "Uninstall any of our test apps that may have been left over from previous test runs"
|
||||
UninstallTestApps("NugetPackageTestApp", "NugetPackageTestAppCX", "IXMPTestApp", "MUXControlsTestApp")
|
||||
|
||||
Write-Host "Uninstall MUX Framework package that may have been left over from previous test runs"
|
||||
# We don't want to uninstall all versions of the MUX Framework package, as there may be other apps preinstalled on the system
|
||||
# that depend on it. We only uninstall the Framework package that corresponds to the version of MUX that we are testing.
|
||||
[xml]$versionData = (Get-Content "version.props")
|
||||
$versionMajor = $versionData.GetElementsByTagName("MUXVersionMajor").'#text'
|
||||
$versionMinor = $versionData.GetElementsByTagName("MUXVersionMinor").'#text'
|
||||
UninstallApps("Microsoft.UI.Xaml.$versionMajor.$versionMinor")
|
||||
|
||||
Get-Process
|
||||
@@ -1,336 +0,0 @@
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TestFile,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$OutputProjFile,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$JobTestSuiteName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TaefPath,
|
||||
|
||||
[string]$TaefQuery
|
||||
)
|
||||
|
||||
Class TestCollection
|
||||
{
|
||||
[string]$Name
|
||||
[string]$SetupMethodName
|
||||
[string]$TeardownMethodName
|
||||
[System.Collections.Generic.Dictionary[string, string]]$Properties
|
||||
|
||||
TestCollection()
|
||||
{
|
||||
if ($this.GetType() -eq [TestCollection])
|
||||
{
|
||||
throw "This class should never be instantiated directly; it should only be derived from."
|
||||
}
|
||||
}
|
||||
|
||||
TestCollection([string]$name)
|
||||
{
|
||||
$this.Init($name)
|
||||
}
|
||||
|
||||
hidden Init([string]$name)
|
||||
{
|
||||
$this.Name = $name
|
||||
$this.Properties = @{}
|
||||
}
|
||||
}
|
||||
|
||||
Class Test : TestCollection
|
||||
{
|
||||
Test([string]$name)
|
||||
{
|
||||
$this.Init($name)
|
||||
}
|
||||
}
|
||||
|
||||
Class TestClass : TestCollection
|
||||
{
|
||||
[System.Collections.Generic.List[Test]]$Tests
|
||||
|
||||
TestClass([string]$name)
|
||||
{
|
||||
$this.Init($name)
|
||||
$this.Tests = @{}
|
||||
}
|
||||
}
|
||||
|
||||
Class TestModule : TestCollection
|
||||
{
|
||||
[System.Collections.Generic.List[TestClass]]$TestClasses
|
||||
|
||||
TestModule([string]$name)
|
||||
{
|
||||
$this.Init($name)
|
||||
$this.TestClasses = @{}
|
||||
}
|
||||
}
|
||||
|
||||
function Parse-TestInfo([string]$taefOutput)
|
||||
{
|
||||
enum LineType
|
||||
{
|
||||
None
|
||||
TestModule
|
||||
TestClass
|
||||
Test
|
||||
Setup
|
||||
Teardown
|
||||
Property
|
||||
}
|
||||
|
||||
[string]$testModuleIndentation = " "
|
||||
[string]$testClassIndentation = " "
|
||||
[string]$testIndentation = " "
|
||||
[string]$setupBeginning = "Setup: "
|
||||
[string]$teardownBeginning = "Teardown: "
|
||||
[string]$propertyBeginning = "Property["
|
||||
|
||||
function Get-LineType([string]$line)
|
||||
{
|
||||
if ($line.Contains($setupBeginning))
|
||||
{
|
||||
return [LineType]::Setup;
|
||||
}
|
||||
elseif ($line.Contains($teardownBeginning))
|
||||
{
|
||||
return [LineType]::Teardown;
|
||||
}
|
||||
elseif ($line.Contains($propertyBeginning))
|
||||
{
|
||||
return [LineType]::Property;
|
||||
}
|
||||
elseif ($line.StartsWith($testModuleIndentation) -and -not $line.StartsWith("$testModuleIndentation "))
|
||||
{
|
||||
return [LineType]::TestModule;
|
||||
}
|
||||
elseif ($line.StartsWith($testClassIndentation) -and -not $line.StartsWith("$testClassIndentation "))
|
||||
{
|
||||
return [LineType]::TestClass;
|
||||
}
|
||||
elseif ($line.StartsWith($testIndentation) -and -not $line.StartsWith("$testIndentation "))
|
||||
{
|
||||
return [LineType]::Test;
|
||||
}
|
||||
else
|
||||
{
|
||||
return [LineType]::None;
|
||||
}
|
||||
}
|
||||
|
||||
[string[]]$lines = $taefOutput.Split(@([Environment]::NewLine, "`n"), [StringSplitOptions]::RemoveEmptyEntries)
|
||||
[System.Collections.Generic.List[TestModule]]$testModules = @()
|
||||
|
||||
[TestModule]$currentTestModule = $null
|
||||
[TestClass]$currentTestClass = $null
|
||||
[Test]$currentTest = $null
|
||||
|
||||
[TestCollection]$lastTestCollection = $null
|
||||
|
||||
foreach ($rawLine in $lines)
|
||||
{
|
||||
[LineType]$lineType = (Get-LineType $rawLine)
|
||||
|
||||
# We don't need the whitespace around the line anymore, so we'll discard it to make things easier.
|
||||
[string]$line = $rawLine.Trim()
|
||||
|
||||
if ($lineType -eq [LineType]::TestModule)
|
||||
{
|
||||
if ($currentTest -ne $null -and $currentTestClass -ne $null)
|
||||
{
|
||||
$currentTestClass.Tests.Add($currentTest)
|
||||
}
|
||||
|
||||
if ($currentTestClass -ne $null -and $currentTestModule -ne $null)
|
||||
{
|
||||
$currentTestModule.TestClasses.Add($currentTestClass)
|
||||
}
|
||||
|
||||
if ($currentTestModule -ne $null)
|
||||
{
|
||||
$testModules.Add($currentTestModule)
|
||||
}
|
||||
|
||||
$currentTestModule = [TestModule]::new($line)
|
||||
$currentTestClass = $null
|
||||
$currentTest = $null
|
||||
$lastTestCollection = $currentTestModule
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::TestClass)
|
||||
{
|
||||
if ($currentTest -ne $null -and $currentTestClass -ne $null)
|
||||
{
|
||||
$currentTestClass.Tests.Add($currentTest)
|
||||
}
|
||||
|
||||
if ($currentTestClass -ne $null -and $currentTestModule -ne $null)
|
||||
{
|
||||
$currentTestModule.TestClasses.Add($currentTestClass)
|
||||
}
|
||||
|
||||
$currentTestClass = [TestClass]::new($line)
|
||||
$currentTest = $null
|
||||
$lastTestCollection = $currentTestClass
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::Test)
|
||||
{
|
||||
if ($currentTest -ne $null -and $currentTestClass -ne $null)
|
||||
{
|
||||
$currentTestClass.Tests.Add($currentTest)
|
||||
}
|
||||
|
||||
$currentTest = [Test]::new($line)
|
||||
$lastTestCollection = $currentTest
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::Setup)
|
||||
{
|
||||
if ($lastTestCollection -ne $null)
|
||||
{
|
||||
$lastTestCollection.SetupMethodName = $line.Replace($setupBeginning, "")
|
||||
}
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::Teardown)
|
||||
{
|
||||
if ($lastTestCollection -ne $null)
|
||||
{
|
||||
$lastTestCollection.TeardownMethodName = $line.Replace($teardownBeginning, "")
|
||||
}
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::Property)
|
||||
{
|
||||
if ($lastTestCollection -ne $null)
|
||||
{
|
||||
foreach ($match in [Regex]::Matches($line, "Property\[(.*)\]\s+=\s+(.*)"))
|
||||
{
|
||||
[string]$propertyKey = $match.Groups[1].Value;
|
||||
[string]$propertyValue = $match.Groups[2].Value;
|
||||
$lastTestCollection.Properties.Add($propertyKey, $propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentTest -ne $null -and $currentTestClass -ne $null)
|
||||
{
|
||||
$currentTestClass.Tests.Add($currentTest)
|
||||
}
|
||||
|
||||
if ($currentTestClass -ne $null -and $currentTestModule -ne $null)
|
||||
{
|
||||
$currentTestModule.TestClasses.Add($currentTestClass)
|
||||
}
|
||||
|
||||
if ($currentTestModule -ne $null)
|
||||
{
|
||||
$testModules.Add($currentTestModule)
|
||||
}
|
||||
|
||||
return $testModules
|
||||
}
|
||||
|
||||
Write-Verbose "TaefQuery = $TaefQuery"
|
||||
|
||||
$TaefSelectQuery = ""
|
||||
$TaefQueryToAppend = ""
|
||||
if($TaefQuery)
|
||||
{
|
||||
$TaefSelectQuery = "/select:`"$TaefQuery`""
|
||||
$TaefQueryToAppend = " and $TaefQuery"
|
||||
}
|
||||
Write-Verbose "TaefSelectQuery = $TaefSelectQuery"
|
||||
|
||||
|
||||
$taefExe = "$TaefPath\te.exe"
|
||||
[string]$taefOutput = & "$taefExe" /listproperties $TaefSelectQuery $TestFile | Out-String
|
||||
|
||||
[System.Collections.Generic.List[TestModule]]$testModules = (Parse-TestInfo $taefOutput)
|
||||
|
||||
$projFileContent = @"
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
"@
|
||||
|
||||
foreach ($testModule in $testModules)
|
||||
{
|
||||
foreach ($testClass in $testModules.TestClasses)
|
||||
{
|
||||
Write-Host "Generating Helix work item for test class $($testClass.Name)..."
|
||||
[System.Collections.Generic.List[string]]$testSuiteNames = @()
|
||||
|
||||
$testSuiteExists = $false
|
||||
$suitelessTestExists = $false
|
||||
|
||||
foreach ($test in $testClass.Tests)
|
||||
{
|
||||
# A test method inherits its 'TestSuite' property from its TestClass
|
||||
if (!$test.Properties.ContainsKey("TestSuite") -and $testClass.Properties.ContainsKey("TestSuite"))
|
||||
{
|
||||
$test.Properties["TestSuite"] = $testClass.Properties["TestSuite"]
|
||||
}
|
||||
|
||||
if ($test.Properties.ContainsKey("TestSuite"))
|
||||
{
|
||||
[string]$testSuite = $test.Properties["TestSuite"]
|
||||
|
||||
if (-not $testSuiteNames.Contains($testSuite))
|
||||
{
|
||||
Write-Host " Found test suite $testSuite. Generating Helix work item for it as well."
|
||||
$testSuiteNames.Add($testSuite)
|
||||
}
|
||||
|
||||
$testSuiteExists = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
$suitelessTestExists = $true
|
||||
}
|
||||
}
|
||||
|
||||
$testClassSelectPattern = "$($testClass.Name).*"
|
||||
if($testClass.Name.Contains("::"))
|
||||
{
|
||||
$testClassSelectPattern = "$($testClass.Name)::*"
|
||||
}
|
||||
$testNameQuery= "(@Name='$testClassSelectPattern')"
|
||||
|
||||
$workItemName = $testClass.Name
|
||||
# Native tests use '::' as a separator, which is not valid for workItem names.
|
||||
$workItemName = $workItemName -replace "::", "-"
|
||||
|
||||
if ($suitelessTestExists)
|
||||
{
|
||||
$projFileContent += @"
|
||||
|
||||
<HelixWorkItem Include="$($workItemName)" Condition="'`$(TestSuite)'=='$($JobTestSuiteName)'">
|
||||
<Timeout>00:30:00</Timeout>
|
||||
<Command>call %HELIX_CORRELATION_PAYLOAD%\runtests.cmd /select:"(@Name='$($testClass.Name)*'$(if ($testSuiteExists) { "and not @TestSuite='*'" }))$($TaefQueryToAppend)"</Command>
|
||||
</HelixWorkItem>
|
||||
"@
|
||||
}
|
||||
|
||||
foreach ($testSuiteName in $testSuiteNames)
|
||||
{
|
||||
$projFileContent += @"
|
||||
|
||||
<HelixWorkItem Include="$($workItemName)-$testSuiteName" Condition="'`$(TestSuite)'=='$($JobTestSuiteName)'">
|
||||
<Timeout>00:30:00</Timeout>
|
||||
<Command>call %HELIX_CORRELATION_PAYLOAD%\runtests.cmd /select:"(@Name='$($testClass.Name)*' and @TestSuite='$testSuiteName')$($TaefQueryToAppend)"</Command>
|
||||
</HelixWorkItem>
|
||||
"@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$projFileContent += @"
|
||||
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
"@
|
||||
|
||||
Set-Content $OutputProjFile $projFileContent -NoNewline -Encoding UTF8
|
||||
@@ -1,12 +0,0 @@
|
||||
# Displaying progress is unnecessary and is just distracting.
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
$dependencyFiles = Get-ChildItem -Filter "*Microsoft.VCLibs.*.appx"
|
||||
|
||||
foreach ($file in $dependencyFiles)
|
||||
{
|
||||
Write-Host "Adding dependency $($file)..."
|
||||
|
||||
Add-AppxPackage $file
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttInputPath
|
||||
)
|
||||
|
||||
Add-Type -Language CSharp -ReferencedAssemblies System.Xml,System.Xml.Linq,System.Runtime.Serialization,System.Runtime.Serialization.Json (Get-Content $PSScriptRoot\HelixTestHelpers.cs -Raw)
|
||||
|
||||
[HelixTestHelpers.FailedTestDetector]::OutputFailedTestQuery($WttInputPath)
|
||||
@@ -1,32 +0,0 @@
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttSingleRerunInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttMultipleRerunInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TestNamePrefix
|
||||
)
|
||||
|
||||
# Ideally these would be passed as parameters to the script. However ps makes it difficult to deal with string literals containing '&', so we just
|
||||
# read the values directly from the environment variables
|
||||
$helixResultsContainerUri = $Env:HELIX_RESULTS_CONTAINER_URI
|
||||
$helixResultsContainerRsas = $Env:HELIX_RESULTS_CONTAINER_RSAS
|
||||
|
||||
Add-Type -Language CSharp -ReferencedAssemblies System.Xml,System.Xml.Linq,System.Runtime.Serialization,System.Runtime.Serialization.Json (Get-Content $PSScriptRoot\HelixTestHelpers.cs -Raw)
|
||||
|
||||
$testResultParser = [HelixTestHelpers.TestResultParser]::new($TestNamePrefix, $helixResultsContainerUri, $helixResultsContainerRsas)
|
||||
[System.Collections.Generic.Dictionary[string, string]]$subResultsJsonByMethodName = $testResultParser.GetSubResultsJsonByMethodName($WttInputPath, $WttSingleRerunInputPath, $WttMultipleRerunInputPath)
|
||||
|
||||
$subResultsJsonDirectory = [System.IO.Path]::GetDirectoryName($WttInputPath)
|
||||
|
||||
foreach ($methodName in $subResultsJsonByMethodName.Keys)
|
||||
{
|
||||
$subResultsJson = $subResultsJsonByMethodName[$methodName]
|
||||
$subResultsJsonPath = [System.IO.Path]::Combine($subResultsJsonDirectory, $methodName + "_subresults.json")
|
||||
Out-File $subResultsJsonPath -Encoding utf8 -InputObject $subResultsJson
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]$MinimumExpectedTestsExecutedCount,
|
||||
|
||||
[string]$AccessToken = $env:SYSTEM_ACCESSTOKEN,
|
||||
[string]$CollectionUri = $env:SYSTEM_COLLECTIONURI,
|
||||
[string]$TeamProject = $env:SYSTEM_TEAMPROJECT,
|
||||
[string]$BuildUri = $env:BUILD_BUILDURI,
|
||||
[bool]$CheckJobAttempt
|
||||
)
|
||||
|
||||
$azureDevOpsRestApiHeaders = @{
|
||||
"Accept"="application/json"
|
||||
"Authorization"="Basic $([System.Convert]::ToBase64String([System.Text.ASCIIEncoding]::ASCII.GetBytes(":$AccessToken")))"
|
||||
}
|
||||
|
||||
. "$PSScriptRoot/AzurePipelinesHelperScripts.ps1"
|
||||
|
||||
Write-Host "Checking test results..."
|
||||
|
||||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
|
||||
[System.Collections.Generic.List[string]]$failingTests = @()
|
||||
[System.Collections.Generic.List[string]]$unreliableTests = @()
|
||||
[System.Collections.Generic.List[string]]$unexpectedResultTest = @()
|
||||
|
||||
[System.Collections.Generic.List[string]]$namesOfProcessedTestRuns = @()
|
||||
$totalTestsExecutedCount = 0
|
||||
|
||||
# We assume that we only have one testRun with a given name that we care about
|
||||
# We only process the last testRun with a given name (based on completedDate)
|
||||
# The name of a testRun is set to the Helix queue that it was run on (e.g. windows.10.amd64.client21h1.xaml)
|
||||
# If we have multiple test runs on the same queue that we care about, we will need to re-visit this logic
|
||||
foreach ($testRun in ($testRuns.value | Sort-Object -Property "completedDate" -Descending))
|
||||
{
|
||||
if ($CheckJobAttempt)
|
||||
{
|
||||
if ($namesOfProcessedTestRuns -contains $testRun.name)
|
||||
{
|
||||
Write-Host "Skipping test run '$($testRun.name)', since we have already processed a test run of that name."
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Processing results from test run '$($testRun.name)'"
|
||||
$namesOfProcessedTestRuns.Add($testRun.name)
|
||||
|
||||
$totalTestsExecutedCount += $testRun.totalTests
|
||||
|
||||
$testRunResultsUri = "$($testRun.url)/results?api-version=5.0"
|
||||
$testResults = Invoke-RestMethodWithRetries "$($testRun.url)/results?api-version=5.0" -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
$shortTestCaseTitle = $testResult.testCaseTitle -replace "[a-zA-Z0-9]+.[a-zA-Z0-9]+.Windows.UI.Xaml.Tests.MUXControls.",""
|
||||
|
||||
if ($testResult.outcome -eq "Failed")
|
||||
{
|
||||
if (-not $failingTests.Contains($shortTestCaseTitle))
|
||||
{
|
||||
$failingTests.Add($shortTestCaseTitle)
|
||||
}
|
||||
}
|
||||
elseif ($testResult.outcome -eq "Warning")
|
||||
{
|
||||
if (-not $unreliableTests.Contains($shortTestCaseTitle))
|
||||
{
|
||||
$unreliableTests.Add($shortTestCaseTitle)
|
||||
}
|
||||
}
|
||||
elseif ($testResult.outcome -ne "Passed")
|
||||
{
|
||||
# We should only see tests with result "Passed", "Failed" or "Warning"
|
||||
if (-not $unexpectedResultTest.Contains($shortTestCaseTitle))
|
||||
{
|
||||
$unexpectedResultTest.Add($shortTestCaseTitle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($unreliableTests.Count -gt 0)
|
||||
{
|
||||
Write-Host @"
|
||||
##vso[task.logissue type=warning;]Unreliable tests:
|
||||
##vso[task.logissue type=warning;]$($unreliableTests -join "$([Environment]::NewLine)##vso[task.logissue type=warning;]")
|
||||
|
||||
"@
|
||||
}
|
||||
|
||||
if ($failingTests.Count -gt 0)
|
||||
{
|
||||
Write-Host @"
|
||||
##vso[task.logissue type=error;]Failing tests:
|
||||
##vso[task.logissue type=error;]$($failingTests -join "$([Environment]::NewLine)##vso[task.logissue type=error;]")
|
||||
|
||||
"@
|
||||
}
|
||||
|
||||
if ($unexpectedResultTest.Count -gt 0)
|
||||
{
|
||||
Write-Host @"
|
||||
##vso[task.logissue type=error;]Tests with unexpected results:
|
||||
##vso[task.logissue type=error;]$($unexpectedResultTest -join "$([Environment]::NewLine)##vso[task.logissue type=error;]")
|
||||
|
||||
"@
|
||||
}
|
||||
|
||||
if($totalTestsExecutedCount -lt $MinimumExpectedTestsExecutedCount)
|
||||
{
|
||||
Write-Host "Expected at least $MinimumExpectedTestsExecutedCount tests to be executed."
|
||||
Write-Host "Actual executed test count is: $totalTestsExecutedCount"
|
||||
Write-Host "##vso[task.complete result=Failed;]"
|
||||
}
|
||||
elseif ($failingTests.Count -gt 0)
|
||||
{
|
||||
Write-Host "At least one test failed."
|
||||
Write-Host "##vso[task.complete result=Failed;]"
|
||||
}
|
||||
elseif ($unreliableTests.Count -gt 0)
|
||||
{
|
||||
Write-Host "All tests eventually passed, but some initially failed."
|
||||
Write-Host "##vso[task.complete result=Succeeded;]"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "All tests passed."
|
||||
Write-Host "##vso[task.complete result=Succeeded;]"
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[string]$Platform,
|
||||
[string]$Configuration,
|
||||
[string]$ArtifactName='drop'
|
||||
)
|
||||
|
||||
$payloadDir = "HelixPayload\$Configuration\$Platform"
|
||||
|
||||
$repoDirectory = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "..\..\"
|
||||
$nugetPackagesDir = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "packages"
|
||||
|
||||
# Create the payload directory. Remove it if it already exists.
|
||||
If(test-path $payloadDir)
|
||||
{
|
||||
Remove-Item $payloadDir -Recurse
|
||||
}
|
||||
New-Item -ItemType Directory -Force -Path $payloadDir
|
||||
|
||||
# Copy files from nuget packages
|
||||
Copy-Item "$nugetPackagesDir\microsoft.windows.apps.test.1.0.181203002\lib\netcoreapp2.1\*.dll" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\NetFx4.5\*" $payloadDir
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\"
|
||||
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\"
|
||||
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\"
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir\content\"
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.1\content\*" "$payloadDir\content\"
|
||||
|
||||
function Copy-If-Exists
|
||||
{
|
||||
Param($source, $destinationDir)
|
||||
|
||||
if (Test-Path $source)
|
||||
{
|
||||
Write-Host "Copy from '$source' to '$destinationDir'"
|
||||
Copy-Item -Force $source $destinationDir
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "'$source' does not exist."
|
||||
}
|
||||
}
|
||||
|
||||
# Copy files from the 'drop' artifact dir
|
||||
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\$Configuration\$Platform\Test\*" $payloadDir -Recurse
|
||||
|
||||
# Copy files from the repo
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir"
|
||||
Copy-Item "build\helix\ConvertWttLogToXUnit.ps1" "$payloadDir"
|
||||
Copy-Item "build\helix\OutputFailedTestQuery.ps1" "$payloadDir"
|
||||
Copy-Item "build\helix\OutputSubResultsJsonFiles.ps1" "$payloadDir"
|
||||
Copy-Item "build\helix\HelixTestHelpers.cs" "$payloadDir"
|
||||
Copy-Item "build\helix\runtests.cmd" $payloadDir
|
||||
Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir"
|
||||
Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
|
||||
|
||||
# Copy the APPX package from the 'drop' artifact dir and Windows Kits
|
||||
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir\CascadiaPackage.zip
|
||||
Copy-Item "C:\program files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\Microsoft.VCLibs.Desktop\14.0\Appx\Retail\x64\Microsoft.VCLibs.x64.14.00.Desktop.appx" $payloadDir\VCLibs.zip
|
||||
|
||||
# Rename it to extension of ZIP because Expand-Archive is real sassy on the build machines
|
||||
# and refuses to unzip it because of its file extension while on a desktop, it just
|
||||
# does the job without complaining.
|
||||
|
||||
# Extract the APPX package
|
||||
Expand-Archive -LiteralPath $payloadDir\CascadiaPackage.zip -DestinationPath $payloadDir\appx
|
||||
Expand-Archive -LiteralPath $payloadDir\VCLibs.zip -DestinationPath $payloadDir\appx -Force
|
||||
@@ -1,130 +0,0 @@
|
||||
Param(
|
||||
[string]$AccessToken = $env:SYSTEM_ACCESSTOKEN,
|
||||
[string]$HelixAccessToken = $env:HelixAccessToken,
|
||||
[string]$CollectionUri = $env:SYSTEM_COLLECTIONURI,
|
||||
[string]$TeamProject = $env:SYSTEM_TEAMPROJECT,
|
||||
[string]$BuildUri = $env:BUILD_BUILDURI,
|
||||
[string]$OutputFolder = "HelixOutput"
|
||||
)
|
||||
|
||||
$helixLinkFile = "$OutputFolder\LinksToHelixTestFiles.html"
|
||||
|
||||
|
||||
function Generate-File-Links
|
||||
{
|
||||
Param ([Array[]]$files,[string]$sectionName)
|
||||
if($files.Count -gt 0)
|
||||
{
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<div class=$sectionName>"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h4>$sectionName</h4>"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<ul>"
|
||||
foreach($file in $files)
|
||||
{
|
||||
$url = Append-HelixAccessTokenToUrl $file.Link "{Your-Helix-Access-Token-Here}"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<li>$($url)</li>"
|
||||
}
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "</ul>"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "</div>"
|
||||
}
|
||||
}
|
||||
|
||||
function Append-HelixAccessTokenToUrl
|
||||
{
|
||||
Param ([string]$url, [string]$token)
|
||||
if($token)
|
||||
{
|
||||
if($url.Contains("?"))
|
||||
{
|
||||
$url = "$($url)&access_token=$($token)"
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = "$($url)?access_token=$($token)"
|
||||
}
|
||||
}
|
||||
return $url
|
||||
}
|
||||
|
||||
#Create output directory
|
||||
New-Item $OutputFolder -ItemType Directory
|
||||
|
||||
$azureDevOpsRestApiHeaders = @{
|
||||
"Accept"="application/json"
|
||||
"Authorization"="Basic $([System.Convert]::ToBase64String([System.Text.ASCIIEncoding]::ASCII.GetBytes(":$AccessToken")))"
|
||||
}
|
||||
|
||||
. "$PSScriptRoot/AzurePipelinesHelperScripts.ps1"
|
||||
|
||||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
|
||||
$webClient = New-Object System.Net.WebClient
|
||||
[System.Collections.Generic.List[string]]$workItems = @()
|
||||
|
||||
foreach ($testRun in $testRuns.value)
|
||||
{
|
||||
Write-Host "testRunUri = $testRun.url"
|
||||
$testResults = Invoke-RestMethodWithRetries "$($testRun.url)/results?api-version=5.0" -Headers $azureDevOpsRestApiHeaders
|
||||
$isTestRunNameShown = $false
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
$info = ConvertFrom-Json $testResult.comment
|
||||
$helixJobId = $info.HelixJobId
|
||||
$helixWorkItemName = $info.HelixWorkItemName
|
||||
|
||||
$workItem = "$helixJobId-$helixWorkItemName"
|
||||
|
||||
Write-Host "Helix Work Item = $workItem"
|
||||
|
||||
if (-not $workItems.Contains($workItem))
|
||||
{
|
||||
$workItems.Add($workItem)
|
||||
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files"
|
||||
$filesQueryUri = Append-HelixAccessTokenToUrl $filesQueryUri $helixAccessToken
|
||||
$files = Invoke-RestMethodWithRetries $filesQueryUri
|
||||
|
||||
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
|
||||
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
|
||||
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
|
||||
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
|
||||
{
|
||||
if(-Not $isTestRunNameShown)
|
||||
{
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
|
||||
$isTestRunNameShown = $true
|
||||
}
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
|
||||
Generate-File-Links $screenShots "Screenshots"
|
||||
Generate-File-Links $dumps "CrashDumps"
|
||||
Generate-File-Links $pgcFiles "PGC files"
|
||||
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
|
||||
Generate-File-Links $misc "Misc"
|
||||
|
||||
foreach($pgcFile in $pgcFiles)
|
||||
{
|
||||
$flavorPath = $testResult.automatedTestName.Split('.')[0]
|
||||
$archPath = $testResult.automatedTestName.Split('.')[1]
|
||||
$fileName = $pgcFile.Name
|
||||
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
|
||||
$destination = "$fullPath\$fileName"
|
||||
|
||||
Write-Host "Copying $($pgcFile.Name) to $destination"
|
||||
|
||||
if (-Not (Test-Path $fullPath))
|
||||
{
|
||||
New-Item $fullPath -ItemType Directory
|
||||
}
|
||||
|
||||
$link = $pgcFile.Link
|
||||
|
||||
Write-Host "Downloading $link to $destination"
|
||||
|
||||
$link = Append-HelixAccessTokenToUrl $link $HelixAccessToken
|
||||
Download-FileWithRetries $link $destination
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<Project Sdk="Microsoft.DotNet.Helix.Sdk" DefaultTargets="Test">
|
||||
<PropertyGroup>
|
||||
<HelixSource>pr/terminal/$(BUILD_SOURCEBRANCH)/</HelixSource>
|
||||
<EnableXUnitReporter>true</EnableXUnitReporter>
|
||||
<EnableAzurePipelinesReporter>true</EnableAzurePipelinesReporter>
|
||||
<FailOnMissionControlTestFailure>true</FailOnMissionControlTestFailure>
|
||||
<HelixPreCommands>$(HelixPreCommands);set testnameprefix=$(Configuration).$(Platform);set testbuildplatform=$(Platform);set rerunPassesRequiredToAvoidFailure=$(rerunPassesRequiredToAvoidFailure)</HelixPreCommands>
|
||||
<OutputPath>..\..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<HelixCorrelationPayload Include="..\..\HelixPayload\$(Configuration)\$(Platform)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- These .proj files are generated by the build machine prior to running tests via GenerateTestProjFile.ps1. -->
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-SettingsModelLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-WindowsTerminalUIATests.proj" Condition=" '$(TestSuite)'=='PgoInstrumentationSuite' " />
|
||||
</Project>
|
||||
@@ -1,136 +0,0 @@
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]$RerunPassesRequiredToAvoidFailure,
|
||||
|
||||
[string]$AccessToken = $env:SYSTEM_ACCESSTOKEN,
|
||||
[string]$CollectionUri = $env:SYSTEM_COLLECTIONURI,
|
||||
[string]$TeamProject = $env:SYSTEM_TEAMPROJECT,
|
||||
[string]$BuildUri = $env:BUILD_BUILDURI
|
||||
)
|
||||
|
||||
. "$PSScriptRoot/AzurePipelinesHelperScripts.ps1"
|
||||
|
||||
|
||||
$azureDevOpsRestApiHeaders = @{
|
||||
"Accept"="application/json"
|
||||
"Authorization"="Basic $([System.Convert]::ToBase64String([System.Text.ASCIIEncoding]::ASCII.GetBytes(":$AccessToken")))"
|
||||
}
|
||||
|
||||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
# To account for unreliable tests, we'll iterate through all of the tests associated with this build, check to see any tests that were unreliable
|
||||
# (denoted by being marked as "skipped"), and if so, we'll instead mark those tests with a warning and enumerate all of the attempted runs
|
||||
# with their pass/fail states as well as any relevant error messages for failed attempts.
|
||||
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
$timesSeenByRunName = @{}
|
||||
|
||||
foreach ($testRun in $testRuns.value)
|
||||
{
|
||||
$testRunResultsUri = "$($testRun.url)/results?api-version=5.0"
|
||||
|
||||
Write-Host "Marking test run `"$($testRun.name)`" as in progress so we can change its results to account for unreliable tests."
|
||||
Invoke-RestMethod "$($testRun.url)?api-version=5.0" -Method Patch -Body (ConvertTo-Json @{ "state" = "InProgress" }) -Headers $azureDevOpsRestApiHeaders -ContentType "application/json" | Out-Null
|
||||
|
||||
Write-Host "Retrieving test results..."
|
||||
$testResults = Invoke-RestMethodWithRetries $testRunResultsUri -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
$testNeedsSubResultProcessing = $false
|
||||
if ($testResult.outcome -eq "NotExecuted")
|
||||
{
|
||||
$testNeedsSubResultProcessing = $true
|
||||
}
|
||||
elseif($testResult.outcome -eq "Failed")
|
||||
{
|
||||
$testNeedsSubResultProcessing = $testResult.errorMessage -like "*_subresults.json*"
|
||||
}
|
||||
|
||||
if ($testNeedsSubResultProcessing)
|
||||
{
|
||||
Write-Host " Test $($testResult.testCaseTitle) was detected as unreliable. Updating..."
|
||||
|
||||
# The errorMessage field contains a link to the JSON-encoded rerun result data.
|
||||
$resultsJson = Download-StringWithRetries "Error results" $testResult.errorMessage
|
||||
$rerunResults = ConvertFrom-Json $resultsJson
|
||||
[System.Collections.Generic.List[System.Collections.Hashtable]]$rerunDataList = @()
|
||||
$attemptCount = 0
|
||||
$passCount = 0
|
||||
$totalDuration = 0
|
||||
|
||||
foreach ($rerun in $rerunResults.results)
|
||||
{
|
||||
$rerunData = @{
|
||||
"displayName" = "Attempt #$($attemptCount + 1) - $($testResult.testCaseTitle)";
|
||||
"durationInMs" = $rerun.duration;
|
||||
"outcome" = $rerun.outcome;
|
||||
}
|
||||
|
||||
if ($rerun.outcome -eq "Passed")
|
||||
{
|
||||
$passCount++
|
||||
}
|
||||
|
||||
if ($attemptCount -gt 0)
|
||||
{
|
||||
$rerunData["sequenceId"] = $attemptCount
|
||||
}
|
||||
|
||||
Write-Host " Attempt #$($attemptCount + 1): $($rerun.outcome)"
|
||||
|
||||
if ($rerun.outcome -ne "Passed")
|
||||
{
|
||||
$screenshots = "$($rerunResults.blobPrefix)/$($rerun.screenshots -join @"
|
||||
$($rerunResults.blobSuffix)
|
||||
$($rerunResults.blobPrefix)
|
||||
"@)$($rerunResults.blobSuffix)"
|
||||
|
||||
# We subtract 1 from the error index because we added 1 so we could use 0
|
||||
# as a default value not injected into the JSON in order to keep its size down.
|
||||
# We did this because there's a maximum size enforced for the errorMessage parameter
|
||||
# in the Azure DevOps REST API.
|
||||
$fullErrorMessage = @"
|
||||
Log: $($rerunResults.blobPrefix)/$($rerun.log)$($rerunResults.blobSuffix)
|
||||
|
||||
Screenshots:
|
||||
$screenshots
|
||||
|
||||
Error log:
|
||||
$($rerunResults.errors[$rerun.errorIndex - 1])
|
||||
"@
|
||||
|
||||
$rerunData["errorMessage"] = $fullErrorMessage
|
||||
}
|
||||
|
||||
$attemptCount++
|
||||
$totalDuration += $rerun.duration
|
||||
$rerunDataList.Add($rerunData)
|
||||
}
|
||||
|
||||
$overallOutcome = "Warning"
|
||||
|
||||
if ($attemptCount -eq 2)
|
||||
{
|
||||
Write-Host " Test $($testResult.testCaseTitle) passed on the immediate rerun, so we'll mark it as unreliable."
|
||||
}
|
||||
elseif ($passCount -gt $RerunPassesRequiredToAvoidFailure)
|
||||
{
|
||||
Write-Host " Test $($testResult.testCaseTitle) passed on $passCount of $attemptCount attempts, which is greater than or equal to the $RerunPassesRequiredToAvoidFailure passes required to avoid being marked as failed. Marking as unreliable."
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host " Test $($testResult.testCaseTitle) passed on only $passCount of $attemptCount attempts, which is less than the $RerunPassesRequiredToAvoidFailure passes required to avoid being marked as failed. Marking as failed."
|
||||
$overallOutcome = "Failed"
|
||||
}
|
||||
|
||||
$updateBody = ConvertTo-Json @(@{ "id" = $testResult.id; "outcome" = $overallOutcome; "errorMessage" = " "; "durationInMs" = $totalDuration; "subResults" = $rerunDataList; "resultGroupType" = "rerun" }) -Depth 5
|
||||
Invoke-RestMethod -Uri $testRunResultsUri -Method Patch -Headers $azureDevOpsRestApiHeaders -Body $updateBody -ContentType "application/json" | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Finished updates. Re-marking test run `"$($testRun.name)`" as completed."
|
||||
Invoke-RestMethod -Uri "$($testRun.url)?api-version=5.0" -Method Patch -Body (ConvertTo-Json @{ "state" = "Completed" }) -Headers $azureDevOpsRestApiHeaders -ContentType "application/json" | Out-Null
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"msbuild-sdks": {
|
||||
"Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.22525.5"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.TestContent" version="1.0.1" />
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="microsoft.windows.apps.test" version="1.0.181203002" targetFramework="native" />
|
||||
<package id="runtime.win-x86.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
|
||||
<package id="runtime.win-x64.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -1,32 +0,0 @@
|
||||
This directory contains code and configuration files to run WinUI tests in Helix.
|
||||
|
||||
Helix is a cloud hosted test execution environment which is accessed via the Arcade SDK.
|
||||
More details:
|
||||
* [Arcade](https://github.com/dotnet/arcade)
|
||||
* [Helix](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Helix/Sdk)
|
||||
|
||||
WinUI tests are scheduled in Helix by the Azure DevOps Pipeline: [RunHelixTests.yml](../RunHelixTests.yml).
|
||||
|
||||
The workflow is as follows:
|
||||
1. NuGet Restore is called on the packages.config in this directory. This downloads any runtime dependencies
|
||||
that are needed to run tests.
|
||||
2. PrepareHelixPayload.ps1 is called. This copies the necessary files from various locations into a Helix
|
||||
payload directory. This directory is what will get sent to the Helix machines.
|
||||
3. RunTestsInHelix.proj is executed. This proj has a dependency on
|
||||
[Microsoft.DotNet.Helix.Sdk](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Helix/Sdk)
|
||||
which it uses to publish the Helix payload directory and to schedule the Helix Work Items. The WinUI tests
|
||||
are parallelized into multiple Helix Work Items.
|
||||
4. Each Helix Work Item calls [runtests.cmd](runtests.cmd) with a specific query to pass to
|
||||
[TAEF](https://docs.microsoft.com/en-us/windows-hardware/drivers/taef/) which runs the tests.
|
||||
5. If a test is detected to have failed, we run it again, first once, then eight more times if it fails again.
|
||||
If it fails all ten times, we report the test as failed; otherwise, we report it as unreliable,
|
||||
which will show up as a warning, but which will not fail the build. When a test is reported as unreliable,
|
||||
we include the results for each individual run via a JSON string in the original test's errorMessage field.
|
||||
6. TAEF produces logs in WTT format. Helix is able to process logs in XUnit format. We run
|
||||
[ConvertWttLogToXUnit.ps1](ConvertWttLogToXUnit.ps1) to convert the logs into the necessary format.
|
||||
7. RunTestsInHelix.proj has EnableAzurePipelinesReporter set to true. This allows the XUnit formatted test
|
||||
results to be reported back to the Azure DevOps Pipeline.
|
||||
8. We process unreliable tests once all tests have been reported by reading the JSON string from the
|
||||
errorMessage field and calling the Azure DevOps REST API to modify the unreliable tests to have sub-results
|
||||
added to the test and to mark the test as "warning", which will enable people to see exactly how the test
|
||||
failed in runs where it did.
|
||||
@@ -1,105 +0,0 @@
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
|
||||
echo %TIME%
|
||||
|
||||
robocopy %HELIX_CORRELATION_PAYLOAD% . /s /NP > NUL
|
||||
|
||||
echo %TIME%
|
||||
|
||||
reg add HKLM\Software\Policies\Microsoft\Windows\Appx /v AllowAllTrustedApps /t REG_DWORD /d 1 /f
|
||||
|
||||
rem enable dump collection for our test apps:
|
||||
rem note, this script is run from a 32-bit cmd, but we need to set the native reg-key
|
||||
FOR %%A IN (TestHostApp.exe,te.exe,te.processhost.exe,conhost.exe,OpenConsole.exe,WindowsTerminal.exe) DO (
|
||||
%systemroot%\sysnative\cmd.exe /c reg add "HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\%%A" /v DumpFolder /t REG_EXPAND_SZ /d %HELIX_DUMP_FOLDER% /f
|
||||
%systemroot%\sysnative\cmd.exe /c reg add "HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\%%A" /v DumpType /t REG_DWORD /d 2 /f
|
||||
%systemroot%\sysnative\cmd.exe /c reg add "HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\%%A" /v DumpCount /t REG_DWORD /d 10 /f
|
||||
)
|
||||
|
||||
echo %TIME%
|
||||
|
||||
:: kill dhandler, which is a tool designed to handle unexpected windows appearing. But since our tests are
|
||||
:: expected to show UI we don't want it running.
|
||||
taskkill -f -im dhandler.exe
|
||||
|
||||
echo %TIME%
|
||||
powershell -ExecutionPolicy Bypass .\EnsureMachineState.ps1
|
||||
echo %TIME%
|
||||
powershell -ExecutionPolicy Bypass .\InstallTestAppDependencies.ps1
|
||||
echo %TIME%
|
||||
|
||||
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll WindowsTerminal.UIA.Tests.dll
|
||||
set testBinaries=
|
||||
for %%B in (%testBinaryCandidates%) do (
|
||||
if exist %%B (
|
||||
set "testBinaries=!testBinaries! %%B"
|
||||
)
|
||||
)
|
||||
|
||||
echo %TIME%
|
||||
te.exe %testBinaries% /enablewttlogging /unicodeOutput:false /sessionTimeout:0:15 /testtimeout:0:10 /screenCaptureOnError %*
|
||||
echo %TIME%
|
||||
|
||||
powershell -ExecutionPolicy Bypass Get-Process
|
||||
|
||||
move te.wtl te_original.wtl
|
||||
|
||||
copy /y te_original.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y *.pgc %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
|
||||
set FailedTestQuery=
|
||||
for /F "tokens=* usebackq" %%I IN (`powershell -ExecutionPolicy Bypass .\OutputFailedTestQuery.ps1 te_original.wtl`) DO (
|
||||
set FailedTestQuery=%%I
|
||||
)
|
||||
|
||||
rem The first time, we'll just re-run failed tests once. In many cases, tests fail very rarely, such that
|
||||
rem a single re-run will be sufficient to detect many unreliable tests.
|
||||
if "%FailedTestQuery%" == "" goto :SkipReruns
|
||||
|
||||
echo %TIME%
|
||||
te.exe %testBinaries% /enablewttlogging /unicodeOutput:false /sessionTimeout:0:15 /testtimeout:0:10 /screenCaptureOnError /select:"%FailedTestQuery%"
|
||||
echo %TIME%
|
||||
|
||||
move te.wtl te_rerun.wtl
|
||||
|
||||
copy /y te_rerun.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
|
||||
rem If there are still failing tests remaining, we'll run them eight more times, so they'll have been run a total of ten times.
|
||||
rem If any tests fail all ten times, we can be pretty confident that these are actual test failures rather than unreliable tests.
|
||||
if not exist te_rerun.wtl goto :SkipReruns
|
||||
|
||||
set FailedTestQuery=
|
||||
for /F "tokens=* usebackq" %%I IN (`powershell -ExecutionPolicy Bypass .\OutputFailedTestQuery.ps1 te_rerun.wtl`) DO (
|
||||
set FailedTestQuery=%%I
|
||||
)
|
||||
|
||||
if "%FailedTestQuery%" == "" goto :SkipReruns
|
||||
|
||||
echo %TIME%
|
||||
te.exe %testBinaries% /enablewttlogging /unicodeOutput:false /sessionTimeout:0:15 /testtimeout:0:10 /screenCaptureOnError /testmode:Loop /LoopTest:8 /select:"%FailedTestQuery%"
|
||||
echo %TIME%
|
||||
|
||||
powershell -ExecutionPolicy Bypass Get-Process
|
||||
|
||||
move te.wtl te_rerun_multiple.wtl
|
||||
|
||||
copy /y te_rerun_multiple.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
powershell -ExecutionPolicy Bypass .\CopyVisualTreeVerificationFiles.ps1
|
||||
|
||||
:SkipReruns
|
||||
|
||||
powershell -ExecutionPolicy Bypass Get-Process
|
||||
|
||||
echo %TIME%
|
||||
powershell -ExecutionPolicy Bypass .\OutputSubResultsJsonFiles.ps1 te_original.wtl te_rerun.wtl te_rerun_multiple.wtl %testnameprefix%
|
||||
powershell -ExecutionPolicy Bypass .\ConvertWttLogToXUnit.ps1 te_original.wtl te_rerun.wtl te_rerun_multiple.wtl testResults.xml %testnameprefix%
|
||||
echo %TIME%
|
||||
|
||||
copy /y *_subresults.json %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
|
||||
type testResults.xml
|
||||
|
||||
echo %TIME%
|
||||
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"Version": "1.0.0",
|
||||
"UseMinimatch": false,
|
||||
"SignBatches": [
|
||||
{
|
||||
"MatchedPath": [
|
||||
"conpty.dll",
|
||||
"OpenConsole.exe"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
47
build/config/esrp.build.batch.conpty.json
Normal file
47
build/config/esrp.build.batch.conpty.json
Normal file
@@ -0,0 +1,47 @@
|
||||
[
|
||||
{
|
||||
"MatchedPath": [
|
||||
"conpty.dll",
|
||||
"OpenConsole.exe"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
65
build/config/esrp.build.batch.terminal_constituents.json
Normal file
65
build/config/esrp.build.batch.terminal_constituents.json
Normal file
@@ -0,0 +1,65 @@
|
||||
[
|
||||
{
|
||||
"MatchedPath": [
|
||||
// Namespaced DLLs
|
||||
"PackageContents/Microsoft.Terminal.*.dll",
|
||||
"PackageContents/Microsoft.Terminal.*.winmd",
|
||||
|
||||
// ConPTY and DefTerm
|
||||
"PackageContents/OpenConsole.exe",
|
||||
"PackageContents/OpenConsoleProxy.dll",
|
||||
|
||||
// Legacy DLLs with old names
|
||||
"PackageContents/TerminalApp.dll",
|
||||
"PackageContents/TerminalApp.winmd",
|
||||
"PackageContents/TerminalConnection.dll",
|
||||
"PackageContents/TerminalThemeHelpers.dll",
|
||||
"PackageContents/WindowsTerminalShellExt.dll",
|
||||
|
||||
// The rest
|
||||
"PackageContents/TerminalAzBridge.exe",
|
||||
"PackageContents/wt.exe",
|
||||
"PackageContents/WindowsTerminal.exe",
|
||||
"PackageContents/elevate-shim.exe"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
46
build/config/esrp.build.batch.wpf.json
Normal file
46
build/config/esrp.build.batch.wpf.json
Normal file
@@ -0,0 +1,46 @@
|
||||
[
|
||||
{
|
||||
"MatchedPath": [
|
||||
"PublicTerminalCore.dll"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
47
build/config/esrp.build.batch.wpfdotnet.json
Normal file
47
build/config/esrp.build.batch.wpfdotnet.json
Normal file
@@ -0,0 +1,47 @@
|
||||
[
|
||||
{
|
||||
"MatchedPath": [
|
||||
"WpfTerminalControl/net472/Microsoft.Terminal.Wpf.dll",
|
||||
"WpfTerminalControl/net6.0-windows/Microsoft.Terminal.Wpf.dll"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
1127
build/config/release.gdnbaselines
Normal file
1127
build/config/release.gdnbaselines
Normal file
File diff suppressed because it is too large
Load Diff
6
build/config/tsa.json
Normal file
6
build/config/tsa.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"instanceUrl": "https://microsoft.visualstudio.com",
|
||||
"projectName": "OS",
|
||||
"areaPath": "OS\\Windows Client and Services\\ADEPT\\E4D-Engineered for Developers\\SHINE\\Terminal",
|
||||
"notificationAliases": ["condev@microsoft.com", "duhowett@microsoft.com"]
|
||||
}
|
||||
@@ -3,8 +3,6 @@
|
||||
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
|
||||
<!-- This cannot be included in another project that depends on XAML (as it would be a duplicate package ID) -->
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
|
||||
<package id="Microsoft.Debugging.Tools.PdbStr" version="20220617.1556.0" targetFramework="native" />
|
||||
<package id="Microsoft.Debugging.Tools.SrcTool" version="20220617.1556.0" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="Terminal.PGO.props" />
|
||||
<Import Project="$(PkgMicrosoft_PGO_Helpers_Cpp)\build\Microsoft.PGO-Helpers.Cpp.props" />
|
||||
<Import Project="$(PkgMicrosoft_PGO_Helpers_Cpp)\build\Microsoft.PGO-Helpers.Cpp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -12,5 +12,6 @@
|
||||
<files>
|
||||
<!-- The target directories for pgd files need to remain as is. PGO optimization pass will rely on this exact directory layout. -->
|
||||
<file src="x64\*.pgd" target="tools\x64"/>
|
||||
<file src="arm64\*.pgd" target="tools\arm64"/>
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Optional, defaults to main. Name of the branch which will be used for calculating branch point. -->
|
||||
<PGOBranch>main</PGOBranch>
|
||||
<PGOBranch>release-1.17</PGOBranch>
|
||||
|
||||
<!-- Mandatory. Name of the NuGet package which will contain PGO databases for consumption by build system. -->
|
||||
<PGOPackageName>Microsoft.Internal.Windows.Terminal.PGODatabase</PGOPackageName>
|
||||
@@ -46,6 +46,5 @@
|
||||
<PGOCopyRuntime Condition="'$(PGOBuildMode)' == 'Instrument'">true</PGOCopyRuntime>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Import PGO-Helpers -->
|
||||
<Import Project="$(PkgMicrosoft_PGO_Helpers_Cpp)\build\Microsoft.PGO-Helpers.Cpp.props" />
|
||||
<!-- Do not import PGO-Helpers props here, as it is too early to detect the C++ tools directory -->
|
||||
</Project>
|
||||
|
||||
@@ -29,76 +29,80 @@ variables:
|
||||
# 0.0.1904.0900
|
||||
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
|
||||
|
||||
parameters:
|
||||
- name: auditMode
|
||||
displayName: "Build in Audit Mode (x64)"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: runTests
|
||||
displayName: "Run Tests"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- x86
|
||||
- arm64
|
||||
|
||||
stages:
|
||||
- stage: Audit_x64
|
||||
displayName: Audit Mode
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/build-console-audit-job.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- ${{ if eq(parameters.auditMode, true) }}:
|
||||
- stage: Audit_x64
|
||||
displayName: Audit Mode
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./templates-v2/job-build-project.yml
|
||||
parameters:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-INT-L
|
||||
buildPlatforms: [x64]
|
||||
buildConfigurations: [AuditMode]
|
||||
buildEverything: true
|
||||
keepAllExpensiveBuildOutputs: false
|
||||
|
||||
- stage: Build_x64
|
||||
displayName: Build x64
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- stage: Build_x86
|
||||
displayName: Build x86
|
||||
- stage: CodeHealth
|
||||
displayName: Code Health
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: x86
|
||||
- stage: Build_ARM64
|
||||
displayName: Build ARM64
|
||||
dependsOn: []
|
||||
condition: not(eq(variables['Build.Reason'], 'PullRequest'))
|
||||
jobs:
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: ARM64
|
||||
- template: ./templates-v2/job-check-code-format.yml
|
||||
|
||||
- stage: Test_x64
|
||||
displayName: Test x64
|
||||
dependsOn: [Build_x64]
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/test-console-ci.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- stage: Test_x86
|
||||
displayName: Test x86
|
||||
dependsOn: [Build_x86]
|
||||
jobs:
|
||||
- template: ./templates/test-console-ci.yml
|
||||
parameters:
|
||||
platform: x86
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- stage: Build_${{ platform }}
|
||||
displayName: Build ${{ platform }}
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./templates-v2/job-build-project.yml
|
||||
parameters:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-INT-L
|
||||
buildPlatforms:
|
||||
- ${{ platform }}
|
||||
buildConfigurations: [Release]
|
||||
buildEverything: true
|
||||
keepAllExpensiveBuildOutputs: false
|
||||
|
||||
- stage: Helix_x64
|
||||
displayName: Helix x64
|
||||
dependsOn: [Build_x64]
|
||||
condition: and(succeeded(), not(eq(variables['Build.Reason'], 'PullRequest')))
|
||||
jobs:
|
||||
- template: ./templates/console-ci-helix-job.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- ${{ if eq(parameters.runTests, true) }}:
|
||||
- stage: Test_${{ platform }}
|
||||
displayName: Test ${{ platform }}
|
||||
dependsOn:
|
||||
- Build_${{ platform }}
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates-v2/job-test-project.yml
|
||||
parameters:
|
||||
platform: ${{ platform }}
|
||||
# The tests might be run more than once; log one artifact per attempt.
|
||||
outputArtifactStem: -$(System.JobAttempt)
|
||||
|
||||
- stage: Scripts
|
||||
displayName: Code Health Scripts
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/check-formatting.yml
|
||||
|
||||
|
||||
- stage: CodeIndexer
|
||||
displayName: Github CodeNav Indexer
|
||||
dependsOn: [Build_x64]
|
||||
condition: and(succeeded(), not(eq(variables['Build.Reason'], 'PullRequest')))
|
||||
jobs:
|
||||
- template: ./templates/codenav-indexer.yml
|
||||
- ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
|
||||
- stage: CodeIndexer
|
||||
displayName: Github CodeNav Indexer
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./templates-v2/job-index-github-codenav.yml
|
||||
|
||||
@@ -27,6 +27,7 @@ steps:
|
||||
clean: true
|
||||
submodules: false
|
||||
fetchDepth: 1 # Don't need a deep checkout for loc files!
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
persistCredentials: true
|
||||
path: s # Adding a second repo made Azure DevOps change where we're checked out.
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ pr:
|
||||
paths:
|
||||
include:
|
||||
- src/features.xml
|
||||
- build/pipelines/feature-flag-ci.yml
|
||||
|
||||
variables:
|
||||
- name: runCodesignValidationInjectionBG
|
||||
@@ -21,9 +22,19 @@ parameters:
|
||||
# Dev is built automatically
|
||||
# WindowsInbox does not typically build with VS.
|
||||
|
||||
jobs:
|
||||
stages:
|
||||
- ${{ each branding in parameters.buildBrandings }}:
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
branding: ${{ branding }}
|
||||
- stage: Build_${{ branding }}
|
||||
dependsOn: []
|
||||
displayName: Build ${{ branding }}
|
||||
jobs:
|
||||
- template: ./templates-v2/job-build-project.yml
|
||||
parameters:
|
||||
pool: # This only runs in CI
|
||||
name: SHINE-OSS-L
|
||||
buildPlatforms: [x64]
|
||||
buildConfigurations: [Release]
|
||||
buildEverything: true
|
||||
branding: ${{ branding }}
|
||||
keepAllExpensiveBuildOutputs: false
|
||||
artifactStem: -${{ branding }} # Disambiguate artifacts with the same config/platform
|
||||
|
||||
@@ -16,44 +16,52 @@ pr: none
|
||||
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
|
||||
|
||||
stages:
|
||||
- stage: Build_Fuzz_Config
|
||||
displayName: Build Fuzzers
|
||||
- stage: Build
|
||||
displayName: Fuzzing Build
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/build-console-fuzzing.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- stage: OneFuzz
|
||||
displayName: Submit OneFuzz Job
|
||||
dependsOn: ['Build_Fuzz_Config']
|
||||
- template: ./templates-v2/job-build-project.yml
|
||||
parameters:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-INT-L
|
||||
buildPlatforms: [x64]
|
||||
buildConfigurations: [Fuzzing]
|
||||
buildEverything: true
|
||||
keepAllExpensiveBuildOutputs: false
|
||||
|
||||
- stage: Submit
|
||||
displayName: Submit to OneFuzz
|
||||
dependsOn: [Build]
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
variables:
|
||||
artifactName: fuzzingBuildOutput
|
||||
jobs:
|
||||
- job:
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
inputs:
|
||||
artifactName: $(artifactName)
|
||||
downloadPath: $(Build.ArtifactStagingDirectory)
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '3.x'
|
||||
addToPath: true
|
||||
architecture: 'x64'
|
||||
- bash: |
|
||||
set -ex
|
||||
pip -q install onefuzz
|
||||
onefuzz config --endpoint $(endpoint) --client_id $(client_id) --authority $(authority) --tenant_domain $(tenant_domain) --client_secret $(client_secret)
|
||||
sed -i s/INSERT_PAT_HERE/$(ado_pat)/ build/Fuzz/notifications-ado.json
|
||||
sed -i s/INSERT_ASSIGNED_HERE/$(ado_assigned_to)/ build/Fuzz/notifications-ado.json
|
||||
displayName: Configure OneFuzz
|
||||
- bash: |
|
||||
onefuzz template libfuzzer basic --colocate_all_tasks --vm_count 1 --target_exe $target_exe_path --notification_config @./build/Fuzz/notifications-ado.json OpenConsole $test_name $(Build.SourceVersion) default
|
||||
displayName: Submit OneFuzz Job
|
||||
env:
|
||||
target_exe_path: $(Build.ArtifactStagingDirectory)/$(artifactName)/Fuzzing/x64/test/OpenConsoleFuzzer.exe
|
||||
test_name: WriteCharsLegacy
|
||||
- job:
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download artifacts
|
||||
inputs:
|
||||
artifactName: build-x64-Fuzzing
|
||||
downloadPath: $(Build.ArtifactStagingDirectory)
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '3.x'
|
||||
addToPath: true
|
||||
architecture: 'x64'
|
||||
- bash: |
|
||||
set -ex
|
||||
pip -q install onefuzz
|
||||
onefuzz config --endpoint $(endpoint) --client_id $(client_id) --authority $(authority) --tenant_domain $(tenant_domain) --client_secret $(client_secret)
|
||||
sed -i s/INSERT_PAT_HERE/$(ado_pat)/ build/Fuzz/notifications-ado.json
|
||||
sed -i s/INSERT_ASSIGNED_HERE/$(ado_assigned_to)/ build/Fuzz/notifications-ado.json
|
||||
displayName: Configure OneFuzz
|
||||
- bash: |
|
||||
onefuzz template libfuzzer basic --colocate_all_tasks --vm_count 1 --target_exe $target_exe_path --notification_config @./build/Fuzz/notifications-ado.json OpenConsole $test_name $(Build.SourceVersion) default
|
||||
displayName: Submit OneFuzz Job
|
||||
env:
|
||||
target_exe_path: $(Build.ArtifactStagingDirectory)/OpenConsoleFuzzer.exe
|
||||
test_name: WriteCharsLegacy
|
||||
|
||||
23
build/pipelines/nightly.yml
Normal file
23
build/pipelines/nightly.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
trigger: none
|
||||
pr: none
|
||||
schedules:
|
||||
- cron: "30 3 * * 2-6" # Run at 03:30 UTC Tuesday through Saturday (After the work day in Pacific, Mon-Fri)
|
||||
displayName: "Nightly Terminal Build"
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
always: false # only run if there's code changes!
|
||||
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
|
||||
extends:
|
||||
template: templates-v2\pipeline-full-release-build.yml
|
||||
parameters:
|
||||
branding: Canary
|
||||
buildTerminal: true
|
||||
pgoBuildMode: Optimize
|
||||
codeSign: true
|
||||
generateSbom: true
|
||||
publishSymbolsToPublic: true
|
||||
publishVpackToWindows: false
|
||||
symbolExpiryTime: 15 # Nightly builds do not keep symbols for very long!
|
||||
49
build/pipelines/ob-nightly.yml
Normal file
49
build/pipelines/ob-nightly.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
trigger: none
|
||||
pr: none
|
||||
schedules:
|
||||
- cron: "30 3 * * 2-6" # Run at 03:30 UTC Tuesday through Saturday (After the work day in Pacific, Mon-Fri)
|
||||
displayName: "Nightly Terminal Build"
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
always: false # only run if there's code changes!
|
||||
|
||||
parameters:
|
||||
- name: publishToAzure
|
||||
displayName: "Deploy to **PUBLIC** Azure Storage"
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
|
||||
variables:
|
||||
- template: templates-v2/variables-nuget-package-version.yml
|
||||
parameters:
|
||||
branding: Canary
|
||||
- template: templates-v2/variables-onebranch-config.yml
|
||||
|
||||
extends:
|
||||
template: templates-v2/pipeline-onebranch-full-release-build.yml
|
||||
parameters:
|
||||
official: true
|
||||
branding: Canary
|
||||
buildTerminal: true
|
||||
pgoBuildMode: Optimize
|
||||
codeSign: true
|
||||
publishSymbolsToPublic: true
|
||||
publishVpackToWindows: false
|
||||
symbolExpiryTime: 15
|
||||
${{ if eq(true, parameters.publishToAzure) }}:
|
||||
extraPublishJobs:
|
||||
- template: job-deploy-to-azure-storage.yml
|
||||
parameters:
|
||||
pool: { type: windows }
|
||||
dependsOn: [PublishSymbols]
|
||||
storagePublicRootURL: $(AppInstallerRootURL)
|
||||
subscription: $(AzureSubscriptionName)
|
||||
storageAccount: $(AzureStorageAccount)
|
||||
storageContainer: $(AzureStorageContainer)
|
||||
buildConfiguration: Release
|
||||
buildPlatforms: [x64, x86, arm64]
|
||||
environment: production-canary
|
||||
|
||||
83
build/pipelines/ob-release.yml
Normal file
83
build/pipelines/ob-release.yml
Normal file
@@ -0,0 +1,83 @@
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
# Expose all of these parameters for user configuration.
|
||||
parameters:
|
||||
- name: branding
|
||||
displayName: "Branding (Build Type)"
|
||||
type: string
|
||||
default: Release
|
||||
values:
|
||||
- Release
|
||||
- Preview
|
||||
- Canary
|
||||
- Dev
|
||||
- name: buildTerminal
|
||||
displayName: "Build Windows Terminal MSIX"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildConPTY
|
||||
displayName: "Build ConPTY NuGet"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildWPF
|
||||
displayName: "Build Terminal WPF Control"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pgoBuildMode
|
||||
displayName: "PGO Build Mode"
|
||||
type: string
|
||||
default: Optimize
|
||||
values:
|
||||
- Optimize
|
||||
- Instrument
|
||||
- None
|
||||
- name: buildConfigurations
|
||||
displayName: "Build Configurations"
|
||||
type: object
|
||||
default:
|
||||
- Release
|
||||
- name: buildPlatforms
|
||||
displayName: "Build Platforms"
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- x86
|
||||
- arm64
|
||||
- name: terminalInternalPackageVersion
|
||||
displayName: "Terminal Internal Package Version"
|
||||
type: string
|
||||
default: '0.0.8'
|
||||
|
||||
- name: publishSymbolsToPublic
|
||||
displayName: "Publish Symbols to MSDL"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: publishVpackToWindows
|
||||
displayName: "Publish VPack to Windows"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
|
||||
variables:
|
||||
- template: templates-v2/variables-nuget-package-version.yml
|
||||
parameters:
|
||||
branding: ${{ parameters.branding }}
|
||||
- template: templates-v2/variables-onebranch-config.yml
|
||||
|
||||
extends:
|
||||
template: templates-v2/pipeline-onebranch-full-release-build.yml
|
||||
parameters:
|
||||
official: true
|
||||
branding: ${{ parameters.branding }}
|
||||
buildTerminal: ${{ parameters.buildTerminal }}
|
||||
buildConPTY: ${{ parameters.buildConPTY }}
|
||||
buildWPF: ${{ parameters.buildWPF }}
|
||||
pgoBuildMode: ${{ parameters.pgoBuildMode }}
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
codeSign: true
|
||||
terminalInternalPackageVersion: ${{ parameters.terminalInternalPackageVersion }}
|
||||
publishSymbolsToPublic: ${{ parameters.publishSymbolsToPublic }}
|
||||
publishVpackToWindows: ${{ parameters.publishVpackToWindows }}
|
||||
@@ -1,5 +1,27 @@
|
||||
trigger: none
|
||||
pr: none
|
||||
schedules:
|
||||
- cron: "0 5 * * 2-6" # Run at 05:00 UTC Tuesday through Saturday (Even later than Localization, after the work day in Pacific, Mon-Fri)
|
||||
displayName: "Nightly Instrumentation Build"
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
always: false # only run if there's code changes!
|
||||
|
||||
parameters:
|
||||
- name: branding
|
||||
displayName: "Branding (Build Type)"
|
||||
type: string
|
||||
default: Preview # By default, we'll PGO the Preview builds to get max coverage
|
||||
values:
|
||||
- Release
|
||||
- Preview
|
||||
- Dev
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- arm64
|
||||
|
||||
variables:
|
||||
- name: runCodesignValidationInjectionBG
|
||||
@@ -10,18 +32,57 @@ variables:
|
||||
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
|
||||
|
||||
stages:
|
||||
- stage: Build_x64
|
||||
displayName: Build x64
|
||||
- stage: Build
|
||||
displayName: Build
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/build-console-pgo.yml
|
||||
- template: ./templates-v2/job-build-project.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- stage: Publish_PGO_Databases
|
||||
displayName: Publish PGO databases
|
||||
dependsOn: ['Build_x64']
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-INT-L
|
||||
branding: ${{ parameters.branding }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
buildConfigurations: [Release]
|
||||
buildEverything: true
|
||||
pgoBuildMode: Instrument
|
||||
artifactStem: -instrumentation
|
||||
|
||||
- stage: RunPGO
|
||||
displayName: Run PGO
|
||||
dependsOn: [Build]
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/pgo-build-and-publish-nuget-job.yml
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- template: ./templates-v2/job-run-pgo-tests.yml
|
||||
parameters:
|
||||
# This job chooses its own pools based on platform
|
||||
buildPlatform: ${{ platform }}
|
||||
buildConfiguration: Release
|
||||
artifactStem: -instrumentation
|
||||
|
||||
- stage: FinalizePGO
|
||||
displayName: Finalize PGO and Publish
|
||||
dependsOn: [RunPGO]
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
# This job takes multiple platforms and fans them back in to a single artifact.
|
||||
- template: ./templates-v2/job-pgo-merge-pgd.yml
|
||||
parameters:
|
||||
pgoArtifact: 'PGO'
|
||||
jobName: MergePGD
|
||||
pool:
|
||||
vmImage: 'windows-2022'
|
||||
buildConfiguration: Release
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
artifactStem: -instrumentation
|
||||
|
||||
- template: ./templates-v2/job-pgo-build-nuget-and-publish.yml
|
||||
parameters:
|
||||
pool:
|
||||
vmImage: 'windows-2022'
|
||||
dependsOn: MergePGD
|
||||
buildConfiguration: Release
|
||||
artifactStem: -instrumentation
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
# This build should never run as CI or against a pull request.
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
pool:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
# Expose all of these parameters for user configuration.
|
||||
parameters:
|
||||
- name: branding
|
||||
displayName: "Branding (Build Type)"
|
||||
@@ -14,22 +10,11 @@ parameters:
|
||||
values:
|
||||
- Release
|
||||
- Preview
|
||||
- Dev
|
||||
- name: buildTerminal
|
||||
displayName: "Build Windows Terminal MSIX"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: runCompliance
|
||||
displayName: "Run Compliance and Security Build"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: publishSymbolsToPublic
|
||||
displayName: "Publish Symbols to MSDL"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildTerminalVPack
|
||||
displayName: "Build Windows Terminal VPack"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildConPTY
|
||||
displayName: "Build ConPTY NuGet"
|
||||
type: boolean
|
||||
@@ -47,677 +32,57 @@ parameters:
|
||||
- Instrument
|
||||
- None
|
||||
- name: buildConfigurations
|
||||
displayName: "Build Configurations"
|
||||
type: object
|
||||
default:
|
||||
- Release
|
||||
- name: buildPlatforms
|
||||
displayName: "Build Platforms"
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- x86
|
||||
- arm64
|
||||
- name: buildWindowsVersions
|
||||
type: object
|
||||
default:
|
||||
- Win10
|
||||
- Win11
|
||||
- name: codeSign
|
||||
displayName: "Sign all build outputs"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: generateSbom
|
||||
displayName: "Generate a Bill of Materials"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: terminalInternalPackageVersion
|
||||
displayName: "Terminal Internal Package Version"
|
||||
type: string
|
||||
default: '0.0.8'
|
||||
|
||||
variables:
|
||||
TerminalInternalPackageVersion: "0.0.7"
|
||||
# If we are building a branch called "release-*", change the NuGet suffix
|
||||
# to "preview". If we don't do that, XES will set the suffix to "release1"
|
||||
# because it truncates the value after the first period.
|
||||
# We also want to disable the suffix entirely if we're Release branded while
|
||||
# on a release branch.
|
||||
# main is special, however. XES ignores main. Since we never produce actual
|
||||
# shipping builds from main, we want to force it to have a beta label as
|
||||
# well.
|
||||
#
|
||||
# In effect:
|
||||
# BRANCH / BRANDING | Release | Preview
|
||||
# ------------------|----------------------------|-----------------------------
|
||||
# release-* | 1.12.20220427 | 1.13.20220427-preview
|
||||
# main | 1.14.20220427-experimental | 1.14.20220427-experimental
|
||||
# all others | 1.14.20220427-mybranch | 1.14.20220427-mybranch
|
||||
${{ if startsWith(variables['Build.SourceBranchName'], 'release-') }}:
|
||||
${{ if eq(parameters.branding, 'Release') }}:
|
||||
NoNuGetPackBetaVersion: true
|
||||
${{ else }}:
|
||||
NuGetPackBetaVersion: preview
|
||||
${{ elseif eq(variables['Build.SourceBranchName'], 'main') }}:
|
||||
NuGetPackBetaVersion: experimental
|
||||
# The NuGet packages have to use *somebody's* DLLs. We used to force them to
|
||||
# use the Win10 build outputs, but if there isn't a Win10 build we should use
|
||||
# the Win11 one.
|
||||
${{ if containsValue(parameters.buildWindowsVersions, 'Win10') }}:
|
||||
TerminalBestVersionForNuGetPackages: Win10
|
||||
${{ else }}:
|
||||
TerminalBestVersionForNuGetPackages: Win11
|
||||
- name: runCompliance
|
||||
displayName: "Run Compliance and Security Build"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: publishSymbolsToPublic
|
||||
displayName: "Publish Symbols to MSDL"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: publishVpackToWindows
|
||||
displayName: "Publish VPack to Windows"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
resources:
|
||||
repositories:
|
||||
- repository: self
|
||||
type: git
|
||||
ref: main
|
||||
jobs:
|
||||
- job: Build
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ each platform in parameters.buildPlatforms }}:
|
||||
${{ each windowsVersion in parameters.buildWindowsVersions }}:
|
||||
${{ config }}_${{ platform }}_${{ windowsVersion }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
BuildPlatform: ${{ platform }}
|
||||
TerminalTargetWindowsVersion: ${{ windowsVersion }}
|
||||
displayName: Build
|
||||
timeoutInMinutes: 240
|
||||
cancelTimeoutInMinutes: 1
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- task: PowerShell@2
|
||||
displayName: Rationalize Build Platform
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Arch = "$(BuildPlatform)"
|
||||
|
||||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
- template: .\templates\restore-nuget-steps.yml
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
|
||||
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
|
||||
versionListDownload: $(TerminalInternalPackageVersion)
|
||||
- task: TouchdownBuildTask@1
|
||||
displayName: Download Localization Files
|
||||
inputs:
|
||||
teamId: 7105
|
||||
authId: $(TouchdownAppId)
|
||||
authKey: $(TouchdownAppKey)
|
||||
resourceFilePath: >-
|
||||
src\cascadia\TerminalApp\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalApp\Resources\en-US\ContextMenu.resw
|
||||
|
||||
src\cascadia\TerminalControl\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalConnection\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalSettingsModel\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw
|
||||
appendRelativeDir: true
|
||||
localizationTarget: false
|
||||
pseudoSetting: Included
|
||||
- task: PowerShell@2
|
||||
displayName: Move Loc files one level up
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw'
|
||||
|
||||
$Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore }
|
||||
pwsh: true
|
||||
- task: PowerShell@2
|
||||
displayName: Copy the Context Menu Loc Resources to CascadiaPackage
|
||||
inputs:
|
||||
filePath: ./build/scripts/Copy-ContextMenuResourcesToCascadiaPackage.ps1
|
||||
pwsh: true
|
||||
- task: PowerShell@2
|
||||
displayName: Generate NOTICE.html from NOTICE.md
|
||||
inputs:
|
||||
filePath: .\build\scripts\Generate-ThirdPartyNotices.ps1
|
||||
arguments: -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
|
||||
pwsh: true
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- pwsh: |-
|
||||
./build/scripts/Patch-ManifestsToWindowsVersion.ps1 -NewWindowsVersion "10.0.22000.0"
|
||||
displayName: Update manifest target version to Win11 (if necessary)
|
||||
condition: and(succeeded(), eq(variables['TerminalTargetWindowsVersion'], 'Win11'))
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln
|
||||
condition: true
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /t:Terminal\CascadiaPackage /p:WindowsTerminalReleaseBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: true
|
||||
maximumCpuCount: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: binlog'
|
||||
condition: failed()
|
||||
continueOnError: True
|
||||
inputs:
|
||||
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
|
||||
ArtifactName: binlog-$(BuildPlatform)-$(TerminalTargetWindowsVersion)
|
||||
- task: PowerShell@2
|
||||
displayName: Check MSIX for common regressions
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix"
|
||||
|
||||
.\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName
|
||||
pwsh: true
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln for PublicTerminalCore
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /p:WindowsTerminalReleaseBuild=true /t:Terminal\wpf\PublicTerminalCore
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
- ${{ if eq(parameters.buildConPTY, true) }}:
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln for ConPTY
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /p:WindowsTerminalReleaseBuild=true /t:Conhost\Host_EXE;Conhost\winconpty_DLL
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
- task: PowerShell@2
|
||||
displayName: Source Index PDBs
|
||||
inputs:
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
|
||||
errorActionPreference: silentlyContinue
|
||||
pwsh: true
|
||||
- task: PowerShell@2
|
||||
displayName: Run Unit Tests
|
||||
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
enabled: False
|
||||
inputs:
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
|
||||
- task: PowerShell@2
|
||||
displayName: Run Feature Tests
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
|
||||
enabled: False
|
||||
inputs:
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy *.appx/*.msix to Artifacts
|
||||
inputs:
|
||||
Contents: >-
|
||||
**/*.appx
|
||||
|
||||
**/*.msix
|
||||
|
||||
**/*.appxsym
|
||||
|
||||
!**/Microsoft.VCLibs*.appx
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
|
||||
displayName: 'Generate SBOM manifest'
|
||||
inputs:
|
||||
BuildDropPath: '$(System.ArtifactsDirectory)/appx'
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (appx)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
|
||||
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
|
||||
- ${{ if eq(parameters.buildConPTY, true) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy ConPTY to Artifacts
|
||||
inputs:
|
||||
Contents: |-
|
||||
$(Build.SourcesDirectory)/bin/**/conpty.dll
|
||||
$(Build.SourcesDirectory)/bin/**/conpty.lib
|
||||
$(Build.SourcesDirectory)/bin/**/conpty.pdb
|
||||
$(Build.SourcesDirectory)/bin/**/OpenConsole.exe
|
||||
$(Build.SourcesDirectory)/bin/**/OpenConsole.pdb
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/conpty
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (ConPTY)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)/conpty
|
||||
ArtifactName: conpty-dll-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy PublicTerminalCore.dll to Artifacts
|
||||
inputs:
|
||||
Contents: >-
|
||||
**/PublicTerminalCore.dll
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/wpf
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (PublicTerminalCore)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)/wpf
|
||||
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
|
||||
|
||||
- task: PublishSymbols@2
|
||||
displayName: Publish symbols path
|
||||
continueOnError: True
|
||||
inputs:
|
||||
SearchPattern: |
|
||||
$(Build.SourcesDirectory)/bin/**/*.pdb
|
||||
$(Build.SourcesDirectory)/bin/**/*.exe
|
||||
$(Build.SourcesDirectory)/bin/**/*.dll
|
||||
IndexSources: false
|
||||
SymbolServerType: TeamServices
|
||||
|
||||
- ${{ if eq(parameters.runCompliance, true) }}:
|
||||
- template: ./templates/build-console-compliance-job.yml
|
||||
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- job: BundleAndSign
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each windowsVersion in parameters.buildWindowsVersions }}:
|
||||
${{ windowsVersion }}:
|
||||
TerminalTargetWindowsVersion: ${{ windowsVersion }}
|
||||
displayName: Create and sign AppX/MSIX bundles
|
||||
variables:
|
||||
${{ if eq(parameters.branding, 'Release') }}:
|
||||
BundleStemName: Microsoft.WindowsTerminal
|
||||
${{ elseif eq(parameters.branding, 'Preview') }}:
|
||||
BundleStemName: Microsoft.WindowsTerminalPreview
|
||||
${{ else }}:
|
||||
BundleStemName: WindowsTerminalDev
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Artifacts ${{ platform }} $(TerminalTargetWindowsVersion)
|
||||
inputs:
|
||||
artifactName: appx-${{ platform }}-Release-$(TerminalTargetWindowsVersion)
|
||||
# Add 3000 to the major version component, but only for the bundle.
|
||||
# This is to ensure that it is newer than "2022.xx.yy.zz" or whatever the original bundle versions were before
|
||||
# we switched to uniform naming.
|
||||
- pwsh: |-
|
||||
$VersionEpoch = 3000
|
||||
$Components = "$(XES_APPXMANIFESTVERSION)" -Split "\."
|
||||
$Components[0] = ([int]$Components[0] + $VersionEpoch)
|
||||
$BundleVersion = $Components -Join "."
|
||||
New-Item -Type Directory "$(System.ArtifactsDirectory)\bundle"
|
||||
.\build\scripts\Create-AppxBundle.ps1 -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(TerminalTargetWindowsVersion)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
displayName: Create WindowsTerminal*.msixbundle
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.msixbundle to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(System.ArtifactsDirectory)\bundle
|
||||
Pattern: $(BundleStemName)*.msixbundle
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "Dynamic",
|
||||
"CertTemplateName": "WINMSAPP1ST",
|
||||
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
|
||||
"OperationCode": "SigntoolSign",
|
||||
"Parameters": {
|
||||
"OpusName": "Microsoft",
|
||||
"OpusInfo": "http://www.microsoft.com",
|
||||
"FileDigest": "/fd \"SHA256\"",
|
||||
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "Dynamic",
|
||||
"CertTemplateName": "WINMSAPP1ST",
|
||||
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
|
||||
"OperationCode": "SigntoolVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: appxbundle-signed'
|
||||
inputs:
|
||||
PathtoPublish: $(System.ArtifactsDirectory)\bundle
|
||||
ArtifactName: appxbundle-signed-$(TerminalTargetWindowsVersion)
|
||||
|
||||
- ${{ if eq(parameters.buildConPTY, true) }}:
|
||||
- job: PackageAndSignConPTY
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ config }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
displayName: Create NuGet Package (ConPTY)
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download ${{ platform }} ConPTY binaries
|
||||
inputs:
|
||||
artifactName: conpty-dll-${{ platform }}-$(BuildConfiguration)-$(TerminalBestVersionForNuGetPackages)
|
||||
downloadPath: bin\${{ platform }}\$(BuildConfiguration)\
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Move downloaded artifacts around
|
||||
inputs:
|
||||
targetType: inline
|
||||
# Find all artifact files and move them up a directory. Ugh.
|
||||
script: |-
|
||||
Get-ChildItem bin -Recurse -Directory -Filter conpty-dll-* | % {
|
||||
$_ | Get-ChildItem -Recurse -File | % {
|
||||
Move-Item -Verbose $_.FullName $_.Directory.Parent.FullName
|
||||
}
|
||||
}
|
||||
Move-Item bin\x86 bin\Win32
|
||||
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit ConPTY libraries and OpenConsole for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: '$(Build.SourcesDirectory)/bin'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(Build.SourcesDirectory)\build\config\ESRPSigning_ConPTY.json'
|
||||
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Use NuGet 5.10.0
|
||||
inputs:
|
||||
versionSpec: 5.10.0
|
||||
- task: NuGetCommand@2
|
||||
displayName: NuGet pack
|
||||
inputs:
|
||||
command: pack
|
||||
packagesToPack: $(Build.SourcesDirectory)\src\winconpty\package\winconpty.nuspec
|
||||
packDestination: '$(Build.ArtifactStagingDirectory)/nupkg'
|
||||
versioningScheme: byEnvVar
|
||||
versionEnvVar: XES_PACKAGEVERSIONNUMBER
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.nupkg to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
Pattern: '*.nupkg'
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetSign",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (nupkg)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)\nupkg
|
||||
ArtifactName: conpty-nupkg-$(BuildConfiguration)
|
||||
|
||||
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- job: PackageAndSignWPF
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ config }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
displayName: Create NuGet Package (WPF Terminal Control)
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download ${{ platform }} PublicTerminalCore
|
||||
inputs:
|
||||
artifactName: wpf-dll-${{ platform }}-$(BuildConfiguration)-$(TerminalBestVersionForNuGetPackages)
|
||||
itemPattern: '**/*.dll'
|
||||
downloadPath: bin\${{ platform }}\$(BuildConfiguration)\
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Move downloaded artifacts around
|
||||
inputs:
|
||||
targetType: inline
|
||||
# Find all artifact files and move them up a directory. Ugh.
|
||||
script: |-
|
||||
Get-ChildItem bin -Recurse -Directory -Filter wpf-dll-* | % {
|
||||
$_ | Get-ChildItem -Recurse -File | % {
|
||||
Move-Item -Verbose $_.FullName $_.Directory.Parent.FullName
|
||||
}
|
||||
}
|
||||
Move-Item bin\x86 bin\Win32
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Use NuGet 5.10.0
|
||||
inputs:
|
||||
versionSpec: 5.10.0
|
||||
- task: NuGetCommand@2
|
||||
displayName: NuGet restore copy
|
||||
inputs:
|
||||
selectOrConfig: config
|
||||
nugetConfigPath: NuGet.Config
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln for WPF Control
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
msbuildArgs: /p:WindowsTerminalReleaseBuild=$(UseReleaseBranding);Version=$(XES_PACKAGEVERSIONNUMBER) /t:Pack
|
||||
platform: Any CPU
|
||||
configuration: $(BuildConfiguration)
|
||||
maximumCpuCount: true
|
||||
- task: PublishSymbols@2
|
||||
displayName: Publish symbols path
|
||||
continueOnError: True
|
||||
inputs:
|
||||
SearchPattern: |
|
||||
$(Build.SourcesDirectory)/bin/**/*.pdb
|
||||
$(Build.SourcesDirectory)/bin/**/*.exe
|
||||
$(Build.SourcesDirectory)/bin/**/*.dll
|
||||
IndexSources: false
|
||||
SymbolServerType: TeamServices
|
||||
SymbolsArtifactName: Symbols_WPF_$(BuildConfiguration)
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy *.nupkg to Artifacts
|
||||
inputs:
|
||||
Contents: '**/*Wpf*.nupkg'
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.nupkg to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
Pattern: '*.nupkg'
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetSign",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (nupkg)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)\nupkg
|
||||
ArtifactName: wpf-nupkg-$(BuildConfiguration)
|
||||
|
||||
- ${{ if eq(parameters.publishSymbolsToPublic, true) }}:
|
||||
- job: PublishSymbols
|
||||
displayName: Publish Symbols
|
||||
dependsOn: BundleAndSign
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
submodules: true
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
|
||||
- template: .\templates\restore-nuget-steps.yml
|
||||
|
||||
# Download the appx-PLATFORM-CONFIG-VERSION artifact for every platform/version combo
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- ${{ each windowsVersion in parameters.buildWindowsVersions }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Symbols ${{ platform }} ${{ windowsVersion }}
|
||||
inputs:
|
||||
artifactName: appx-${{ platform }}-Release-${{ windowsVersion }}
|
||||
|
||||
# It seems easier to do this -- download every appxsym -- then enumerate all the PDBs in the build directory for the
|
||||
# public symbol push. Otherwise, we would have to list all of the PDB files one by one.
|
||||
- pwsh: |-
|
||||
mkdir $(Build.SourcesDirectory)/appxsym-temp
|
||||
Get-ChildItem "$(System.ArtifactsDirectory)" -Filter *.appxsym -Recurse | % {
|
||||
$src = $_.FullName
|
||||
$dest = Join-Path "$(Build.SourcesDirectory)/appxsym-temp/" $_.Name
|
||||
|
||||
mkdir $dest
|
||||
Write-Host "Extracting $src to $dest..."
|
||||
tar -x -v -f $src -C $dest
|
||||
}
|
||||
displayName: Extract symbols for public consumption
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Source Index PDBs (the public ones)
|
||||
inputs:
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
arguments: -SearchDir '$(Build.SourcesDirectory)/appxsym-temp' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
|
||||
pwsh: true
|
||||
|
||||
# Publish the app symbols to the public MSDL symbol server
|
||||
# accessible via https://msdl.microsoft.com/download/symbols
|
||||
- task: PublishSymbols@2
|
||||
displayName: 'Publish app symbols to MSDL'
|
||||
inputs:
|
||||
symbolsFolder: '$(Build.SourcesDirectory)/appxsym-temp'
|
||||
searchPattern: '**/*.pdb'
|
||||
SymbolsMaximumWaitTime: 30
|
||||
SymbolServerType: 'TeamServices'
|
||||
SymbolsProduct: 'Windows Terminal Application Binaries'
|
||||
SymbolsVersion: '$(XES_APPXMANIFESTVERSION)'
|
||||
# The ADO task does not support indexing of GitHub sources.
|
||||
indexSources: false
|
||||
detailedLog: true
|
||||
# There is a bug which causes this task to fail if LIB includes an inaccessible path (even though it does not depend on it).
|
||||
# To work around this issue, we just force LIB to be any dir that we know exists.
|
||||
# Copied from https://github.com/microsoft/icu/blob/f869c214adc87415dfe751d81f42f1bca55dcf5f/build/azure-nuget.yml#L564-L583
|
||||
env:
|
||||
LIB: $(Build.SourcesDirectory)
|
||||
ArtifactServices_Symbol_AccountName: microsoftpublicsymbols
|
||||
ArtifactServices_Symbol_PAT: $(ADO_microsoftpublicsymbols_PAT)
|
||||
|
||||
|
||||
- ${{ if eq(parameters.buildTerminalVPack, true) }}:
|
||||
- job: VPack
|
||||
displayName: Create Windows vPack
|
||||
dependsOn: BundleAndSign
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
submodules: true
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Build Artifacts
|
||||
inputs:
|
||||
artifactName: appxbundle-signed-Win11
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Rename and stage packages for vpack
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
# Rename to known/fixed name for Windows build system
|
||||
|
||||
Get-ChildItem Microsoft.WindowsTerminal_Win11_*.msixbundle | Rename-Item -NewName { 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle' }
|
||||
|
||||
|
||||
# Create vpack directory and place item inside
|
||||
|
||||
mkdir WindowsTerminal.app
|
||||
|
||||
mv Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle .\WindowsTerminal.app\
|
||||
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed-Win11
|
||||
- task: PkgESVPack@12
|
||||
displayName: 'Package ES - VPack'
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed-Win11\WindowsTerminal.app
|
||||
description: VPack for the Windows Terminal Application
|
||||
pushPkgName: WindowsTerminal.app
|
||||
owner: conhost
|
||||
githubToken: $(GitHubTokenForVpackProvenance)
|
||||
- task: PublishPipelineArtifact@1
|
||||
displayName: 'Copy VPack Manifest to Drop'
|
||||
inputs:
|
||||
targetPath: $(XES_VPACKMANIFESTDIRECTORY)
|
||||
artifactName: VPackManifest
|
||||
- task: PkgESFCIBGit@12
|
||||
displayName: 'Submit VPack Manifest to Windows'
|
||||
inputs:
|
||||
configPath: '$(Build.SourcesDirectory)\build\config\GitCheckin.json'
|
||||
artifactsDirectory: $(XES_VPACKMANIFESTDIRECTORY)
|
||||
prTimeOut: 5
|
||||
...
|
||||
extends:
|
||||
template: templates-v2/pipeline-full-release-build.yml
|
||||
parameters:
|
||||
branding: ${{ parameters.branding }}
|
||||
buildTerminal: ${{ parameters.buildTerminal }}
|
||||
buildConPTY: ${{ parameters.buildConPTY }}
|
||||
buildWPF: ${{ parameters.buildWPF }}
|
||||
pgoBuildMode: ${{ parameters.pgoBuildMode }}
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
generateSbom: ${{ parameters.generateSbom }}
|
||||
terminalInternalPackageVersion: ${{ parameters.terminalInternalPackageVersion }}
|
||||
publishSymbolsToPublic: ${{ parameters.publishSymbolsToPublic }}
|
||||
publishVpackToWindows: ${{ parameters.publishVpackToWindows }}
|
||||
|
||||
144
build/pipelines/templates-v2/job-build-package-wpf.yml
Normal file
144
build/pipelines/templates-v2/job-build-package-wpf.yml
Normal file
@@ -0,0 +1,144 @@
|
||||
parameters:
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
- name: generateSbom
|
||||
type: boolean
|
||||
default: false
|
||||
- name: codeSign
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: dependsOn
|
||||
type: object
|
||||
default: null
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
- name: jobName
|
||||
type: string
|
||||
default: PackWPF
|
||||
- name: variables
|
||||
type: object
|
||||
default: {}
|
||||
- name: publishArtifacts
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.jobName }}
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
${{ if eq(parameters.codeSign, true) }}:
|
||||
displayName: Pack and Sign Microsoft.Terminal.Wpf
|
||||
${{ else }}:
|
||||
displayName: Pack Microsoft.Terminal.Wpf
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ config }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
variables:
|
||||
OutputBuildPlatform: AnyCPU
|
||||
Terminal.BinDir: $(Build.SourcesDirectory)/bin/$(OutputBuildPlatform)/$(BuildConfiguration)
|
||||
JobOutputDirectory: $(Build.ArtifactStagingDirectory)\nupkg
|
||||
JobOutputArtifactName: wpf-nupkg-$(BuildConfiguration)${{ parameters.artifactStem }}
|
||||
${{ insert }}: ${{ parameters.variables }}
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
|
||||
- template: steps-download-bin-dir-artifact.yml
|
||||
parameters:
|
||||
buildPlatforms:
|
||||
- ${{ parameters.buildPlatforms }}
|
||||
- Any CPU # Make sure we grab the precompiled WPF bits
|
||||
# This build is already matrix'd on configuration, so
|
||||
# just pass a single config into the download template.
|
||||
buildConfigurations:
|
||||
- $(BuildConfiguration)
|
||||
artifactStem: ${{ parameters.artifactStem }}
|
||||
|
||||
- template: .\steps-restore-nuget.yml
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution OpenConsole.sln for WPF Control (Pack)
|
||||
inputs:
|
||||
solution: 'OpenConsole.sln'
|
||||
msbuildArgs: >-
|
||||
/p:WindowsTerminalReleaseBuild=true;Version=$(XES_PACKAGEVERSIONNUMBER)
|
||||
/p:NoBuild=true
|
||||
/p:IncludeSymbols=true
|
||||
/t:Terminal\wpf\WpfTerminalControl:Pack
|
||||
platform: Any CPU
|
||||
configuration: $(BuildConfiguration)
|
||||
maximumCpuCount: true
|
||||
clean: false
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy *.nupkg to Artifacts
|
||||
inputs:
|
||||
Contents: 'bin/**/*Wpf*.nupkg'
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- task: EsrpCodeSigning@3
|
||||
displayName: Submit *.nupkg to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
Pattern: '*.nupkg'
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetSign",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
|
||||
- ${{ if eq(parameters.generateSbom, true) }}:
|
||||
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
|
||||
displayName: 'Generate SBOM manifest (wpf)'
|
||||
inputs:
|
||||
BuildDropPath: '$(System.ArtifactsDirectory)/nupkg'
|
||||
BuildComponentPath: '$(Build.SourcesDirectory)/bin'
|
||||
|
||||
- task: DropValidatorTask@0
|
||||
displayName: 'Validate wpf SBOM manifest'
|
||||
inputs:
|
||||
BuildDropPath: '$(System.ArtifactsDirectory)/nupkg'
|
||||
OutputPath: 'output.json'
|
||||
ValidateSignature: true
|
||||
Verbosity: 'Verbose'
|
||||
|
||||
- ${{ if eq(parameters.publishArtifacts, true) }}:
|
||||
- publish: $(JobOutputDirectory)
|
||||
artifact: $(JobOutputArtifactName)
|
||||
displayName: Publish nupkg
|
||||
293
build/pipelines/templates-v2/job-build-project.yml
Normal file
293
build/pipelines/templates-v2/job-build-project.yml
Normal file
@@ -0,0 +1,293 @@
|
||||
parameters:
|
||||
- name: branding
|
||||
type: string
|
||||
default: Dev
|
||||
- name: additionalBuildOptions
|
||||
type: string
|
||||
default: ''
|
||||
- name: buildTerminal
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildConPTY
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildWPF
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildWPFDotNetComponents # This weird hack is to make sure we sign and source index the .NET pieces
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildEverything
|
||||
displayName: "Build Everything (Overrides all other build options)"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pgoBuildMode
|
||||
type: string
|
||||
default: None
|
||||
values: [Optimize, Instrument, None]
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
default:
|
||||
- Release
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- x86
|
||||
- arm64
|
||||
- name: generateSbom
|
||||
type: boolean
|
||||
default: false
|
||||
- name: codeSign
|
||||
type: boolean
|
||||
default: false
|
||||
- name: keepAllExpensiveBuildOutputs
|
||||
type: boolean
|
||||
default: true
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
- name: jobName
|
||||
type: string
|
||||
default: 'Build'
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: beforeBuildSteps
|
||||
type: stepList
|
||||
default: []
|
||||
- name: variables
|
||||
type: object
|
||||
default: {}
|
||||
- name: publishArtifacts
|
||||
type: boolean
|
||||
default: true
|
||||
- name: removeAllNonSignedFiles
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.jobName }}
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ each platform in parameters.buildPlatforms }}:
|
||||
${{ config }}_${{ platform }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
BuildPlatform: ${{ platform }}
|
||||
${{ if eq(platform, 'x86') }}:
|
||||
OutputBuildPlatform: Win32
|
||||
${{ elseif eq(platform, 'Any CPU') }}:
|
||||
OutputBuildPlatform: AnyCPU
|
||||
${{ else }}:
|
||||
OutputBuildPlatform: ${{ platform }}
|
||||
variables:
|
||||
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe'
|
||||
Terminal.BinDir: $(Build.SourcesDirectory)/bin/$(OutputBuildPlatform)/$(BuildConfiguration)
|
||||
# Azure DevOps abhors a vacuum
|
||||
# If these are blank, expansion will fail later on... which will result in direct substitution of the variable *names*
|
||||
# later on. We'll just... set them to a single space and if we need to, check IsNullOrWhiteSpace.
|
||||
# Yup.
|
||||
BuildTargetParameter: ' '
|
||||
SelectedSigningFragments: ' '
|
||||
JobOutputDirectory: $(Terminal.BinDir)
|
||||
JobOutputArtifactName: build-$(BuildPlatform)-$(BuildConfiguration)${{ parameters.artifactStem }}
|
||||
${{ insert }}: ${{ parameters.variables }}
|
||||
displayName: Build
|
||||
timeoutInMinutes: 240
|
||||
cancelTimeoutInMinutes: 1
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
# This generates either nothing for BuildTargetParameter, or /t:X;Y;Z, to control targets later.
|
||||
- pwsh: |-
|
||||
If (-Not [bool]::Parse("${{ parameters.buildEverything }}")) {
|
||||
$BuildTargets = @()
|
||||
$SignFragments = @()
|
||||
If ([bool]::Parse("${{ parameters.buildTerminal }}")) {
|
||||
$BuildTargets += "Terminal\CascadiaPackage"
|
||||
$SignFragments += "terminal_constituents"
|
||||
}
|
||||
If ([bool]::Parse("${{ parameters.buildWPFDotNetComponents }}")) {
|
||||
$BuildTargets += "Terminal\wpf\WpfTerminalControl"
|
||||
$SignFragments += "wpfdotnet"
|
||||
}
|
||||
If ([bool]::Parse("${{ parameters.buildWPF }}")) {
|
||||
$BuildTargets += "Terminal\wpf\PublicTerminalCore"
|
||||
$SignFragments += "wpf"
|
||||
}
|
||||
If ([bool]::Parse("${{ parameters.buildConPTY }}")) {
|
||||
$BuildTargets += "Conhost\Host_EXE;Conhost\winconpty_DLL"
|
||||
$SignFragments += "conpty"
|
||||
}
|
||||
Write-Host "Targets: $($BuildTargets -Join ";")"
|
||||
Write-Host "Sign targets: $($SignFragments -Join ";")"
|
||||
Write-Host "##vso[task.setvariable variable=BuildTargetParameter]/t:$($BuildTargets -Join ";")"
|
||||
Write-Host "##vso[task.setvariable variable=SelectedSigningFragments]$($SignFragments -Join ";")"
|
||||
}
|
||||
displayName: Prepare Build and Sign Targets
|
||||
|
||||
- pwsh: |-
|
||||
.\build\scripts\Generate-ThirdPartyNotices.ps1 -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
|
||||
displayName: Generate NOTICE.html from NOTICE.md
|
||||
|
||||
- template: .\steps-restore-nuget.yml
|
||||
|
||||
- ${{ parameters.beforeBuildSteps }}
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: Build OpenConsole.sln
|
||||
inputs:
|
||||
solution: 'OpenConsole.sln'
|
||||
msbuildArgs: >-
|
||||
/p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }}
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
/bl:$(Build.SourcesDirectory)\msbuild.binlog
|
||||
$(BuildTargetParameter)
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
maximumCpuCount: true
|
||||
|
||||
- ${{ if eq(parameters.publishArtifacts, true) }}:
|
||||
- publish: $(Build.SourcesDirectory)/msbuild.binlog
|
||||
artifact: logs-$(BuildPlatform)-$(BuildConfiguration)${{ parameters.artifactStem }}
|
||||
condition: always()
|
||||
displayName: Publish Build Log
|
||||
- ${{ else }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy Build Log
|
||||
inputs:
|
||||
contents: $(Build.SourcesDirectory)/msbuild.binlog
|
||||
TargetFolder: $(Terminal.BinDir)
|
||||
|
||||
# This saves ~2GiB per architecture. We won't need these later.
|
||||
# Removes:
|
||||
# - All .lib that do not have an associated .exp (which would indicate that they are import libs)
|
||||
# - All .pdbs from those .libs (which were only used during linking)
|
||||
# - Directories ending in Lib (static lib projects that we fully linked into DLLs which may also contain unnecessary resources)
|
||||
# - All LocalTests_ project outputs, as they were subsumed into TestHostApp
|
||||
# - All PDB files inside the WindowsTerminal/ output, which do not belong there.
|
||||
# - console.dll, which apparently breaks XFGCheck? lol.
|
||||
- pwsh: |-
|
||||
$binDir = '$(Terminal.BinDir)'
|
||||
$ImportLibs = Get-ChildItem $binDir -Recurse -File -Filter '*.exp' | ForEach-Object { $_.FullName -Replace "exp$","lib" }
|
||||
$StaticLibs = Get-ChildItem $binDir -Recurse -File -Filter '*.lib' | Where-Object FullName -NotIn $ImportLibs
|
||||
|
||||
$Items = @()
|
||||
$Items += $StaticLibs
|
||||
$Items += Get-Item ($StaticLibs.FullName -Replace "lib$","pdb") -ErrorAction:Ignore
|
||||
$Items += Get-ChildItem $binDir -Directory -Filter '*Lib'
|
||||
$Items += Get-ChildItem $binDir -Directory -Filter 'LocalTests_*'
|
||||
$Items += Get-ChildItem "${$binDir}\WindowsTerminal" -Filter '*.pdb' -ErrorAction:Ignore
|
||||
|
||||
If (-Not [bool]::Parse('${{ parameters.keepAllExpensiveBuildOutputs }}')) {
|
||||
$Items += Get-ChildItem '$(Terminal.BinDir)' -Filter '*.pdb' -Recurse
|
||||
}
|
||||
|
||||
$Items += Get-ChildItem $binDir -Filter 'console.dll'
|
||||
|
||||
$Items | Remove-Item -Recurse -Force -Verbose -ErrorAction:Ignore
|
||||
displayName: Clean up static libs and extra symbols
|
||||
errorActionPreference: silentlyContinue # It's OK if this silently fails
|
||||
|
||||
# We cannot index PDBs that we have deleted!
|
||||
- ${{ if eq(parameters.keepAllExpensiveBuildOutputs, true) }}:
|
||||
- pwsh: |-
|
||||
build\scripts\Index-Pdbs.ps1 -SearchDir '$(Terminal.BinDir)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
|
||||
displayName: Source Index PDBs
|
||||
errorActionPreference: silentlyContinue
|
||||
|
||||
- ${{ if or(parameters.buildTerminal, parameters.buildEverything) }}:
|
||||
- pwsh: |-
|
||||
$Package = (Get-ChildItem -Recurse -Filter "CascadiaPackage*.msix" | Select -First 1)
|
||||
$PackageFilename = $Package.FullName
|
||||
Write-Host "##vso[task.setvariable variable=WindowsTerminalPackagePath]${PackageFilename}"
|
||||
displayName: Locate the MSIX
|
||||
|
||||
# CHECK EXCEPTION
|
||||
# PGO requires a desktop CRT
|
||||
- ${{ if ne(parameters.pgoBuildMode, 'Instrument') }}:
|
||||
- pwsh: |-
|
||||
.\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path "$(WindowsTerminalPackagePath)"
|
||||
displayName: Check MSIX for common regressions
|
||||
condition: and(succeeded(), ne(variables.WindowsTerminalPackagePath, ''))
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- pwsh: |-
|
||||
& "$(MakeAppxPath)" unpack /p "$(WindowsTerminalPackagePath)" /d "$(Terminal.BinDir)/PackageContents"
|
||||
displayName: Unpack the MSIX for signing
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- template: steps-create-signing-config.yml
|
||||
parameters:
|
||||
outFile: '$(Build.SourcesDirectory)/ESRPSigningConfig.json'
|
||||
stage: build
|
||||
fragments: $(SelectedSigningFragments)
|
||||
|
||||
# Code-sign everything we just put together.
|
||||
# We run the signing in Terminal.BinDir, because all of the signing batches are relative to the final architecture/configuration output folder.
|
||||
- task: EsrpCodeSigning@3
|
||||
displayName: Submit Signing Request
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: '$(Terminal.BinDir)'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(Build.SourcesDirectory)/ESRPSigningConfig.json'
|
||||
|
||||
# We only need to re-pack the MSIX if we actually signed, so this can stay in the codeSign conditional
|
||||
- ${{ if or(parameters.buildTerminal, parameters.buildEverything) }}:
|
||||
- pwsh: |-
|
||||
$outDir = New-Item -Type Directory "$(Terminal.BinDir)/_appx" -ErrorAction:Ignore
|
||||
$PackageFilename = Join-Path $outDir.FullName (Split-Path -Leaf "$(WindowsTerminalPackagePath)")
|
||||
& "$(MakeAppxPath)" pack /h SHA256 /o /p $PackageFilename /d "$(Terminal.BinDir)/PackageContents"
|
||||
Write-Host "##vso[task.setvariable variable=WindowsTerminalPackagePath]${PackageFilename}"
|
||||
displayName: Re-pack the new Terminal package after signing
|
||||
|
||||
# Some of our governed pipelines explicitly fail builds that have *any* non-codesigned filed (!)
|
||||
- ${{ if eq(parameters.removeAllNonSignedFiles, true) }}:
|
||||
- pwsh: |-
|
||||
Get-ChildItem "$(Terminal.BinDir)" -Recurse -Include "*.dll","*.exe" |
|
||||
Where-Object { (Get-AuthenticodeSignature $_).Status -Ne "Valid" } |
|
||||
Remove-Item -Verbose -Force
|
||||
displayName: Remove all non-signed output files
|
||||
|
||||
- ${{ else }}: # No Signing
|
||||
- ${{ if or(parameters.buildTerminal, parameters.buildEverything) }}:
|
||||
- pwsh: |-
|
||||
$outDir = New-Item -Type Directory "$(Terminal.BinDir)/_appx" -ErrorAction:Ignore
|
||||
$PackageFilename = Join-Path $outDir.FullName (Split-Path -Leaf "$(WindowsTerminalPackagePath)")
|
||||
Copy-Item "$(WindowsTerminalPackagePath)" $PackageFilename
|
||||
Write-Host "##vso[task.setvariable variable=WindowsTerminalPackagePath]${PackageFilename}"
|
||||
displayName: Stage the package (unsigned)
|
||||
condition: and(succeeded(), ne(variables.WindowsTerminalPackagePath, ''))
|
||||
|
||||
- ${{ if or(parameters.buildTerminal, parameters.buildEverything) }}:
|
||||
- pwsh: |-
|
||||
$XamlAppxPath = (Get-Item "src\cascadia\CascadiaPackage\AppPackages\*\Dependencies\$(BuildPlatform)\Microsoft.UI.Xaml*.appx").FullName
|
||||
$outDir = New-Item -Type Directory "$(Terminal.BinDir)/_unpackaged" -ErrorAction:Ignore
|
||||
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 -TerminalAppX $(WindowsTerminalPackagePath) -XamlAppX $XamlAppxPath -Destination $outDir.FullName
|
||||
displayName: Build Unpackaged Distribution (from MSIX)
|
||||
condition: and(succeeded(), ne(variables.WindowsTerminalPackagePath, ''))
|
||||
|
||||
- ${{ if eq(parameters.generateSbom, true) }}:
|
||||
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
|
||||
displayName: 'Generate SBOM manifest'
|
||||
inputs:
|
||||
BuildDropPath: '$(Terminal.BinDir)'
|
||||
|
||||
- task: DropValidatorTask@0
|
||||
displayName: 'Validate SBOM manifest'
|
||||
inputs:
|
||||
BuildDropPath: '$(Terminal.BinDir)'
|
||||
OutputPath: 'output.json'
|
||||
ValidateSignature: true
|
||||
Verbosity: 'Verbose'
|
||||
|
||||
- ${{ if eq(parameters.publishArtifacts, true) }}:
|
||||
- publish: $(Terminal.BinDir)
|
||||
artifact: $(JobOutputArtifactName)
|
||||
displayName: Publish All Outputs
|
||||
15
build/pipelines/templates-v2/job-check-code-format.yml
Normal file
15
build/pipelines/templates-v2/job-check-code-format.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
jobs:
|
||||
- job: CodeFormatCheck
|
||||
displayName: Check Code Format
|
||||
pool: { vmImage: windows-2022 }
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
submodules: false
|
||||
clean: true
|
||||
|
||||
- powershell: |-
|
||||
.\build\scripts\Invoke-FormattingCheck.ps1
|
||||
displayName: 'Run formatters'
|
||||
@@ -1,21 +1,15 @@
|
||||
parameters:
|
||||
artifactName: 'drop'
|
||||
|
||||
jobs:
|
||||
- job: CodeNavIndexer
|
||||
displayName: Run Github CodeNav Indexer
|
||||
pool: { vmImage: windows-2019 }
|
||||
pool: { vmImage: windows-2022 }
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
submodules: false
|
||||
clean: true
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
inputs:
|
||||
artifactName: ${{ parameters.artifactName }}
|
||||
|
||||
- task: RichCodeNavIndexer@0
|
||||
inputs:
|
||||
languages: 'cpp,csharp'
|
||||
150
build/pipelines/templates-v2/job-merge-msix-into-bundle.yml
Normal file
150
build/pipelines/templates-v2/job-merge-msix-into-bundle.yml
Normal file
@@ -0,0 +1,150 @@
|
||||
parameters:
|
||||
- name: branding
|
||||
type: string
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
- name: generateSbom
|
||||
type: boolean
|
||||
default: false
|
||||
- name: codeSign
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: dependsOn
|
||||
type: object
|
||||
default: null
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
- name: jobName
|
||||
type: string
|
||||
default: Bundle
|
||||
- name: variables
|
||||
type: object
|
||||
default: {}
|
||||
- name: publishArtifacts
|
||||
type: boolean
|
||||
default: true
|
||||
- name: afterBuildSteps
|
||||
type: stepList
|
||||
default: []
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.jobName }}
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
${{ if eq(parameters.codeSign, true) }}:
|
||||
displayName: Pack and Sign Terminal MSIXBundle
|
||||
${{ else }}:
|
||||
displayName: Pack Terminal MSIXBundle
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ config }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
variables:
|
||||
${{ if eq(parameters.branding, 'Release') }}:
|
||||
BundleStemName: Microsoft.WindowsTerminal
|
||||
${{ elseif eq(parameters.branding, 'Preview') }}:
|
||||
BundleStemName: Microsoft.WindowsTerminalPreview
|
||||
${{ else }}:
|
||||
BundleStemName: WindowsTerminalDev
|
||||
JobOutputDirectory: '$(System.ArtifactsDirectory)/bundle'
|
||||
JobOutputArtifactName: appxbundle-$(BuildConfiguration)${{ parameters.artifactStem }}
|
||||
${{ insert }}: ${{ parameters.variables }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- template: steps-download-bin-dir-artifact.yml
|
||||
parameters:
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
# This build is already matrix'd on configuration, so
|
||||
# just pass a single config into the download template.
|
||||
buildConfigurations:
|
||||
- $(BuildConfiguration)
|
||||
artifactStem: ${{ parameters.artifactStem }}
|
||||
|
||||
# Add 3000 to the major version component, but only for the bundle.
|
||||
# This is to ensure that it is newer than "2022.xx.yy.zz" or whatever the original bundle versions were before
|
||||
# we switched to uniform naming.
|
||||
- pwsh: |-
|
||||
$VersionEpoch = 3000
|
||||
$Components = "$(XES_APPXMANIFESTVERSION)" -Split "\."
|
||||
$Components[0] = ([int]$Components[0] + $VersionEpoch)
|
||||
$BundleVersion = $Components -Join "."
|
||||
New-Item -Type Directory "$(System.ArtifactsDirectory)/bundle"
|
||||
$BundlePath = "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
.\build\scripts\Create-AppxBundle.ps1 -InputPath 'bin/' -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath $BundlePath
|
||||
Write-Host "##vso[task.setvariable variable=MsixBundlePath]${BundlePath}"
|
||||
displayName: Create msixbundle
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- task: EsrpCodeSigning@3
|
||||
displayName: Submit *.msixbundle to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(System.ArtifactsDirectory)\bundle
|
||||
Pattern: $(BundleStemName)*.msixbundle
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "Dynamic",
|
||||
"CertTemplateName": "WINMSAPP1ST",
|
||||
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
|
||||
"OperationCode": "SigntoolSign",
|
||||
"Parameters": {
|
||||
"OpusName": "Microsoft",
|
||||
"OpusInfo": "http://www.microsoft.com",
|
||||
"FileDigest": "/fd \"SHA256\"",
|
||||
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "Dynamic",
|
||||
"CertTemplateName": "WINMSAPP1ST",
|
||||
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
|
||||
"OperationCode": "SigntoolVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
|
||||
- ${{ if eq(parameters.generateSbom, true) }}:
|
||||
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
|
||||
displayName: 'Generate SBOM manifest (bundle)'
|
||||
inputs:
|
||||
BuildDropPath: '$(System.ArtifactsDirectory)/bundle'
|
||||
BuildComponentPath: '$(Build.SourcesDirectory)/bin'
|
||||
|
||||
- task: DropValidatorTask@0
|
||||
displayName: 'Validate bundle SBOM manifest'
|
||||
inputs:
|
||||
BuildDropPath: '$(System.ArtifactsDirectory)/bundle'
|
||||
OutputPath: 'output.json'
|
||||
ValidateSignature: true
|
||||
Verbosity: 'Verbose'
|
||||
|
||||
- ${{ parameters.afterBuildSteps }}
|
||||
|
||||
- ${{ if eq(parameters.publishArtifacts, true) }}:
|
||||
- publish: $(JobOutputDirectory)
|
||||
artifact: $(JobOutputArtifactName)
|
||||
displayName: Publish msixbundle
|
||||
129
build/pipelines/templates-v2/job-package-conpty.yml
Normal file
129
build/pipelines/templates-v2/job-package-conpty.yml
Normal file
@@ -0,0 +1,129 @@
|
||||
parameters:
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
- name: generateSbom
|
||||
type: boolean
|
||||
default: false
|
||||
- name: codeSign
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: dependsOn
|
||||
type: object
|
||||
default: null
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
- name: jobName
|
||||
type: string
|
||||
default: PackConPTY
|
||||
- name: variables
|
||||
type: object
|
||||
default: {}
|
||||
- name: publishArtifacts
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.jobName }}
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
${{ if eq(parameters.codeSign, true) }}:
|
||||
displayName: Pack and Sign Microsoft.Windows.Console.ConPTY
|
||||
${{ else }}:
|
||||
displayName: Pack Microsoft.Windows.Console.ConPTY
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ config }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
variables:
|
||||
JobOutputDirectory: $(Build.ArtifactStagingDirectory)\nupkg
|
||||
JobOutputArtifactName: conpty-nupkg-$(BuildConfiguration)${{ parameters.artifactStem }}
|
||||
${{ insert }}: ${{ parameters.variables }}
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
|
||||
- template: steps-download-bin-dir-artifact.yml
|
||||
parameters:
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
# This build is already matrix'd on configuration, so
|
||||
# just pass a single config into the download template.
|
||||
buildConfigurations:
|
||||
- $(BuildConfiguration)
|
||||
artifactStem: ${{ parameters.artifactStem }}
|
||||
|
||||
- template: steps-ensure-nuget-version.yml
|
||||
|
||||
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
|
||||
# This should be `task: NuGetCommand@2`
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: NuGet pack
|
||||
inputs:
|
||||
command: pack
|
||||
packagesToPack: $(Build.SourcesDirectory)\src\winconpty\package\winconpty.nuspec
|
||||
packDestination: '$(Build.ArtifactStagingDirectory)/nupkg'
|
||||
versioningScheme: byEnvVar
|
||||
versionEnvVar: XES_PACKAGEVERSIONNUMBER
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- task: EsrpCodeSigning@3
|
||||
displayName: Submit *.nupkg to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
Pattern: '*.nupkg'
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetSign",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
|
||||
- ${{ if eq(parameters.generateSbom, true) }}:
|
||||
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
|
||||
displayName: 'Generate SBOM manifest (conpty)'
|
||||
inputs:
|
||||
BuildDropPath: '$(System.ArtifactsDirectory)/nupkg'
|
||||
BuildComponentPath: '$(Build.SourcesDirectory)/bin'
|
||||
|
||||
- task: DropValidatorTask@0
|
||||
displayName: 'Validate conpty SBOM manifest'
|
||||
inputs:
|
||||
BuildDropPath: '$(System.ArtifactsDirectory)/nupkg'
|
||||
OutputPath: 'output.json'
|
||||
ValidateSignature: true
|
||||
Verbosity: 'Verbose'
|
||||
|
||||
- ${{ if eq(parameters.publishArtifacts, true) }}:
|
||||
- publish: $(JobOutputDirectory)
|
||||
artifact: $(JobOutputArtifactName)
|
||||
displayName: Publish nupkg
|
||||
@@ -1,14 +1,26 @@
|
||||
# From our friends at MUX: https://github.com/microsoft/microsoft-ui-xaml/blob/main/build/AzurePipelinesTemplates/MUX-BuildAndPublishPGONuGet-Job.yml
|
||||
|
||||
parameters:
|
||||
dependsOn: ''
|
||||
pgoArtifact: PGO
|
||||
- name: buildConfiguration
|
||||
type: string
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: dependsOn
|
||||
type: object
|
||||
default: null
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
- name: jobName
|
||||
type: string
|
||||
default: BuildAndPublishPGONuget
|
||||
|
||||
jobs:
|
||||
- job: BuildAndPublishPGONuGet
|
||||
- job: ${{ parameters.jobName }}
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
displayName: Package and Publish PGO Databases
|
||||
|
||||
variables:
|
||||
artifactsPath: $(Build.SourcesDirectory)\Artifacts
|
||||
pgoToolsPath: $(Build.SourcesDirectory)\build\PGO
|
||||
@@ -16,20 +28,25 @@ jobs:
|
||||
nuspecFilename: PGO.nuspec
|
||||
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
- checkout: self
|
||||
clean: true
|
||||
# It is important that this be 0, otherwise git will not fetch the branch ref names that the PGO rules require.
|
||||
fetchDepth: 0
|
||||
submodules: false
|
||||
persistCredentials: false
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download Final PGO Databases
|
||||
inputs:
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
artifact: pgd-merged-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
|
||||
downloadPath: $(artifactsPath)
|
||||
|
||||
- template: steps-ensure-nuget-version.yml
|
||||
|
||||
- task: NuGetAuthenticate@0
|
||||
inputs:
|
||||
nuGetServiceConnections: 'Terminal Public Artifact Feed'
|
||||
|
||||
- task: NuGetToolInstaller@0
|
||||
displayName: 'Use NuGet 5.8.0'
|
||||
inputs:
|
||||
versionSpec: 5.8.0
|
||||
|
||||
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
|
||||
# This should be `task: NuGetCommand@2`
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
@@ -45,12 +62,11 @@ jobs:
|
||||
displayName: 'Create PGO Nuget'
|
||||
inputs:
|
||||
solution: $(pgoToolsPath)\PGO.DB.proj
|
||||
msbuildArguments: '/t:CreatePGONuGet /p:PGOBuildMode=Instrument /p:PGDPathForAllArch=$(artifactsPath)\${{ parameters.pgoArtifact }} /p:PGOOutputPath=$(Build.ArtifactStagingDirectory)'
|
||||
msbuildArguments: '/t:CreatePGONuGet /p:PGOBuildMode=Instrument /p:PGDPathForAllArch=$(artifactsPath) /p:PGOOutputPath=$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathToPublish: $(Build.ArtifactStagingDirectory)
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
- publish: $(Build.ArtifactStagingDirectory)
|
||||
artifact: pgo-nupkg-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
|
||||
displayName: "Publish Pipeline Artifact"
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: 'NuGet push'
|
||||
75
build/pipelines/templates-v2/job-pgo-merge-pgd.yml
Normal file
75
build/pipelines/templates-v2/job-pgo-merge-pgd.yml
Normal file
@@ -0,0 +1,75 @@
|
||||
parameters:
|
||||
- name: buildConfiguration
|
||||
type: string
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: dependsOn
|
||||
type: object
|
||||
default: null
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
- name: jobName
|
||||
type: string
|
||||
default: MergePGD
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.jobName }}
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
displayName: Merge PGO Counts for ${{ parameters.buildConfiguration }}
|
||||
|
||||
steps:
|
||||
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
|
||||
- script: |
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
|
||||
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
|
||||
del %TEMP%\vsinstalldir.txt
|
||||
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download PGO Databases for ${{ platform }}
|
||||
inputs:
|
||||
artifactName: build-${{ platform }}-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
|
||||
itemPattern: '**/*.pgd'
|
||||
downloadPath: '$(Build.SourcesDirectory)/pgd/${{ platform }}/${{ parameters.buildConfiguration }}'
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download PGO Counts for ${{ platform }}
|
||||
inputs:
|
||||
artifactName: pgc-intermediates-${{ platform }}-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
|
||||
downloadPath: '$(Build.SourcesDirectory)/pgc/${{ platform }}/${{ parameters.buildConfiguration }}'
|
||||
- pwsh: |-
|
||||
$Arch = '${{ platform }}'
|
||||
$Conf = '${{ parameters.buildConfiguration }}'
|
||||
$PGCDir = '$(Build.SourcesDirectory)/pgc/${{ platform }}/${{ parameters.buildConfiguration }}'
|
||||
$PGDDir = '$(Build.SourcesDirectory)/pgd/${{ platform }}/${{ parameters.buildConfiguration }}'
|
||||
# Flatten the PGD directory
|
||||
Get-ChildItem $PGDDir -Recurse -Filter *.pgd | Move-Item -Destination $PGDDir -Verbose
|
||||
Get-ChildItem $PGCDir -Filter *.pgc |
|
||||
ForEach-Object {
|
||||
$Parts = $_.Name -Split "!";
|
||||
$_ | Add-Member Module $Parts[0] -PassThru
|
||||
} |
|
||||
Group-Object Module |
|
||||
ForEach-Object {
|
||||
& "$(VCToolsInstallDir)\bin\Hostx64\${{ platform }}\pgomgr.exe" /merge $_.Group.FullName "$PGDDir\$($_.Name).pgd"
|
||||
}
|
||||
displayName: Merge PGO Counts for ${{ platform }}
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy merged pgds to artifact staging'
|
||||
inputs:
|
||||
sourceFolder: '$(Build.SourcesDirectory)/pgd/${{ platform }}/${{ parameters.buildConfiguration }}'
|
||||
contents: '**\*.pgd'
|
||||
targetFolder: '$(Build.ArtifactStagingDirectory)\out-pgd\${{ platform }}'
|
||||
|
||||
- publish: $(Build.ArtifactStagingDirectory)\out-pgd
|
||||
artifact: pgd-merged-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
|
||||
displayName: "Publish merged PGDs"
|
||||
97
build/pipelines/templates-v2/job-publish-symbols.yml
Normal file
97
build/pipelines/templates-v2/job-publish-symbols.yml
Normal file
@@ -0,0 +1,97 @@
|
||||
parameters:
|
||||
- name: includePublicSymbolServer
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: dependsOn
|
||||
type: object
|
||||
default: null
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
- name: jobName
|
||||
type: string
|
||||
default: PublishSymbols
|
||||
- name: symbolExpiryTime
|
||||
type: string
|
||||
default: 36530 # This is the default from PublishSymbols@2
|
||||
- name: variables
|
||||
type: object
|
||||
default: {}
|
||||
- name: symbolPatGoesInTaskInputs
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.jobName }}
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
${{ if eq(parameters.includePublicSymbolServer, true) }}:
|
||||
displayName: Publish Symbols to Internal and MSDL
|
||||
${{ else }}:
|
||||
displayName: Publish Symbols Internally
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
variables:
|
||||
${{ insert }}: ${{ parameters.variables }}
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download all PDBs from all prior build phases
|
||||
inputs:
|
||||
itemPattern: '**/*.pdb'
|
||||
targetPath: '$(Build.SourcesDirectory)/bin'
|
||||
|
||||
- task: PublishSymbols@2
|
||||
displayName: Publish Symbols (to current Azure DevOps tenant)
|
||||
continueOnError: True
|
||||
inputs:
|
||||
SymbolsFolder: '$(Build.SourcesDirectory)/bin'
|
||||
SearchPattern: '**/*.pdb'
|
||||
IndexSources: false
|
||||
DetailedLog: true
|
||||
SymbolsMaximumWaitTime: 30
|
||||
SymbolServerType: 'TeamServices'
|
||||
SymbolsProduct: 'Windows Terminal Converged Symbols'
|
||||
SymbolsVersion: '$(XES_APPXMANIFESTVERSION)'
|
||||
SymbolExpirationInDays: ${{ parameters.symbolExpiryTime }}
|
||||
env:
|
||||
LIB: $(Build.SourcesDirectory)
|
||||
|
||||
- ${{ if eq(parameters.includePublicSymbolServer, true) }}:
|
||||
- task: PublishSymbols@2
|
||||
displayName: 'Publish symbols to MSDL'
|
||||
continueOnError: True
|
||||
inputs:
|
||||
SymbolsFolder: '$(Build.SourcesDirectory)/bin'
|
||||
SearchPattern: '**/*.pdb'
|
||||
IndexSources: false
|
||||
DetailedLog: true
|
||||
SymbolsMaximumWaitTime: 30
|
||||
SymbolServerType: 'TeamServices'
|
||||
SymbolsProduct: 'Windows Terminal Converged Symbols'
|
||||
SymbolsVersion: '$(XES_APPXMANIFESTVERSION)'
|
||||
SymbolExpirationInDays: ${{ parameters.symbolExpiryTime }}
|
||||
${{ if eq(parameters.symbolPatGoesInTaskInputs, true) }}:
|
||||
Pat: $(ADO_microsoftpublicsymbols_PAT)
|
||||
# The ADO task does not support indexing of GitHub sources.
|
||||
# There is a bug which causes this task to fail if LIB includes an inaccessible path (even though it does not depend on it).
|
||||
# To work around this issue, we just force LIB to be any dir that we know exists.
|
||||
# Copied from https://github.com/microsoft/icu/blob/f869c214adc87415dfe751d81f42f1bca55dcf5f/build/azure-nuget.yml#L564-L583
|
||||
env:
|
||||
LIB: $(Build.SourcesDirectory)
|
||||
ArtifactServices_Symbol_AccountName: microsoftpublicsymbols
|
||||
${{ if ne(parameters.symbolPatGoesInTaskInputs, true) }}:
|
||||
ArtifactServices_Symbol_PAT: $(ADO_microsoftpublicsymbols_PAT)
|
||||
83
build/pipelines/templates-v2/job-run-pgo-tests.yml
Normal file
83
build/pipelines/templates-v2/job-run-pgo-tests.yml
Normal file
@@ -0,0 +1,83 @@
|
||||
parameters:
|
||||
buildConfiguration: 'Release'
|
||||
buildPlatform: ''
|
||||
artifactStem: ''
|
||||
testLogPath: '$(Build.BinariesDirectory)\$(BuildPlatform)\$(BuildConfiguration)\testsOnBuildMachine.wtl'
|
||||
|
||||
jobs:
|
||||
- job: PGO${{ parameters.buildPlatform }}${{ parameters.buildConfiguration }}
|
||||
displayName: PGO ${{ parameters.buildPlatform }} ${{ parameters.buildConfiguration }}
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.buildConfiguration }}
|
||||
BuildPlatform: ${{ parameters.buildPlatform }}
|
||||
OutputBuildPlatform: ${{ parameters.buildPlatform }}
|
||||
Terminal.BinDir: $(Build.SourcesDirectory)/bin/$(OutputBuildPlatform)/$(BuildConfiguration)
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
${{ if ne(parameters.buildPlatform, 'ARM64') }}:
|
||||
name: SHINE-OSS-Testing-x64
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-Testing-arm64
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
${{ if ne(parameters.buildPlatform, 'ARM64') }}:
|
||||
name: SHINE-INT-Testing-x64
|
||||
${{ else }}:
|
||||
name: SHINE-INT-Testing-arm64
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: false
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download artifacts
|
||||
inputs:
|
||||
artifactName: build-${{ parameters.buildPlatform }}-$(BuildConfiguration)${{ parameters.artifactStem }}
|
||||
downloadPath: $(Terminal.BinDir)
|
||||
|
||||
# The tests expect Terminal to be an unpackaged distribution named terminal-0.0.1.0 (after the dev build version scheme)
|
||||
# Extract to that folder explicitly and strip the embedded folder name from the unpackaged archive.
|
||||
- powershell: |-
|
||||
$TargetDirectory = New-Item -Type Directory (Join-Path "$(Terminal.BinDir)" "terminal-0.0.1.0")
|
||||
& tar.exe -x -v -f (Get-Item "$(Terminal.BinDir)/_unpackaged/*.zip") -C $TargetDirectory.FullName --strip-components=1
|
||||
displayName: Extract the unpackaged build for PGO
|
||||
|
||||
- template: steps-ensure-nuget-version.yml
|
||||
|
||||
- powershell: |-
|
||||
$Package = 'Microsoft.Internal.Windows.Terminal.TestContent'
|
||||
$Version = '1.0.1'
|
||||
& nuget.exe install $Package -Version $Version
|
||||
Write-Host "##vso[task.setvariable variable=TerminalTestContentPath]$(Build.SourcesDirectory)\packages\${Package}.${Version}\content"
|
||||
displayName: Install Test Content
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run PGO Tests'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: >-
|
||||
-MatchPattern '*UIA.Tests.dll'
|
||||
-Platform '$(OutputBuildPlatform)'
|
||||
-Configuration '$(BuildConfiguration)'
|
||||
-LogPath '${{ parameters.testLogPath }}'
|
||||
-Root "$(Terminal.BinDir)"
|
||||
-AdditionalTaefArguments '/select:(@IsPGO=true)','/p:WTTestContent=$(TerminalTestContentPath)'
|
||||
condition: and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument'))
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy PGO outputs to Artifacts'
|
||||
condition: always()
|
||||
inputs:
|
||||
Contents: |
|
||||
**/*.pgc
|
||||
${{ parameters.testLogPath }}
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/pgc'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
|
||||
- publish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/pgc'
|
||||
artifact: pgc-intermediates-$(BuildPlatform)-$(BuildConfiguration)${{ parameters.artifactStem }}
|
||||
condition: always()
|
||||
81
build/pipelines/templates-v2/job-submit-windows-vpack.yml
Normal file
81
build/pipelines/templates-v2/job-submit-windows-vpack.yml
Normal file
@@ -0,0 +1,81 @@
|
||||
parameters:
|
||||
- name: buildConfiguration
|
||||
type: string
|
||||
- name: generateSbom
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: dependsOn
|
||||
type: object
|
||||
default: null
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
- name: variables
|
||||
type: object
|
||||
default: {}
|
||||
- name: publishArtifacts
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
- job: VPack
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
displayName: Create and Submit Windows vPack
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
variables:
|
||||
JobOutputDirectory: $(XES_VPACKMANIFESTDIRECTORY)
|
||||
JobOutputArtifactName: vpack-manifest${{ parameters.artifactStem }}
|
||||
${{ insert }}: ${{ parameters.variables }}
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download MSIX Bundle Artifact
|
||||
inputs:
|
||||
artifactName: appxbundle-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
|
||||
downloadPath: '$(Build.SourcesDirectory)/bundle'
|
||||
|
||||
# Rename to known/fixed name for Windows build system
|
||||
- powershell: |-
|
||||
# Create vpack directory and place item inside
|
||||
$TargetFolder = New-Item -Type Directory '$(Build.SourcesDirectory)/WindowsTerminal.app'
|
||||
Get-ChildItem bundle/Microsoft.WindowsTerminal_*.msixbundle | Move-Item (Join-Path $TargetFolder.FullName 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle') -Verbose
|
||||
displayName: Stage packages for vpack
|
||||
|
||||
- task: PkgESVPack@12
|
||||
displayName: 'Package ES - VPack'
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
sourceDirectory: '$(Build.SourcesDirectory)/WindowsTerminal.app'
|
||||
description: VPack for the Windows Terminal Application
|
||||
pushPkgName: WindowsTerminal.app
|
||||
owner: conhost
|
||||
githubToken: $(GitHubTokenForVpackProvenance)
|
||||
|
||||
- ${{ if eq(parameters.publishArtifacts, true) }}:
|
||||
- publish: $(JobOutputDirectory)
|
||||
artifact: $(JobOutputArtifactName)
|
||||
displayName: 'Publish VPack Manifest to Drop'
|
||||
|
||||
- task: PkgESFCIBGit@12
|
||||
displayName: 'Submit VPack Manifest to Windows'
|
||||
inputs:
|
||||
configPath: '$(Build.SourcesDirectory)\build\config\GitCheckin.json'
|
||||
artifactsDirectory: $(XES_VPACKMANIFESTDIRECTORY)
|
||||
prTimeOut: 5
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
parameters:
|
||||
configuration: 'Release'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
artifactName: 'drop'
|
||||
testLogPath: '$(Build.BinariesDirectory)\$(BuildPlatform)\$(BuildConfiguration)\testsOnBuildMachine.wtl'
|
||||
inputArtifactStem: ''
|
||||
outputArtifactStem: ''
|
||||
|
||||
jobs:
|
||||
- job: Test${{ parameters.platform }}${{ parameters.configuration }}
|
||||
@@ -11,47 +11,52 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
${{ if eq(parameters.platform, 'x86') }}:
|
||||
OutputBuildPlatform: Win32
|
||||
${{ else }}:
|
||||
OutputBuildPlatform: ${{ parameters.platform }}
|
||||
Terminal.BinDir: $(Build.SourcesDirectory)/bin/$(OutputBuildPlatform)/$(BuildConfiguration)
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(parameters.platform, 'ARM64') }}:
|
||||
name: SHINE-OSS-Testing-x64
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-Testing-arm64
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
${{ if ne(parameters.platform, 'ARM64') }}:
|
||||
name: SHINE-INT-Testing-x64
|
||||
${{ else }}:
|
||||
name: SHINE-INT-Testing-arm64
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
submodules: false
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download artifacts
|
||||
inputs:
|
||||
artifactName: ${{ parameters.artifactName }}
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Rationalize build platform'
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
$Arch = "$(BuildPlatform)"
|
||||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
artifactName: build-${{ parameters.platform }}-$(BuildConfiguration)${{ parameters.inputArtifactStem }}
|
||||
downloadPath: $(Terminal.BinDir)
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run Unit Tests'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' -Root "$(System.ArtifactsDirectory)\\${{ parameters.artifactName }}\\$(BuildConfiguration)\\$(BuildPlatform)\\test"
|
||||
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(OutputBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' -Root "$(Terminal.BinDir)"
|
||||
condition: and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument'))
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run Feature Tests (x64 only)'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' -Root "$(System.ArtifactsDirectory)\\${{ parameters.artifactName }}\\$(BuildConfiguration)\\$(BuildPlatform)\\test"
|
||||
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), eq(variables['BuildPlatform'], 'x64'))
|
||||
- ${{ if or(eq(parameters.platform, 'x64'), eq(parameters.platform, 'arm64')) }}:
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run Feature Tests'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(OutputBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' -Root "$(Terminal.BinDir)"
|
||||
condition: and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument'))
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Convert Test Logs from WTL to xUnit format'
|
||||
@@ -59,7 +64,7 @@ jobs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\ConvertWttLogToXUnit.ps1
|
||||
arguments: -WttInputPath '${{ parameters.testLogPath }}' -WttSingleRerunInputPath 'unused.wtl' -WttMultipleRerunInputPath 'unused2.wtl' -XUnitOutputPath 'onBuildMachineResults.xml' -TestNamePrefix '$(BuildConfiguration).$(BuildPlatform)'
|
||||
condition: and(ne(variables['PGOBuildMode'], 'Instrument'),or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Upload converted test logs'
|
||||
@@ -67,13 +72,9 @@ jobs:
|
||||
inputs:
|
||||
testResultsFormat: 'xUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest
|
||||
testResultsFiles: '**/onBuildMachineResults.xml'
|
||||
#searchFolder: '$(System.DefaultWorkingDirectory)' # Optional
|
||||
#mergeTestResults: false # Optional
|
||||
#failTaskOnFailedTests: false # Optional
|
||||
testRunTitle: 'On Build Machine Tests' # Optional
|
||||
buildPlatform: $(BuildPlatform) # Optional
|
||||
buildConfiguration: $(BuildConfiguration) # Optional
|
||||
#publishRunAttachments: true # Optional
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy result logs to Artifacts'
|
||||
@@ -87,4 +88,5 @@ jobs:
|
||||
flattenFolders: true
|
||||
|
||||
- publish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test-logs'
|
||||
artifact: TestLogs$(BuildPlatform)$(BuildConfiguration)
|
||||
artifact: test-logs-$(BuildPlatform)-$(BuildConfiguration)${{ parameters.outputArtifactStem }}
|
||||
condition: always()
|
||||
177
build/pipelines/templates-v2/pipeline-full-release-build.yml
Normal file
177
build/pipelines/templates-v2/pipeline-full-release-build.yml
Normal file
@@ -0,0 +1,177 @@
|
||||
# This build should never run as CI or against a pull request.
|
||||
trigger: none
|
||||
|
||||
parameters:
|
||||
- name: branding
|
||||
type: string
|
||||
default: Release
|
||||
- name: buildTerminal
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildConPTY
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildWPF
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pgoBuildMode
|
||||
type: string
|
||||
default: Optimize
|
||||
values:
|
||||
- Optimize
|
||||
- Instrument
|
||||
- None
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
default:
|
||||
- Release
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- x86
|
||||
- arm64
|
||||
- name: codeSign
|
||||
type: boolean
|
||||
default: true
|
||||
- name: generateSbom
|
||||
type: boolean
|
||||
default: true
|
||||
- name: terminalInternalPackageVersion
|
||||
type: string
|
||||
default: '0.0.8'
|
||||
|
||||
- name: publishSymbolsToPublic
|
||||
type: boolean
|
||||
default: true
|
||||
- name: symbolExpiryTime
|
||||
type: string
|
||||
default: 36530 # This is the default from PublishSymbols@2
|
||||
- name: publishVpackToWindows
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
- name: pool
|
||||
type: object
|
||||
default:
|
||||
name: SHINE-INT-S # By default, send jobs to the small agent pool.
|
||||
demands: ImageOverride -equals SHINE-VS17-Latest
|
||||
|
||||
variables:
|
||||
- template: variables-nuget-package-version.yml
|
||||
parameters:
|
||||
branding: ${{ parameters.branding }}
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: self
|
||||
type: git
|
||||
ref: main
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
displayName: Build
|
||||
pool: ${{ parameters.pool }}
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./job-build-project.yml
|
||||
parameters:
|
||||
pool:
|
||||
name: SHINE-INT-L # Run the compilation on the large agent pool, rather than the default small one.
|
||||
demands: ImageOverride -equals SHINE-VS17-Latest
|
||||
branding: ${{ parameters.branding }}
|
||||
buildTerminal: ${{ parameters.buildTerminal }}
|
||||
buildConPTY: ${{ parameters.buildConPTY }}
|
||||
buildWPF: ${{ parameters.buildWPF }}
|
||||
pgoBuildMode: ${{ parameters.pgoBuildMode }}
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
generateSbom: ${{ parameters.generateSbom }}
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
beforeBuildSteps: # Right before we build, lay down the universal package and localizations
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
|
||||
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
|
||||
versionListDownload: ${{ parameters.terminalInternalPackageVersion }}
|
||||
|
||||
- template: ./steps-fetch-and-prepare-localizations.yml
|
||||
parameters:
|
||||
includePseudoLoc: true
|
||||
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
# Add an Any CPU build flavor for the WPF control bits
|
||||
- template: ./job-build-project.yml
|
||||
parameters:
|
||||
# This job is allowed to run on the default small pool.
|
||||
jobName: BuildWPF
|
||||
branding: ${{ parameters.branding }}
|
||||
buildTerminal: false
|
||||
buildWPFDotNetComponents: true
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms:
|
||||
- Any CPU
|
||||
generateSbom: ${{ parameters.generateSbom }}
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
beforeBuildSteps:
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
# WPF doesn't need the localizations or the universal package, but if it does... put them here.
|
||||
|
||||
- stage: Package
|
||||
displayName: Package
|
||||
pool: ${{ parameters.pool }}
|
||||
dependsOn: [Build]
|
||||
jobs:
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- template: ./job-merge-msix-into-bundle.yml
|
||||
parameters:
|
||||
jobName: Bundle
|
||||
branding: ${{ parameters.branding }}
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
generateSbom: ${{ parameters.generateSbom }}
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
|
||||
- ${{ if eq(parameters.buildConPTY, true) }}:
|
||||
- template: ./job-package-conpty.yml
|
||||
parameters:
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
generateSbom: ${{ parameters.generateSbom }}
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- template: ./job-build-package-wpf.yml
|
||||
parameters:
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
generateSbom: ${{ parameters.generateSbom }}
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
|
||||
- stage: Publish
|
||||
displayName: Publish
|
||||
pool: ${{ parameters.pool }}
|
||||
dependsOn: [Build, Package]
|
||||
jobs:
|
||||
# We only support the vpack for Release builds that include Terminal
|
||||
- ${{ if and(containsValue(parameters.buildConfigurations, 'Release'), parameters.buildTerminal, parameters.publishVpackToWindows) }}:
|
||||
- template: ./job-submit-windows-vpack.yml
|
||||
parameters:
|
||||
buildConfiguration: Release
|
||||
generateSbom: ${{ parameters.generateSbom }}
|
||||
|
||||
- template: ./job-publish-symbols.yml
|
||||
parameters:
|
||||
includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }}
|
||||
symbolExpiryTime: ${{ parameters.symbolExpiryTime }}
|
||||
|
||||
...
|
||||
@@ -0,0 +1,256 @@
|
||||
parameters:
|
||||
- name: official
|
||||
type: boolean
|
||||
default: false
|
||||
- name: branding
|
||||
type: string
|
||||
default: Release
|
||||
values:
|
||||
- Release
|
||||
- Preview
|
||||
- Canary
|
||||
- Dev
|
||||
- name: buildTerminal
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildConPTY
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildWPF
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pgoBuildMode
|
||||
type: string
|
||||
default: Optimize
|
||||
values:
|
||||
- Optimize
|
||||
- Instrument
|
||||
- None
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
default:
|
||||
- Release
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- x86
|
||||
- arm64
|
||||
- name: codeSign
|
||||
type: boolean
|
||||
default: true
|
||||
- name: terminalInternalPackageVersion
|
||||
type: string
|
||||
default: '0.0.8'
|
||||
|
||||
- name: publishSymbolsToPublic
|
||||
type: boolean
|
||||
default: true
|
||||
- name: publishVpackToWindows
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
- name: extraPublishJobs
|
||||
type: object
|
||||
default: []
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: templates
|
||||
type: git
|
||||
name: OneBranch.Pipelines/GovernedTemplates
|
||||
ref: refs/heads/main
|
||||
|
||||
extends:
|
||||
${{ if eq(parameters.official, true) }}:
|
||||
template: v2/Microsoft.Official.yml@templates # https://aka.ms/obpipelines/templates
|
||||
${{ else }}:
|
||||
template: v2/Microsoft.NonOfficial.yml@templates
|
||||
parameters:
|
||||
featureFlags:
|
||||
WindowsHostVersion: 1ESWindows2022
|
||||
platform:
|
||||
name: 'windows_undocked'
|
||||
product: 'Windows Terminal'
|
||||
cloudvault: # https://aka.ms/obpipelines/cloudvault
|
||||
enabled: false
|
||||
globalSdl: # https://aka.ms/obpipelines/sdl
|
||||
tsa:
|
||||
enabled: true
|
||||
configFile: '$(Build.SourcesDirectory)\build\config\tsa.json'
|
||||
binskim:
|
||||
break: false
|
||||
scanOutputDirectoryOnly: true
|
||||
policheck:
|
||||
break: false
|
||||
severity: Note
|
||||
baseline:
|
||||
baselineFile: '$(Build.SourcesDirectory)\build\config\release.gdnbaselines'
|
||||
suppressionSet: default
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
displayName: Build
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: ./build/pipelines/templates-v2/job-build-project.yml@self
|
||||
parameters:
|
||||
pool: { type: windows }
|
||||
variables:
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
ob_artifactBaseName: $(JobOutputArtifactName)
|
||||
publishArtifacts: false # Handled by OneBranch
|
||||
branding: ${{ parameters.branding }}
|
||||
buildTerminal: ${{ parameters.buildTerminal }}
|
||||
buildConPTY: ${{ parameters.buildConPTY }}
|
||||
buildWPF: ${{ parameters.buildWPF }}
|
||||
pgoBuildMode: ${{ parameters.pgoBuildMode }}
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
generateSbom: false # this is handled by onebranch
|
||||
removeAllNonSignedFiles: true # appease the overlords
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
beforeBuildSteps: # Right before we build, lay down the universal package and localizations
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
|
||||
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
|
||||
versionListDownload: ${{ parameters.terminalInternalPackageVersion }}
|
||||
|
||||
- template: ./build/pipelines/templates-v2/steps-fetch-and-prepare-localizations.yml@self
|
||||
parameters:
|
||||
includePseudoLoc: true
|
||||
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
# Add an Any CPU build flavor for the WPF control bits
|
||||
- template: ./build/pipelines/templates-v2/job-build-project.yml@self
|
||||
parameters:
|
||||
pool: { type: windows }
|
||||
variables:
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
ob_artifactBaseName: $(JobOutputArtifactName)
|
||||
publishArtifacts: false # Handled by OneBranch
|
||||
jobName: BuildWPF
|
||||
branding: ${{ parameters.branding }}
|
||||
buildTerminal: false
|
||||
buildWPFDotNetComponents: true
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms:
|
||||
- Any CPU
|
||||
generateSbom: false # this is handled by onebranch
|
||||
removeAllNonSignedFiles: true # appease the overlords
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
beforeBuildSteps:
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
# WPF doesn't need the localizations or the universal package, but if it does... put them here.
|
||||
|
||||
- stage: Package
|
||||
displayName: Package
|
||||
dependsOn: [Build]
|
||||
jobs:
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- template: ./build/pipelines/templates-v2/job-merge-msix-into-bundle.yml@self
|
||||
parameters:
|
||||
pool: { type: windows }
|
||||
variables:
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
ob_artifactBaseName: $(JobOutputArtifactName)
|
||||
### This job is also in charge of submitting the vpack to Windows if it's enabled
|
||||
ob_createvpack_enabled: ${{ and(parameters.buildTerminal, parameters.publishVpackToWindows) }}
|
||||
ob_updateOSManifest_enabled: ${{ and(parameters.buildTerminal, parameters.publishVpackToWindows) }}
|
||||
### If enabled above, these options are in play.
|
||||
ob_createvpack_packagename: 'WindowsTerminal.app'
|
||||
ob_createvpack_owneralias: 'conhost@microsoft.com'
|
||||
ob_createvpack_description: 'VPack for the Windows Terminal Application'
|
||||
ob_createvpack_targetDestinationDirectory: '$(Destination)'
|
||||
ob_createvpack_propsFile: false
|
||||
ob_createvpack_provData: true
|
||||
ob_createvpack_metadata: '$(Build.SourceVersion)'
|
||||
ob_createvpack_topLevelRetries: 0
|
||||
ob_createvpack_failOnStdErr: true
|
||||
ob_createvpack_taskLogVerbosity: Detailed
|
||||
ob_createvpack_verbose: true
|
||||
ob_createvpack_vpackdirectory: '$(JobOutputDirectory)\vpack'
|
||||
ob_updateOSManifest_gitcheckinConfigPath: '$(Build.SourcesDirectory)\build\config\GitCheckin.json'
|
||||
# We're skipping the 'fetch' part of the OneBranch rules, but that doesn't mean
|
||||
# that it doesn't expect to have downloaded a manifest directly to some 'destination'
|
||||
# folder that it can then update and upload.
|
||||
# Effectively: it says "destination" but it means "source"
|
||||
# DH: Don't ask why.
|
||||
ob_updateOSManifest_destination: $(XES_VPACKMANIFESTDIRECTORY)
|
||||
ob_updateOSManifest_skipFetch: true
|
||||
publishArtifacts: false # Handled by OneBranch
|
||||
jobName: Bundle
|
||||
branding: ${{ parameters.branding }}
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
generateSbom: false # Handled by onebranch
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
afterBuildSteps:
|
||||
- pwsh: |-
|
||||
$d = New-Item "$(JobOutputDirectory)/vpack" -Type Directory
|
||||
Copy-Item -Verbose -Path "$(MsixBundlePath)" -Destination (Join-Path $d 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle')
|
||||
displayName: Stage msixbundle for vpack
|
||||
|
||||
- ${{ if eq(parameters.buildConPTY, true) }}:
|
||||
- template: ./build/pipelines/templates-v2/job-package-conpty.yml@self
|
||||
parameters:
|
||||
pool: { type: windows }
|
||||
variables:
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
ob_artifactBaseName: $(JobOutputArtifactName)
|
||||
publishArtifacts: false # Handled by OneBranch
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
generateSbom: false # this is handled by onebranch
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- template: ./build/pipelines/templates-v2/job-build-package-wpf.yml@self
|
||||
parameters:
|
||||
pool: { type: windows }
|
||||
variables:
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
ob_artifactBaseName: $(JobOutputArtifactName)
|
||||
publishArtifacts: false # Handled by OneBranch
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
generateSbom: false # this is handled by onebranch
|
||||
codeSign: ${{ parameters.codeSign }}
|
||||
|
||||
- stage: Publish
|
||||
displayName: Publish
|
||||
dependsOn: [Build, Package]
|
||||
jobs:
|
||||
- template: ./build/pipelines/templates-v2/job-publish-symbols.yml@self
|
||||
parameters:
|
||||
pool: { type: windows }
|
||||
includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }}
|
||||
symbolPatGoesInTaskInputs: true # onebranch tries to muck with the PAT variable, so we need to change how it get the PAT
|
||||
variables:
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(Build.ArtifactStagingDirectory)
|
||||
# Without this, OneBranch will nerf our symbol tasks
|
||||
ob_symbolsPublishing_enabled: true
|
||||
|
||||
- ${{ parameters.extraPublishJobs }}
|
||||
35
build/pipelines/templates-v2/steps-create-signing-config.yml
Normal file
35
build/pipelines/templates-v2/steps-create-signing-config.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
parameters:
|
||||
- name: stage
|
||||
type: string
|
||||
- name: outFile
|
||||
type: string
|
||||
- name: fragments
|
||||
type: string
|
||||
|
||||
# This build step template takes all files named "esrp.STAGE.batch.*.json"
|
||||
# and merges them into a single output signing config.
|
||||
#
|
||||
# We generate the batch signing config by sticking together multiple "batches".
|
||||
# The filter below (with Fragments) works by splitting the filename, esrp.s.batch.x.json,
|
||||
# to get 'x' and then checking whether x is in Fragments.
|
||||
# We have to manually strip comments out of the batch fragments due to https://github.com/PowerShell/PowerShell/issues/14553
|
||||
|
||||
steps:
|
||||
- pwsh: |-
|
||||
$SignBatchFiles = (Get-Item build/config/esrp.${{ parameters.stage }}.batch.*.json)
|
||||
$Fragments = "${{ parameters.fragments }}"
|
||||
If (-Not [String]::IsNullOrWhiteSpace($Fragments)) {
|
||||
$FragmentList = $Fragments -Split ";"
|
||||
If ($FragmentList.Length -Gt 0) {
|
||||
$SignBatchFiles = $SignBatchFiles | Where-Object { ($_.Name -Split '\.')[3] -In $FragmentList }
|
||||
}
|
||||
}
|
||||
Write-Host "Found $(@($SignBatchFiles).Length) Signing Configs"
|
||||
Write-Host ($SignBatchFiles.Name -Join ";")
|
||||
$FinalSignConfig = @{
|
||||
Version = "1.0.0";
|
||||
UseMinimatch = $false;
|
||||
SignBatches = @($SignBatchFiles | ForEach-Object { Get-Content $_ | Where-Object { $_ -NotMatch "^\s*\/\/" } | ConvertFrom-Json -Depth 10 });
|
||||
}
|
||||
$FinalSignConfig | ConvertTo-Json -Depth 10 | Out-File -Encoding utf8 "${{ parameters.outFile }}"
|
||||
displayName: Merge ${{ parameters.stage }} signing configs (${{ parameters.outFile }})
|
||||
@@ -0,0 +1,24 @@
|
||||
parameters:
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
- name: artifactStem
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
steps:
|
||||
- ${{ each configuration in parameters.buildConfigurations }}:
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download artifacts for ${{ platform }} ${{ configuration }}
|
||||
inputs:
|
||||
# Make sure to download the entire artifact, because it includes the SPDX SBOM
|
||||
artifactName: build-${{ platform }}-${{ configuration }}${{ parameters.artifactStem }}
|
||||
# Downloading to the source directory should ensure that the later SBOM generator can see the earlier SBOMs.
|
||||
${{ if eq(platform, 'x86') }}:
|
||||
downloadPath: '$(Build.SourcesDirectory)/bin/Win32/${{ configuration }}'
|
||||
${{ elseif eq(platform, 'Any CPU') }}:
|
||||
downloadPath: '$(Build.SourcesDirectory)/bin/AnyCPU/${{ configuration }}'
|
||||
${{ else }}:
|
||||
downloadPath: '$(Build.SourcesDirectory)/bin/${{ platform }}/${{ configuration }}'
|
||||
@@ -0,0 +1,5 @@
|
||||
steps:
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Use NuGet 6.6.1
|
||||
inputs:
|
||||
versionSpec: 6.6.1
|
||||
@@ -0,0 +1,27 @@
|
||||
parameters:
|
||||
- name: includePseudoLoc
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
steps:
|
||||
- task: TouchdownBuildTask@1
|
||||
displayName: Download Localization Files
|
||||
inputs:
|
||||
teamId: 7105
|
||||
authId: $(TouchdownAppId)
|
||||
authKey: $(TouchdownAppKey)
|
||||
resourceFilePath: |
|
||||
src\cascadia\**\en-US\*.resw
|
||||
appendRelativeDir: true
|
||||
localizationTarget: false
|
||||
${{ if eq(parameters.includePseudoLoc, true) }}:
|
||||
pseudoSetting: Included
|
||||
|
||||
- pwsh: |-
|
||||
$Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw'
|
||||
$Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore }
|
||||
displayName: Move Loc files into final locations
|
||||
|
||||
- pwsh: |-
|
||||
./build/scripts/Copy-ContextMenuResourcesToCascadiaPackage.ps1
|
||||
displayName: Copy the Context Menu Loc Resources to CascadiaPackage
|
||||
@@ -1,11 +1,13 @@
|
||||
steps:
|
||||
- task: NuGetToolInstaller@0
|
||||
displayName: 'Use NuGet 6.3.0'
|
||||
inputs:
|
||||
versionSpec: 6.3.0
|
||||
- template: steps-ensure-nuget-version.yml
|
||||
|
||||
- task: NuGetAuthenticate@0
|
||||
|
||||
- script: |-
|
||||
echo ##vso[task.setvariable variable=NUGET_RESTORE_MSBUILD_ARGS]/p:Platform=$(BuildPlatform)
|
||||
displayName: Ensure NuGet restores for $(BuildPlatform)
|
||||
condition: and(succeeded(), ne(variables['BuildPlatform'], 'Any CPU'))
|
||||
|
||||
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
|
||||
# This should be `task: NuGetCommand@2`
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
@@ -0,0 +1,27 @@
|
||||
parameters:
|
||||
- name: branding
|
||||
type: string
|
||||
|
||||
variables:
|
||||
# If we are building a branch called "release-*", change the NuGet suffix
|
||||
# to "preview". If we don't do that, XES will set the suffix to "release1"
|
||||
# because it truncates the value after the first period.
|
||||
# We also want to disable the suffix entirely if we're Release branded while
|
||||
# on a release branch.
|
||||
# main is special, however. XES ignores main. Since we never produce actual
|
||||
# shipping builds from main, we want to force it to have a beta label as
|
||||
# well.
|
||||
#
|
||||
# In effect:
|
||||
# BRANCH / BRANDING | Release | Preview
|
||||
# ------------------|----------------------------|-----------------------------
|
||||
# release-* | 1.12.20220427 | 1.13.20220427-preview
|
||||
# main | 1.14.20220427-experimental | 1.14.20220427-experimental
|
||||
# all others | 1.14.20220427-mybranch | 1.14.20220427-mybranch
|
||||
${{ if startsWith(variables['Build.SourceBranchName'], 'release-') }}:
|
||||
${{ if eq(parameters.branding, 'Release') }}:
|
||||
NoNuGetPackBetaVersion: true
|
||||
${{ else }}:
|
||||
NuGetPackBetaVersion: preview
|
||||
${{ elseif eq(variables['Build.SourceBranchName'], 'main') }}:
|
||||
NuGetPackBetaVersion: experimental
|
||||
@@ -0,0 +1,2 @@
|
||||
variables:
|
||||
WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest'
|
||||
@@ -1,34 +0,0 @@
|
||||
parameters:
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}AuditMode
|
||||
displayName: Static Analysis Build ${{ parameters.platform }}
|
||||
variables:
|
||||
BuildConfiguration: AuditMode
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
|
||||
- template: restore-nuget-steps.yml
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 'Build solution **\OpenConsole.sln'
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
platform: '$(BuildPlatform)'
|
||||
configuration: '$(BuildConfiguration)'
|
||||
msbuildArgs: ${{ parameters.additionalBuildArguments }}
|
||||
clean: true
|
||||
maximumCpuCount: true
|
||||
@@ -1,31 +0,0 @@
|
||||
parameters:
|
||||
configuration: 'Release'
|
||||
branding: 'Dev'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}${{ parameters.configuration }}${{ parameters.branding }}
|
||||
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }} ${{ parameters.branding }}
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
WindowsTerminalBranding: ${{ parameters.branding }}
|
||||
EnableRichCodeNavigation: true
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
parameters:
|
||||
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
|
||||
|
||||
# It appears that the Component Governance build task that gets automatically injected stopped working
|
||||
# when we renamed our main branch.
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: 'Component Detection'
|
||||
condition: and(succeededOrFailed(), not(eq(variables['Build.Reason'], 'PullRequest')))
|
||||
@@ -1,203 +0,0 @@
|
||||
jobs:
|
||||
- job: Compliance
|
||||
# We don't *need* a matrix but there's no other way to set parameters on a "job"
|
||||
# in the AzDO YAML syntax. It would have to be a "stage" or a "template".
|
||||
# Doesn't matter. We're going to do compliance on Release x64 because
|
||||
# that's the one all the tooling works against for sure.
|
||||
strategy:
|
||||
matrix:
|
||||
Release_x64:
|
||||
BuildConfiguration: Release
|
||||
BuildPlatform: x64
|
||||
displayName: Validate Security and Compliance
|
||||
timeoutInMinutes: 240
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- task: PowerShell@2
|
||||
displayName: Rationalize Build Platform
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Arch = "$(BuildPlatform)"
|
||||
|
||||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
- template: restore-nuget-steps.yml
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
|
||||
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
|
||||
versionListDownload: $(TerminalInternalPackageVersion)
|
||||
- task: TouchdownBuildTask@1
|
||||
displayName: Download Localization Files
|
||||
inputs:
|
||||
teamId: 7105
|
||||
authId: $(TouchdownAppId)
|
||||
authKey: $(TouchdownAppKey)
|
||||
resourceFilePath: >-
|
||||
src\cascadia\TerminalApp\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalControl\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalConnection\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalSettingsModel\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw
|
||||
appendRelativeDir: true
|
||||
localizationTarget: false
|
||||
pseudoSetting: Included
|
||||
- task: PowerShell@2
|
||||
displayName: Move Loc files one level up
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw'
|
||||
|
||||
$Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore }
|
||||
pwsh: true
|
||||
|
||||
# 1ES Component Governance onboarding (Detects open source components). See https://docs.opensource.microsoft.com/tools/cg.html
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: Component Detection
|
||||
|
||||
# # PREfast and PoliCheck need Node. Install that first.
|
||||
- task: NodeTool@0
|
||||
|
||||
# !!! NOTE !!! Run PREfast first. Some of the other tasks are going to run on a completed build.
|
||||
# PREfast is going to build the code as a part of its analysis and the generated sources
|
||||
# and output binaries will be sufficient for the rest of the analysis.
|
||||
# If you disable this, the other tasks won't likely work. You would have to add a build
|
||||
# step instead that builds the code normally before calling them.
|
||||
# Also... PREfast will rebuild anyway so that's why we're not running a normal build first.
|
||||
# Waste of time to build twice.
|
||||
# PREfast. See https://www.1eswiki.com/wiki/SDL_Native_Rules_Build_Task
|
||||
|
||||
# The following 1ES tasks all operate completely differently and have a different syntax for usage.
|
||||
# Most notable is every one of them has a different way of excluding things.
|
||||
# Go see their 1eswiki.com pages to figure out how to exclude things.
|
||||
# When writing exclusions, try to make them narrow so when new projects/binaries are added, they
|
||||
# cause an error here and have to be explicitly pulled out. Don't write an exclusion so broad
|
||||
# that it will catch other new stuff.
|
||||
|
||||
# https://www.1eswiki.com/wiki/PREfast_Build_Task
|
||||
# Builds the project with C/C++ static analysis tools to find coding flaws and vulnerabilities
|
||||
# !!! WARNING !!! It doesn't work with WAPPROJ packaging projects. Build the sub-projects instead.
|
||||
- task: securedevelopmentteam.vss-secure-development-tools.build-task-prefast.SDLNativeRules@3
|
||||
displayName: 'Run the PREfast SDL Native Rules for MSBuild'
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
setupCommandlines: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsMSBuildCmd.bat"'
|
||||
msBuildCommandline: msbuild.exe /nologo /m /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /p:WindowsTerminalReleaseBuild=true /p:platform=$(BuildPlatform) /p:configuration=$(BuildConfiguration) /t:Terminal\Window\WindowsTerminal /p:VisualStudioVersion=17.0 $(Build.SourcesDirectory)\OpenConsole.sln
|
||||
msBuildVersion: "17.0"
|
||||
|
||||
# Copies output from PREfast SDL Native Rules task to expected location for consumption by PkgESSecComp
|
||||
- task: CopyFiles@1
|
||||
displayName: 'Copy PREfast xml files to SDLNativeRulesDir'
|
||||
inputs:
|
||||
SourceFolder: '$(Agent.BuildDirectory)'
|
||||
Contents: |
|
||||
**\*.nativecodeanalysis.xml
|
||||
TargetFolder: '$(Agent.BuildDirectory)\_sdt\logs\SDLNativeRules'
|
||||
|
||||
# https://www.1eswiki.com/index.php?title=PoliCheck_Build_Task
|
||||
# Scans the text of source code, comments, and content for terminology that could be sensitive for legal, cultural, or geopolitical reasons.
|
||||
# (Also finds vulgarities... takes all the fun out of everything.)
|
||||
- task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@2
|
||||
displayName: 'Run PoliCheck'
|
||||
inputs:
|
||||
targetType: F
|
||||
targetArgument: $(Build.SourcesDirectory)
|
||||
result: PoliCheck.xml
|
||||
optionsFC: 1
|
||||
optionsXS: 1
|
||||
optionsUEPath: $(Build.SourcesDirectory)\build\config\PolicheckExclusions.xml
|
||||
optionsHMENABLE: 0
|
||||
continueOnError: true
|
||||
|
||||
# https://www.1eswiki.com/wiki/CredScan_Azure_DevOps_Build_Task
|
||||
# Searches through source code and build outputs for a credential left behind in the open
|
||||
- task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3
|
||||
displayName: 'Run CredScan'
|
||||
inputs:
|
||||
outputFormat: pre
|
||||
# suppressionsFile: LocalSuppressions.json
|
||||
batchSize: 20
|
||||
debugMode: false
|
||||
continueOnError: true
|
||||
|
||||
# https://www.1eswiki.com/wiki/BinSkim_Build_Task
|
||||
# Searches managed and unmanaged binaries for known security vulnerabilities.
|
||||
- task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@4
|
||||
displayName: 'Run BinSkim'
|
||||
inputs:
|
||||
TargetPattern: guardianGlob
|
||||
# See https://aka.ms/gdn-globs for how to do match patterns
|
||||
AnalyzeTargetGlob: $(Build.SourcesDirectory)\bin\**\*.dll;$(Build.SourcesDirectory)\bin\**\*.exe;-:file|**\Microsoft.UI.Xaml.dll;-:file|**\Microsoft.Toolkit.Win32.UI.XamlHost.dll;-:file|**\vcruntime*.dll;-:file|**\vcomp*.dll;-:file|**\vccorlib*.dll;-:file|**\vcamp*.dll;-:file|**\msvcp*.dll;-:file|**\concrt*.dll;-:file|**\TerminalThemeHelpers*.dll;-:file|**\cpprest*.dll
|
||||
continueOnError: true
|
||||
|
||||
# Set XES_SERIALPOSTBUILDREADY to run Security and Compliance task once per build
|
||||
- powershell: Write-Host "##vso[task.setvariable variable=XES_SERIALPOSTBUILDREADY;]true"
|
||||
displayName: 'Set XES_SERIALPOSTBUILDREADY Vars'
|
||||
|
||||
# https://www.osgwiki.com/wiki/Package_ES_Security_and_Compliance
|
||||
# Does a few things:
|
||||
# - Ensures that Windows-required compliance tasks are run either inside this task
|
||||
# or were run as a previous step prior to this one
|
||||
# (PREfast, PoliCheck, Credscan)
|
||||
# - Runs Windows-specific compliance tasks inside the task
|
||||
# + CheckCFlags - ensures that compiler and linker flags meet Windows standards
|
||||
# + CFGCheck/XFGCheck - ensures that Control Flow Guard (CFG) or
|
||||
# eXtended Flow Guard (XFG) are enabled on binaries
|
||||
# NOTE: CFG is deprecated and XFG isn't fully ready yet.
|
||||
# NOTE2: CFG fails on an XFG'd binary
|
||||
# - Brokers all security/compliance task logs to "Trust Services Automation (TSA)" (https://aka.ms/tsa)
|
||||
# which is a system that maps all errors into the appropriate bug database
|
||||
# template for each organization since they all vary. It should also suppress
|
||||
# new bugs when one already exists for the product.
|
||||
# This one is set up to go to the OS repository and use the given parameters
|
||||
# to file bugs to our AzDO product path.
|
||||
# If we don't use PkgESSecComp to do this for us, we need to install the TSA task
|
||||
# ourselves in this pipeline to finalize data upload and bug creation.
|
||||
# !!! NOTE !!! This task goes *LAST* after any other compliance tasks so it catches their logs
|
||||
- task: PkgESSecComp@10
|
||||
displayName: 'Security and Compliance tasks'
|
||||
inputs:
|
||||
fileNewBugs: false
|
||||
areaPath: 'OS\WDX\DXP\WinDev\Terminal'
|
||||
teamProject: 'OS'
|
||||
iterationPath: 'OS\Future'
|
||||
bugTags: 'TerminalReleaseCompliance'
|
||||
scanAll: true
|
||||
errOnBugs: false
|
||||
failOnStdErr: true
|
||||
taskLogVerbosity: Diagnostic
|
||||
secCompConfigFromTask: |
|
||||
# Overrides default build sources directory
|
||||
sourceTargetOverrideAll: $(Build.SourcesDirectory)
|
||||
# Overrides default build binaries directory when "Scan all" option is specified
|
||||
binariesTargetOverrideAll: $(Build.SourcesDirectory)\bin
|
||||
|
||||
# Set the tools to false if they should not run in the build
|
||||
tools:
|
||||
- toolName: CheckCFlags
|
||||
enable: true
|
||||
- toolName: CFGCheck
|
||||
enable: true
|
||||
- toolName: Policheck
|
||||
enable: false
|
||||
- toolName: CredScan
|
||||
enable: false
|
||||
- toolName: XFGCheck
|
||||
enable: false
|
||||
@@ -1,90 +0,0 @@
|
||||
parameters:
|
||||
configuration: 'Fuzzing'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
clean: true
|
||||
|
||||
- template: restore-nuget-steps.yml
|
||||
|
||||
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
|
||||
- script: |
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
|
||||
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
|
||||
del %TEMP%\vsinstalldir.txt
|
||||
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 'Build solution **\OpenConsole.sln'
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
platform: '$(BuildPlatform)'
|
||||
configuration: '$(BuildConfiguration)'
|
||||
msbuildArgs: "${{ parameters.additionalBuildArguments }}"
|
||||
clean: true
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Rationalize build platform'
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
$Arch = "$(BuildPlatform)"
|
||||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy result logs to Artifacts'
|
||||
inputs:
|
||||
Contents: |
|
||||
**/*.wtl
|
||||
**/*onBuildMachineResults.xml
|
||||
${{ parameters.testLogPath }}
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy outputs needed for test runs to Artifacts'
|
||||
inputs:
|
||||
Contents: |
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.exe
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml
|
||||
**/Microsoft.VCLibs.*.appx
|
||||
**/TestHostApp/*.exe
|
||||
**/TestHostApp/*.dll
|
||||
**/TestHostApp/*.xml
|
||||
!**/*.pdb
|
||||
!**/*.ipdb
|
||||
!**/*.obj
|
||||
!**/*.pch
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: succeeded()
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish All Build Artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'fuzzingBuildOutput'
|
||||
@@ -1,55 +0,0 @@
|
||||
parameters:
|
||||
configuration: 'Release'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
minimumExpectedTestsExecutedCount: 1 # Sanity check for minimum expected tests to be reported
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Instrument'
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
parameters:
|
||||
additionalBuildArguments: '${{ parameters.additionalBuildArguments }}'
|
||||
|
||||
- template: helix-runtests-job.yml
|
||||
parameters:
|
||||
name: 'RunTestsInHelix'
|
||||
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
condition: succeeded()
|
||||
testSuite: 'PgoInstrumentationSuite'
|
||||
taefQuery: '@IsPgo=true'
|
||||
configuration: ${{ parameters.configuration }}
|
||||
platform: ${{ parameters.platform }}
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
|
||||
- template: helix-processtestresults-job.yml
|
||||
parameters:
|
||||
name: 'ProcessTestResults'
|
||||
pgoArtifact: 'PGO'
|
||||
dependsOn:
|
||||
- RunTestsInHelix
|
||||
condition: succeededOrFailed()
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}
|
||||
|
||||
- template: pgo-merge-pgd-job.yml
|
||||
parameters:
|
||||
name: 'MergePGD'
|
||||
dependsOn:
|
||||
- ProcessTestResults
|
||||
pgoArtifact: 'PGO'
|
||||
platform: ${{ parameters.platform }}
|
||||
configuration: ${{ parameters.configuration }}
|
||||
@@ -1,130 +0,0 @@
|
||||
parameters:
|
||||
additionalBuildArguments: ''
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
|
||||
- template: restore-nuget-steps.yml
|
||||
|
||||
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
|
||||
- script: |
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
|
||||
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
|
||||
del %TEMP%\vsinstalldir.txt
|
||||
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display build machine environment variables'
|
||||
inputs:
|
||||
filename: 'set'
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 'Build solution **\OpenConsole.sln'
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
platform: '$(BuildPlatform)'
|
||||
configuration: '$(BuildConfiguration)'
|
||||
msbuildArgs: "${{ parameters.additionalBuildArguments }} /p:PGOBuildMode=$(PGOBuildMode) /bl:$(Build.SourcesDirectory)\\msbuild.binlog"
|
||||
clean: true
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Check MSIX for common regressions'
|
||||
# PGO runtime needs its own CRT and it's in the package for convenience.
|
||||
# That will make this script mad so skip since we're not shipping the PGO Instrumentation one anyway.
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
$Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix"
|
||||
.\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'Source Index PDBs'
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
|
||||
errorActionPreference: silentlyContinue
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Rationalize build platform'
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
$Arch = "$(BuildPlatform)"
|
||||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy *.appx/*.msix to Artifacts (Non-PR builds only)'
|
||||
inputs:
|
||||
Contents: |
|
||||
**/*.appx
|
||||
**/*.msix
|
||||
**/*.appxsym
|
||||
!**/Microsoft.VCLibs*.appx
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: succeeded()
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy outputs needed for test runs to Artifacts'
|
||||
inputs:
|
||||
Contents: |
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.exe
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml
|
||||
**/Microsoft.VCLibs.*.appx
|
||||
**/*unit.test*.dll
|
||||
**/*unit.test*.manifest
|
||||
**/TestHostApp/*.exe
|
||||
**/TestHostApp/*.dll
|
||||
**/TestHostApp/*.xml
|
||||
!**/*.pdb
|
||||
!**/*.ipdb
|
||||
!**/*.obj
|
||||
!**/*.pch
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: succeeded()
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish All Build Artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'drop'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy PGO databases needed for PGO instrumentation run'
|
||||
inputs:
|
||||
Contents: |
|
||||
**/*.pgd
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO/$(BuildPlatform)'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish All PGO Artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO'
|
||||
ArtifactName: 'PGO'
|
||||
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: binlog'
|
||||
condition: always()
|
||||
continueOnError: True
|
||||
inputs:
|
||||
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
|
||||
ArtifactName: binlog-$(BuildPlatform)
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
jobs:
|
||||
- job: CodeFormatCheck
|
||||
displayName: Proper Code Formatting Check
|
||||
pool: { vmImage: windows-2022 }
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
fetchDepth: 1
|
||||
submodules: false
|
||||
clean: true
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Code Formatting Check'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: '.\build\scripts\Invoke-FormattingCheck.ps1'
|
||||
@@ -1,25 +0,0 @@
|
||||
parameters:
|
||||
configuration: 'Release'
|
||||
platform: ''
|
||||
minimumExpectedTestsExecutedCount: 10 # Sanity check for minimum expected tests to be reported
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
|
||||
jobs:
|
||||
- template: helix-runtests-job.yml
|
||||
parameters:
|
||||
name: 'RunTestsInHelix'
|
||||
# We're not setting dependsOn as we want to rely on the "stage" dependency above us
|
||||
testSuite: 'DevTestSuite'
|
||||
platform: ${{ parameters.platform }}
|
||||
configuration: ${{ parameters.configuration }}
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
|
||||
- template: helix-processtestresults-job.yml
|
||||
parameters:
|
||||
dependsOn:
|
||||
- RunTestsInHelix
|
||||
# the default condition is succeededOrFailed(), and the "stage" condition ensures we only run as needed
|
||||
platform: ${{ parameters.platform }}
|
||||
configuration: ${{ parameters.configuration }}
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}
|
||||
@@ -1,15 +0,0 @@
|
||||
parameters:
|
||||
condition: ''
|
||||
testFilePath: ''
|
||||
outputProjFileName: ''
|
||||
testSuite: ''
|
||||
taefQuery: ''
|
||||
|
||||
steps:
|
||||
- task: powershell@2
|
||||
displayName: 'Create ${{ parameters.outputProjFileName }}'
|
||||
condition: ${{ parameters.condition }}
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\GenerateTestProjFile.ps1
|
||||
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
|
||||
@@ -1,71 +0,0 @@
|
||||
parameters:
|
||||
condition: 'succeededOrFailed()'
|
||||
dependsOn: ''
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
minimumExpectedTestsExecutedCount: 10
|
||||
checkJobAttempt: false
|
||||
pgoArtifact: ''
|
||||
|
||||
jobs:
|
||||
- job: ProcessTestResults
|
||||
displayName: Process Helix Results ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
condition: ${{ parameters.condition }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
timeoutInMinutes: 120
|
||||
variables:
|
||||
helixOutputFolder: $(Build.SourcesDirectory)\HelixOutput
|
||||
|
||||
steps:
|
||||
- task: powershell@2
|
||||
displayName: 'UpdateUnreliableTests.ps1'
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
HelixAccessToken: $(HelixApiAccessToken)
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\UpdateUnreliableTests.ps1
|
||||
arguments: -RerunPassesRequiredToAvoidFailure '${{ parameters.rerunPassesRequiredToAvoidFailure }}'
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'OutputTestResults.ps1'
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
HelixAccessToken: $(HelixApiAccessToken)
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\OutputTestResults.ps1
|
||||
arguments: -MinimumExpectedTestsExecutedCount '${{ parameters.minimumExpectedTestsExecutedCount }}' -CheckJobAttempt $${{ parameters.checkJobAttempt }}
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'ProcessHelixFiles.ps1'
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
HelixAccessToken: $(HelixApiAccessToken)
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\ProcessHelixFiles.ps1
|
||||
arguments: -OutputFolder '$(helixOutputFolder)'
|
||||
|
||||
- ${{if ne(parameters.pgoArtifact, '') }}:
|
||||
- script: move /y $(helixOutputFolder)\PGO $(Build.ArtifactStagingDirectory)
|
||||
displayName: 'Move pgc files to PGO artifact'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Helix files'
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
PathtoPublish: $(helixOutputFolder)
|
||||
artifactName: drop
|
||||
|
||||
- ${{if ne(parameters.pgoArtifact, '') }}:
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish pgc files'
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)\PGO\Release
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
@@ -1,164 +0,0 @@
|
||||
parameters:
|
||||
name: 'RunTestsInHelix'
|
||||
dependsOn: ''
|
||||
condition: ''
|
||||
testSuite: ''
|
||||
# If a Pipeline runs this template more than once, this parameter should be unique per build flavor to differentiate the
|
||||
# the different test runs:
|
||||
helixType: 'test/devtest'
|
||||
artifactName: 'drop'
|
||||
maxParallel: 4
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
taefQuery: ''
|
||||
configuration: ''
|
||||
platform: ''
|
||||
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
|
||||
useBuildOutputFromPipeline: $(System.DefinitionId)
|
||||
openHelixTargetQueues: 'windows.10.amd64.client21h1.open.xaml'
|
||||
closedHelixTargetQueues: 'windows.10.amd64.client21h1.xaml'
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
displayName: Submit Helix ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
condition: ${{ parameters.condition }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
timeoutInMinutes: 120
|
||||
strategy:
|
||||
maxParallel: ${{ parameters.maxParallel }}
|
||||
variables:
|
||||
buildConfiguration: ${{ parameters.configuration }}
|
||||
buildPlatform: ${{ parameters.platform }}
|
||||
openHelixTargetQueues: ${{ parameters.openHelixTargetQueues }}
|
||||
closedHelixTargetQueues: ${{ parameters.closedHelixTargetQueues }}
|
||||
artifactsDir: $(Build.SourcesDirectory)\Artifacts
|
||||
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\$(buildPlatform)
|
||||
helixCommonArgs: '/binaryLogger:$(Build.SourcesDirectory)/${{parameters.name}}.$(buildPlatform).$(buildConfiguration).binlog /p:HelixBuild=$(Build.BuildId).$(buildPlatform).$(buildConfiguration) /p:Platform=$(buildPlatform) /p:Configuration=$(buildConfiguration) /p:HelixType=${{parameters.helixType}} /p:TestSuite=${{parameters.testSuite}} /p:ProjFilesPath=$(Build.ArtifactStagingDirectory) /p:rerunPassesRequiredToAvoidFailure=${{parameters.rerunPassesRequiredToAvoidFailure}}'
|
||||
|
||||
steps:
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display build machine environment variables'
|
||||
inputs:
|
||||
filename: 'set'
|
||||
|
||||
- task: NuGetToolInstaller@0
|
||||
displayName: 'Use NuGet 6.3.0'
|
||||
inputs:
|
||||
versionSpec: 6.3.0
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: 'NuGet restore build/Helix/packages.config'
|
||||
inputs:
|
||||
restoreSolution: build/Helix/packages.config
|
||||
feedsToUse: config
|
||||
nugetConfigPath: nuget.config
|
||||
restoreDirectory: packages
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
condition:
|
||||
and(succeeded(),eq(variables['useBuildOutputFromBuildId'],''))
|
||||
inputs:
|
||||
artifactName: ${{ parameters.artifactName }}
|
||||
downloadPath: '$(artifactsDir)'
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
condition:
|
||||
and(succeeded(),ne(variables['useBuildOutputFromBuildId'],''))
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(System.TeamProjectId)
|
||||
pipeline: ${{ parameters.useBuildOutputFromPipeline }}
|
||||
buildId: $(useBuildOutputFromBuildId)
|
||||
artifactName: ${{ parameters.artifactName }}
|
||||
downloadPath: '$(artifactsDir)'
|
||||
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display Artifact Directory payload contents'
|
||||
inputs:
|
||||
filename: 'dir'
|
||||
arguments: '/s $(artifactsDir)'
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'PrepareHelixPayload.ps1'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\PrepareHelixPayload.ps1
|
||||
arguments: -Platform '$(buildPlatform)' -Configuration '$(buildConfiguration)' -ArtifactName '${{ parameters.artifactName }}'
|
||||
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display Helix payload contents'
|
||||
inputs:
|
||||
filename: 'dir'
|
||||
arguments: '/s $(Build.SourcesDirectory)\HelixPayload'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Make artifact directories'
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\"
|
||||
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\"
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.LocalTests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-TerminalAppLocalTests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\SettingsModel.LocalTests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-SettingsModelLocalTests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\Conhost.UIA.Tests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-HostTestsUIA.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),or(eq('${{ parameters.testSuite }}','PgoInstrumentationSuite'),eq('${{ parameters.testSuite }}','DevTestSuite')))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\WindowsTerminal.UIA.Tests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-WindowsTerminalUIATests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish generated .proj files'
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)
|
||||
artifactName: ${{ parameters.artifactName }}
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Run tests in Helix (open queues)'
|
||||
condition: and(succeeded(),eq(variables['System.CollectionUri'],'https://dev.azure.com/ms/'))
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
command: custom
|
||||
projects: build\Helix\RunTestsInHelix.proj
|
||||
custom: msbuild
|
||||
arguments: '$(helixCommonArgs) /p:IsExternal=true /p:Creator=Terminal /p:HelixTargetQueues=$(openHelixTargetQueues)'
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Run tests in Helix (closed queues)'
|
||||
condition: and(succeeded(),ne(variables['System.CollectionUri'],'https://dev.azure.com/ms/'))
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
HelixAccessToken: $(HelixApiAccessToken)
|
||||
inputs:
|
||||
command: custom
|
||||
projects: build\Helix\RunTestsInHelix.proj
|
||||
custom: msbuild
|
||||
arguments: '$(helixCommonArgs) /p:HelixTargetQueues=$(closedHelixTargetQueues)'
|
||||
@@ -1,70 +0,0 @@
|
||||
parameters:
|
||||
dependsOn: ''
|
||||
pgoArtifact: PGO
|
||||
platform: ''
|
||||
configuration: ''
|
||||
|
||||
jobs:
|
||||
- job: MergePGD
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
artifactsPath: $(Build.SourcesDirectory)\Artifacts
|
||||
pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }}
|
||||
buildPlatform: ${{ parameters.platform }}
|
||||
buildConfiguration: ${{ parameters.configuration }}
|
||||
|
||||
steps:
|
||||
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
|
||||
- script: |
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
|
||||
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
|
||||
del %TEMP%\vsinstalldir.txt
|
||||
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
- task: NuGetToolInstaller@0
|
||||
displayName: 'Use NuGet 6.3.0'
|
||||
inputs:
|
||||
versionSpec: 6.3.0
|
||||
|
||||
- task: NuGetAuthenticate@0
|
||||
|
||||
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
|
||||
# This should be `task: NuGetCommand@2`
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: Restore NuGet packages for extraneous build actions
|
||||
inputs:
|
||||
command: restore
|
||||
feedsToUse: config
|
||||
configPath: NuGet.config
|
||||
restoreSolution: build/packages.config
|
||||
restoreDirectory: '$(Build.SourcesDirectory)\packages'
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
inputs:
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
downloadPath: $(artifactsPath)
|
||||
|
||||
- task: MSBuild@1
|
||||
displayName: Merge counts into PGD
|
||||
inputs:
|
||||
solution: $(Build.SourcesDirectory)\OpenConsole.sln
|
||||
platform: $(buildPlatform)
|
||||
configuration: $(buildConfiguration)
|
||||
msbuildArguments: '/t:MergePGOCounts /p:PGOBuildMode=Instrument /p:PGDPath=$(pgoArtifactsPath)\$(buildPlatform) /p:PGCRootPath=$(pgoArtifactsPath)\$(buildPlatform)'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy merged pgd to artifact staging'
|
||||
inputs:
|
||||
sourceFolder: $(pgoArtifactsPath)
|
||||
contents: '**\$(buildPlatform)\*.pgd'
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathToPublish: $(Build.ArtifactStagingDirectory)
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
78
build/scripts/Merge-PriFiles.ps1
Normal file
78
build/scripts/Merge-PriFiles.ps1
Normal file
@@ -0,0 +1,78 @@
|
||||
Param(
|
||||
[Parameter(Mandatory,
|
||||
HelpMessage="List of PRI files or XML dumps (detailed only) to merge")]
|
||||
[string[]]
|
||||
$Path,
|
||||
|
||||
[Parameter(Mandatory,
|
||||
HelpMessage="Output Path")]
|
||||
[string]
|
||||
$OutputPath,
|
||||
|
||||
[Parameter(HelpMessage="Name of index in output file; defaults to 'Application'")]
|
||||
[string]
|
||||
$IndexName = "Application",
|
||||
|
||||
[Parameter(HelpMessage="Path to makepri.exe")]
|
||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||
[string]
|
||||
$MakePriPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakePri.exe"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
|
||||
New-Item -ItemType Directory -Path $tempDir | Out-Null
|
||||
$priConfig = Join-Path $tempDir "priconfig.xml"
|
||||
$priListFile = Join-Path $tempDir "pri.resfiles"
|
||||
$dumpListFile = Join-Path $tempDir "dump.resfiles"
|
||||
|
||||
@"
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources targetOsVersion="10.0.0" majorVersion="1">
|
||||
<index root="\" startIndexAt="dump.resfiles">
|
||||
<default>
|
||||
<qualifier name="Language" value="en-US" />
|
||||
<qualifier name="Contrast" value="standard" />
|
||||
<qualifier name="Scale" value="200" />
|
||||
<qualifier name="HomeRegion" value="001" />
|
||||
<qualifier name="TargetSize" value="256" />
|
||||
<qualifier name="LayoutDirection" value="LTR" />
|
||||
<qualifier name="DXFeatureLevel" value="DX9" />
|
||||
<qualifier name="Configuration" value="" />
|
||||
<qualifier name="AlternateForm" value="" />
|
||||
<qualifier name="Platform" value="UAP" />
|
||||
</default>
|
||||
<indexer-config type="PRIINFO" />
|
||||
<indexer-config type="RESFILES" qualifierDelimiter="." />
|
||||
</index>
|
||||
<index root="\" startIndexAt="pri.resfiles">
|
||||
<default>
|
||||
<qualifier name="Language" value="en-US" />
|
||||
<qualifier name="Contrast" value="standard" />
|
||||
<qualifier name="Scale" value="200" />
|
||||
<qualifier name="HomeRegion" value="001" />
|
||||
<qualifier name="TargetSize" value="256" />
|
||||
<qualifier name="LayoutDirection" value="LTR" />
|
||||
<qualifier name="DXFeatureLevel" value="DX9" />
|
||||
<qualifier name="Configuration" value="" />
|
||||
<qualifier name="AlternateForm" value="" />
|
||||
<qualifier name="Platform" value="UAP" />
|
||||
</default>
|
||||
<indexer-config type="PRI" />
|
||||
<indexer-config type="RESFILES" qualifierDelimiter="." />
|
||||
</index>
|
||||
</resources>
|
||||
"@ | Out-File -Encoding:utf8NoBOM $priConfig
|
||||
|
||||
$Path | Where { $_ -Like "*.pri" } | ForEach-Object {
|
||||
Get-Item $_ | Select -Expand FullName
|
||||
} | Out-File -Encoding:utf8NoBOM $priListFile
|
||||
|
||||
$Path | Where { $_ -Like "*.xml" } | ForEach-Object {
|
||||
Get-Item $_ | Select -Expand FullName
|
||||
} | Out-File -Encoding:utf8NoBOM $dumpListFile
|
||||
|
||||
& $MakePriPath new /pr $tempDir /cf $priConfig /o /in $IndexName /of $OutputPath
|
||||
|
||||
Remove-Item -Recurse -Force $tempDir
|
||||
47
build/scripts/Merge-TerminalAndXamlResources.ps1
Normal file
47
build/scripts/Merge-TerminalAndXamlResources.ps1
Normal file
@@ -0,0 +1,47 @@
|
||||
Param(
|
||||
[Parameter(Mandatory,
|
||||
HelpMessage="Root directory of extracted Terminal AppX")]
|
||||
[string[]]
|
||||
$TerminalRoot,
|
||||
|
||||
[Parameter(Mandatory,
|
||||
HelpMessage="Root directory of extracted Xaml AppX")]
|
||||
[string[]]
|
||||
$XamlRoot,
|
||||
|
||||
[Parameter(Mandatory,
|
||||
HelpMessage="Output Path")]
|
||||
[string]
|
||||
$OutputPath,
|
||||
|
||||
[Parameter(HelpMessage="Path to makepri.exe")]
|
||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||
[string]
|
||||
$MakePriPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakePri.exe"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
|
||||
New-Item -ItemType Directory -Path $tempDir | Out-Null
|
||||
|
||||
$terminalDump = Join-Path $tempDir "terminal.pri.xml"
|
||||
|
||||
& $MakePriPath dump /if (Join-Path $TerminalRoot "resources.pri") /of $terminalDump /dt detailed
|
||||
|
||||
Write-Verbose "Removing Microsoft.UI.Xaml node from Terminal to prevent a collision with XAML"
|
||||
$terminalXMLDocument = [xml](Get-Content $terminalDump)
|
||||
$resourceMap = $terminalXMLDocument.PriInfo.ResourceMap
|
||||
$fileSubtree = $resourceMap.ResourceMapSubtree | Where-Object { $_.Name -eq "Files" }
|
||||
$subtrees = $fileSubtree.ResourceMapSubtree
|
||||
$xamlSubtreeChild = ($subtrees | Where-Object { $_.Name -eq "Microsoft.UI.Xaml" })
|
||||
if ($Null -Ne $xamlSubtreeChild) {
|
||||
$null = $fileSubtree.RemoveChild($xamlSubtreeChild)
|
||||
$terminalXMLDocument.Save($terminalDump)
|
||||
}
|
||||
|
||||
$indexName = $terminalXMLDocument.PriInfo.ResourceMap.name
|
||||
|
||||
& (Join-Path $PSScriptRoot "Merge-PriFiles.ps1") -Path $terminalDump, (Join-Path $XamlRoot "resources.pri") -IndexName $indexName -OutputPath $OutputPath -MakePriPath $MakePriPath
|
||||
|
||||
Remove-Item -Recurse -Force $tempDir
|
||||
117
build/scripts/New-UnpackagedTerminalDistribution.ps1
Normal file
117
build/scripts/New-UnpackagedTerminalDistribution.ps1
Normal file
@@ -0,0 +1,117 @@
|
||||
Param(
|
||||
[Parameter(Mandatory,
|
||||
HelpMessage="Path to Terminal AppX")]
|
||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||
[string]
|
||||
$TerminalAppX,
|
||||
|
||||
[Parameter(Mandatory,
|
||||
HelpMessage="Path to Xaml AppX")]
|
||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||
[string]
|
||||
$XamlAppX,
|
||||
|
||||
[Parameter(HelpMessage="Output Directory")]
|
||||
[string]
|
||||
$Destination = ".",
|
||||
|
||||
[Parameter(HelpMessage="Path to makeappx.exe")]
|
||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||
[string]
|
||||
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakeAppx.exe"
|
||||
)
|
||||
|
||||
$filesToRemove = @("*.xml", "*.winmd", "Appx*", "Images/*Tile*", "Images/*Logo*") # Remove from Terminal
|
||||
$filesToKeep = @("Microsoft.Terminal.Remoting.winmd") # ... except for these
|
||||
$filesToCopyFromXaml = @("Microsoft.UI.Xaml.dll", "Microsoft.UI.Xaml") # We don't need the .winmd
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {
|
||||
Write-Error "Could not find MakeAppx.exe at `"$MakeAppxPath`".`nMake sure that -MakeAppxPath points to a valid SDK."
|
||||
Exit 1
|
||||
}
|
||||
|
||||
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
|
||||
New-Item -ItemType Directory -Path $tempDir | Out-Null
|
||||
|
||||
$XamlAppX = Get-Item $XamlAppX | Select-Object -Expand FullName
|
||||
$TerminalAppX = Get-Item $TerminalAppX | Select-Object -Expand FullName
|
||||
|
||||
########
|
||||
# Reading the AppX Manifest for preliminary info
|
||||
########
|
||||
|
||||
$appxManifestPath = Join-Path $tempDir AppxManifest.xml
|
||||
& tar.exe -x -f "$TerminalAppX" -C $tempDir AppxManifest.xml
|
||||
$manifest = [xml](Get-Content $appxManifestPath)
|
||||
$pfn = $manifest.Package.Identity.Name
|
||||
$version = $manifest.Package.Identity.Version
|
||||
$architecture = $manifest.Package.Identity.ProcessorArchitecture
|
||||
|
||||
$distributionName = "{0}_{1}_{2}" -f ($pfn, $version, $architecture)
|
||||
$terminalDir = "terminal-{0}" -f ($version)
|
||||
|
||||
########
|
||||
# Unpacking Terminal and XAML
|
||||
########
|
||||
|
||||
$terminalAppPath = Join-Path $tempdir $terminalDir
|
||||
$xamlAppPath = Join-Path $tempdir "xaml"
|
||||
New-Item -ItemType Directory -Path $terminalAppPath | Out-Null
|
||||
New-Item -ItemType Directory -Path $xamlAppPath | Out-Null
|
||||
& $MakeAppxPath unpack /p $TerminalAppX /d $terminalAppPath /o | Out-Null
|
||||
If ($LASTEXITCODE -Ne 0) {
|
||||
Throw "Unpacking $TerminalAppX failed"
|
||||
}
|
||||
& $MakeAppxPath unpack /p $XamlAppX /d $xamlAppPath /o | Out-Null
|
||||
If ($LASTEXITCODE -Ne 0) {
|
||||
Throw "Unpacking $XamlAppX failed"
|
||||
}
|
||||
|
||||
########
|
||||
# Some sanity checking
|
||||
########
|
||||
|
||||
$xamlManifest = [xml](Get-Content (Join-Path $xamlAppPath "AppxManifest.xml"))
|
||||
If ($xamlManifest.Package.Identity.Name -NotLike "Microsoft.UI.Xaml*") {
|
||||
Throw "$XamlAppX is not a XAML package (instead, it looks like $($xamlManifest.Package.Identity.Name))"
|
||||
}
|
||||
If ($xamlManifest.Package.Identity.ProcessorArchitecture -Ne $architecture) {
|
||||
Throw "$XamlAppX is not built for $architecture (instead, it is built for $($xamlManifest.Package.Identity.ProcessorArchitecture))"
|
||||
}
|
||||
|
||||
########
|
||||
# Preparation of source files
|
||||
########
|
||||
|
||||
$itemsToRemove = $filesToRemove | ForEach-Object {
|
||||
Get-Item (Join-Path $terminalAppPath $_) -EA:SilentlyContinue | Where-Object {
|
||||
$filesToKeep -NotContains $_.Name
|
||||
}
|
||||
} | Sort-Object FullName -Unique
|
||||
$itemsToRemove | Remove-Item -Recurse
|
||||
|
||||
$filesToCopyFromXaml | ForEach-Object {
|
||||
Get-Item (Join-Path $xamlAppPath $_)
|
||||
} | Copy-Item -Recurse -Destination $terminalAppPath
|
||||
|
||||
########
|
||||
# Resource Management
|
||||
########
|
||||
|
||||
$finalTerminalPriFile = Join-Path $terminalAppPath "resources.pri"
|
||||
& (Join-Path $PSScriptRoot "Merge-TerminalAndXamlResources.ps1") `
|
||||
-TerminalRoot $terminalAppPath `
|
||||
-XamlRoot $xamlAppPath `
|
||||
-OutputPath $finalTerminalPriFile `
|
||||
-Verbose:$Verbose
|
||||
|
||||
########
|
||||
# Packaging
|
||||
########
|
||||
|
||||
New-Item -ItemType Directory -Path $Destination -ErrorAction:SilentlyContinue | Out-Null
|
||||
$outputZip = (Join-Path $Destination ("{0}.zip" -f ($distributionName)))
|
||||
& tar -c --format=zip -f $outputZip -C $tempDir $terminalDir
|
||||
Get-Item $outputZip
|
||||
@@ -1,14 +0,0 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
|
||||
Param(
|
||||
[string]$NewWindowsVersion = "10.0.22000.0"
|
||||
)
|
||||
|
||||
Get-ChildItem src/cascadia/CascadiaPackage -Recurse -Filter *.appxmanifest | ForEach-Object {
|
||||
$xml = [xml](Get-Content $_.FullName)
|
||||
$xml.Package.Dependencies.TargetDeviceFamily | Where-Object Name -Like "Windows*" | ForEach-Object {
|
||||
$_.MinVersion = $NewWindowsVersion
|
||||
}
|
||||
$xml.Save($_.FullName)
|
||||
}
|
||||
@@ -1,27 +1,37 @@
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$true, Position=0)][string]$MatchPattern,
|
||||
[Parameter(Mandatory=$true, Position=1)][string]$Platform,
|
||||
[Parameter(Mandatory=$true, Position=2)][string]$Configuration,
|
||||
[Parameter(Mandatory=$false, Position=3)][string]$LogPath,
|
||||
[Parameter(Mandatory=$false)][string]$Root = ".\bin\$Platform\$Configuration"
|
||||
[Parameter(Mandatory=$true, Position=0)]
|
||||
[string]$MatchPattern,
|
||||
[Parameter(Mandatory=$true, Position=1)]
|
||||
[string]$Platform,
|
||||
[Parameter(Mandatory=$true, Position=2)]
|
||||
[string]$Configuration,
|
||||
[Parameter(Mandatory=$false, Position=3)]
|
||||
[string]$LogPath,
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$Root = ".\bin\$Platform\$Configuration",
|
||||
[string[]]$AdditionalTaefArguments
|
||||
)
|
||||
|
||||
$testdlls = Get-ChildItem -Path "$Root" -Recurse -Filter $MatchPattern
|
||||
# Find test DLLs based on the provided root, match pattern, and recursion
|
||||
$testDlls = Get-ChildItem -Path $Root -Recurse -Filter $MatchPattern
|
||||
|
||||
$args = @()
|
||||
|
||||
$args = @();
|
||||
|
||||
if ($LogPath)
|
||||
{
|
||||
$args += '/enablewttlogging';
|
||||
$args += '/appendwttlogging';
|
||||
$args += "/logFile:$LogPath";
|
||||
Write-Host "Wtt Logging Enabled";
|
||||
# Check if the LogPath parameter is provided and enable WTT logging
|
||||
if ($LogPath) {
|
||||
$args += '/enablewttlogging'
|
||||
$args += '/appendwttlogging'
|
||||
$args += "/logFile:$LogPath"
|
||||
Write-Host "WTT Logging Enabled"
|
||||
}
|
||||
|
||||
&"$Root\te.exe" $args $testdlls.FullName
|
||||
# Invoke the te.exe executable with arguments and test DLLs
|
||||
& "$Root\te.exe" $args $testDlls.FullName $AdditionalTaefArguments
|
||||
|
||||
if ($lastexitcode -Ne 0) { Exit $lastexitcode }
|
||||
# Check the exit code of the te.exe process and exit accordingly
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
Exit 0
|
||||
|
||||
@@ -96,11 +96,6 @@ Try {
|
||||
Throw "Failed to find App.xbf (TerminalApp project) in resources.pri"
|
||||
}
|
||||
|
||||
If (($null -eq (Get-Item "$AppxPackageRootPath\cpprest142_2_10.dll" -EA:Ignore)) -And
|
||||
($null -eq (Get-Item "$AppxPackageRootPath\cpprest142_2_10d.dll" -EA:Ignore))) {
|
||||
Throw "Failed to find cpprest142_2_10.dll -- check the WAP packaging project"
|
||||
}
|
||||
|
||||
If (($null -eq (Get-Item "$AppxPackageRootPath\wtd.exe" -EA:Ignore)) -And
|
||||
($null -eq (Get-Item "$AppxPackageRootPath\wt.exe" -EA:Ignore))) {
|
||||
Throw "Failed to find wt.exe/wtd.exe -- check the WAP packaging project"
|
||||
|
||||
@@ -10,22 +10,4 @@
|
||||
<OpenConsoleDir>$(MSBuildThisFileDirectory)</OpenConsoleDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
For the Windows 10 build, we're targeting the prerelease version of Microsoft.UI.Xaml.
|
||||
This version emits every XAML DLL directly into our package.
|
||||
This is a workaround for us not having deliverable MSFT-21242953 on this version of Windows.
|
||||
|
||||
This version should be tracked in all project packages.config files for projects that depend on Xaml.
|
||||
-->
|
||||
<TerminalMUXVersion>2.7.3-prerelease.220816001</TerminalMUXVersion>
|
||||
<!--
|
||||
For the Windows 11-specific build, we're targeting the public version of Microsoft.UI.Xaml.
|
||||
This version emits a package dependency instead of embedding the dependency in our own package.
|
||||
|
||||
This version should be tracked in build/packages.config.
|
||||
-->
|
||||
<TerminalMUXVersion Condition="'$(TerminalTargetWindowsVersion)'=='Win11'">2.7.3</TerminalMUXVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
12
custom.props
12
custom.props
@@ -2,18 +2,6 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- This file is read by XES, which we use in our Release builds. -->
|
||||
<PropertyGroup Label="Version">
|
||||
<!--
|
||||
The Windows 11 build is going to have the same package name, so it *must* have a different version.
|
||||
The easiest way for us to do this is to add 1 to the revision field.
|
||||
In short, for a given Terminal build 1.11, we will emit two different versions (assume this is build
|
||||
4 on day 23 of the year):
|
||||
- 1.11.234.0 for Windows 10
|
||||
- 1.11.235.0 for Windows 11
|
||||
This presents a potential for conflicts if we want to ship two builds produced back to back on the
|
||||
same day... which is terribly unlikely.
|
||||
-->
|
||||
<VersionBuildRevision Condition="'$(TerminalTargetWindowsVersion)'=='Win11' and '$(VersionBuildRevision)'!=''">$([MSBuild]::Add($(VersionBuildRevision), 1))</VersionBuildRevision>
|
||||
|
||||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2022</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
|
||||
@@ -2,15 +2,13 @@
|
||||
<!-- The packages.config acts as the global version for all of the NuGet packages contained within. -->
|
||||
<packages>
|
||||
<!-- Native packages -->
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
<package id="vcpkg-cpprestsdk" version="2.10.14" targetFramework="native" />
|
||||
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.6.220404001" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.7.230706001" targetFramework="native" />
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Native" version="2.3.2262" targetFramework="native" developmentDependency="true" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3-prerelease.220816001" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" developmentDependency="true" />
|
||||
|
||||
<!-- Managed packages -->
|
||||
|
||||
@@ -145,7 +145,7 @@ Our only backport successes really come from corporations with massive addressab
|
||||
|
||||
It's also costly in terms of time, effort, and testing for us to validate a modification to a released OS. We have a mindbogglingly massive amount of automated machinery dedicated to processing and validating the things that we check in while developing the current OS builds. But it's a special costly ask to spin up some to all of those activities to validate backported fixes. We do it all the time for Patch Tuesday, but in those patches, they only pass through the minimum number of fixes required to maximize the restoration of productivity/security/revenue/etc. because every additional fix adds additional complexity and additional risk.
|
||||
|
||||
So from our little team working hard to make developers happy, we virtually never make the cut for servicing. We're sorry, but we hope you can understand. It's just the reality of the situation to say "nope" when people ask for a backport. In our team's ideal world, you would all be running the latest console bits everywhere everytime we make a change. But that's just not how it is today.
|
||||
So from our little team working hard to make developers happy, we virtually never make the cut for servicing. We're sorry, but we hope you can understand. It's just the reality of the situation to say "nope" when people ask for a backport. In our team's ideal world, you would all be running the latest console bits everywhere every time we make a change. But that's just not how it is today.
|
||||
|
||||
Original Source: https://github.com/microsoft/terminal/issues/279#issuecomment-439179675
|
||||
|
||||
|
||||
@@ -82,7 +82,14 @@
|
||||
"properties": {
|
||||
"colorScheme": {
|
||||
"description": "The name of a color scheme to use when unfocused.",
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/SchemePair"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"foreground": {
|
||||
"$ref": "#/$defs/Color",
|
||||
@@ -233,6 +240,22 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"SchemePair": {
|
||||
"description": "Contains both a light and dark color scheme for the Terminal to use, depending on the theme of the application.",
|
||||
"properties": {
|
||||
"light": {
|
||||
"default": "Campbell",
|
||||
"description": "Name of the scheme to use when the app is using light theme",
|
||||
"type": "string"
|
||||
},
|
||||
"dark": {
|
||||
"default": "Campbell",
|
||||
"description": "Name of the scheme to use when the app is using dark theme",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"FontConfig": {
|
||||
"properties": {
|
||||
"face": {
|
||||
@@ -539,6 +562,160 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"NewTabMenuEntryType": {
|
||||
"enum": [
|
||||
"source",
|
||||
"profile",
|
||||
"folder",
|
||||
"separator",
|
||||
"remainingProfiles",
|
||||
"matchProfiles"
|
||||
]
|
||||
},
|
||||
"NewTabMenuEntry": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "The type of menu entry",
|
||||
"$ref": "#/$defs/NewTabMenuEntryType"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"FolderEntryInlining": {
|
||||
"enum": [
|
||||
"never",
|
||||
"auto"
|
||||
]
|
||||
},
|
||||
"FolderEntry": {
|
||||
"description": "A folder entry in the new tab dropdown",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/NewTabMenuEntry"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "folder"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The name of the folder to show in the menu"
|
||||
},
|
||||
"icon": {
|
||||
"$ref": "#/$defs/Icon"
|
||||
},
|
||||
"entries": {
|
||||
"type": "array",
|
||||
"description": "The entries to put inside this folder",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/NewTabMenuEntry"
|
||||
}
|
||||
},
|
||||
"inline": {
|
||||
"description": "When set to auto and the folder only has a single entry, the entry will show directly and no folder will be rendered",
|
||||
"default": "never",
|
||||
"$ref": "#/$defs/FolderEntryInlining"
|
||||
},
|
||||
"allowEmpty": {
|
||||
"description": "Whether to render a folder without entries, or to hide it",
|
||||
"default": "false",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"SeparatorEntry": {
|
||||
"description": "A separator in the new tab dropdown",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/NewTabMenuEntry"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "separator"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ProfileEntry": {
|
||||
"description": "A profile in the new tab dropdown",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/NewTabMenuEntry"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "profile"
|
||||
},
|
||||
"profile": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The name or GUID of the profile to show in this entry"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"RemainingProfilesEntry": {
|
||||
"description": "The set of profiles that are not yet explicitly included in another entry, such as the profile or source entries. This entry can be used at most one time!",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/NewTabMenuEntry"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "remainingProfiles"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"MatchProfilesEntry": {
|
||||
"description": "A set of profiles all matching the given name, source, or command line, to show in the new tab dropdown",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/NewTabMenuEntry"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "matchProfiles"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The name of the profiles to match"
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The source of the profiles to match"
|
||||
},
|
||||
"commandline": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The command line of the profiles to match"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"SwitchToAdjacentTabArgs": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -1546,6 +1723,145 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShowCloseButton": {
|
||||
"enum": [
|
||||
"always",
|
||||
"hover",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThemeColor": {
|
||||
"description": "A special kind of color for use in themes. Can be an #rrggbb color, #rrggbbaa color, or a special value. 'accent' is evaluated as the user's selected Accent color in the OS, and 'terminalBackground' will be evaluated as the background color of the active terminal pane.",
|
||||
"oneOf": [
|
||||
{
|
||||
"pattern": "^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{2})?)?$",
|
||||
"type": "string",
|
||||
"format": "color",
|
||||
"default": "#000000ff"
|
||||
},
|
||||
{
|
||||
"const": "accent",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"const": "terminalBackground",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"TabTheme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the tabs",
|
||||
"properties": {
|
||||
"background": {
|
||||
"description": "The color of a tab when it is the active tab",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
},
|
||||
"unfocusedBackground": {
|
||||
"description": "The color of a tab when it is not the active tab",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
},
|
||||
"showCloseButton": {
|
||||
"description": "Controls the visibility of the close button on the tab",
|
||||
"$ref": "#/$defs/ShowCloseButton"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TabRowTheme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the tab row",
|
||||
"properties": {
|
||||
"background": {
|
||||
"description": "The color of the tab row when the window is the foreground window.",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
},
|
||||
"unfocusedBackground": {
|
||||
"description": "The color of the tab row when the window is inactive",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"WindowTheme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the window itself",
|
||||
"properties": {
|
||||
"applicationTheme": {
|
||||
"description": "Which UI theme the Terminal should use for controls",
|
||||
"enum": [ "light", "dark", "system" ],
|
||||
"type": "string"
|
||||
},
|
||||
"useMica": {
|
||||
"description": "True if the Terminal should use a Mica backdrop for the window. This will apply underneath all controls (including the terminal panes and the titlebar)",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"Theme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the window. This controls things like the titlebar, the tabs, the application theme.",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the theme. This will be displayed in the settings UI.",
|
||||
"not": {
|
||||
"enum": [ "light", "dark", "system" ]
|
||||
}
|
||||
},
|
||||
"tab": {
|
||||
"$ref": "#/$defs/TabTheme"
|
||||
},
|
||||
"tabRow": {
|
||||
"$ref": "#/$defs/TabRowTheme"
|
||||
},
|
||||
"window": {
|
||||
"$ref": "#/$defs/WindowTheme"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ThemePair": {
|
||||
"additionalProperties": false,
|
||||
"description": "A pair of Theme names, to allow the Terminal to switch theme based on the OS theme",
|
||||
"properties": {
|
||||
"light": {
|
||||
"type": "string",
|
||||
"description": "The name of the theme to use when the OS is in Light theme",
|
||||
"default": "light"
|
||||
},
|
||||
"dark": {
|
||||
"type": "string",
|
||||
"description": "The name of the theme to use when the OS is in Dark theme",
|
||||
"default": "dark"
|
||||
}
|
||||
}
|
||||
},
|
||||
"NewTabMenu": {
|
||||
"description": "Defines the order and structure of the 'new tab' menu. It can consist of e.g. profiles, folders, and separators.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/FolderEntry"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/SeparatorEntry"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/ProfileEntry"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/MatchProfilesEntry"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/RemainingProfilesEntry"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Keybinding": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@@ -1924,20 +2240,32 @@
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"newTabMenu": {
|
||||
"$ref": "#/$defs/NewTabMenu"
|
||||
},
|
||||
"language": {
|
||||
"default": "",
|
||||
"description": "Sets an override for the app's preferred language, expressed as a BCP-47 language tag like en-US.",
|
||||
"type": "string"
|
||||
},
|
||||
"theme": {
|
||||
"default": "system",
|
||||
"description": "Sets the theme of the application. The special value \"system\" refers to the active Windows system theme.",
|
||||
"enum": [
|
||||
"light",
|
||||
"dark",
|
||||
"system"
|
||||
],
|
||||
"type": "string"
|
||||
"default": "dark",
|
||||
"description": "Sets the theme of the application. This value should be the name of one of the themes defined in `themes`. The Terminal also includes the themes `dark`, `light`, and `system`.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/ThemePair"
|
||||
}
|
||||
]
|
||||
},
|
||||
"themes": {
|
||||
"description": "The list of available themes",
|
||||
"items": {
|
||||
"$ref": "#/$defs/Theme"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"showTabsInTitlebar": {
|
||||
"default": true,
|
||||
@@ -2170,7 +2498,14 @@
|
||||
"colorScheme": {
|
||||
"default": "Campbell",
|
||||
"description": "Name of the terminal color scheme to use. Color schemes are defined under \"schemes\".",
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/SchemePair"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"commandline": {
|
||||
"description": "Executable used in the profile.",
|
||||
|
||||
235
doc/color_nudging.html
Normal file
235
doc/color_nudging.html
Normal file
@@ -0,0 +1,235 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Perceptual Color Nudging</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
html {
|
||||
background-color: #0c0c0c;
|
||||
color: #cccccc;
|
||||
font-family: "Cascadia Code", "Cascadia Mono", monospace;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
body>div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
form,
|
||||
h2 {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
p,
|
||||
pre {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table td {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="flex: 2; align-items: flex-start; background-color: #0c0c0c">
|
||||
<form>
|
||||
<input id="background-color" name="background-color" type="color" value="#0c0c0c" />
|
||||
<label for="background-color">background color</label>
|
||||
</form>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Input</td>
|
||||
<td>WCAG21:<br>APCA:</td>
|
||||
<td id="stats-input"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ΔE2000<br>(ConEmu)</td>
|
||||
<td>WCAG21:<br>APCA:</td>
|
||||
<td id="stats-cielab"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ΔEOK</td>
|
||||
<td>WCAG21:<br>APCA:</td>
|
||||
<td id="stats-oklab"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="input" style="flex: 1">
|
||||
<h2>Input</h2>
|
||||
<pre style="font-size: 8pt">猫</pre>
|
||||
<pre style="font-size: 10pt">猫</pre>
|
||||
<pre style="font-size: 12pt">猫</pre>
|
||||
<pre style="font-size: 14pt">猫</pre>
|
||||
<pre style="font-size: 16pt">猫</pre>
|
||||
<pre style="font-size: 32pt">猫</pre>
|
||||
<pre style="font-size: 64pt">猫</pre>
|
||||
</div>
|
||||
<div id="cielab" style="flex: 1">
|
||||
<h2>ΔE2000 (ConEmu)</h2>
|
||||
<pre style="font-size: 8pt">猫</pre>
|
||||
<pre style="font-size: 10pt">猫</pre>
|
||||
<pre style="font-size: 12pt">猫</pre>
|
||||
<pre style="font-size: 14pt">猫</pre>
|
||||
<pre style="font-size: 16pt">猫</pre>
|
||||
<pre style="font-size: 32pt">猫</pre>
|
||||
<pre style="font-size: 64pt">猫</pre>
|
||||
</div>
|
||||
<div id="oklab" style="flex: 1">
|
||||
<h2>ΔEOK</h2>
|
||||
<pre style="font-size: 8pt">猫</pre>
|
||||
<pre style="font-size: 10pt">猫</pre>
|
||||
<pre style="font-size: 12pt">猫</pre>
|
||||
<pre style="font-size: 14pt">猫</pre>
|
||||
<pre style="font-size: 16pt">猫</pre>
|
||||
<pre style="font-size: 32pt">猫</pre>
|
||||
<pre style="font-size: 64pt">猫</pre>
|
||||
</div>
|
||||
<script type="module">
|
||||
import Color from "https://cdn.jsdelivr.net/npm/colorjs.io@0.4.3/+esm";
|
||||
|
||||
window.Color = Color;
|
||||
|
||||
const input = document.getElementById("input");
|
||||
const cielab = document.getElementById("cielab");
|
||||
const oklab = document.getElementById("oklab");
|
||||
|
||||
const statsInput = document.getElementById("stats-input");
|
||||
const statsCielab = document.getElementById("stats-cielab");
|
||||
const statsOklab = document.getElementById("stats-oklab");
|
||||
|
||||
let backgroundColor = new Color("#0c0c0c");
|
||||
let foregroundColor = new Color("#0c0c0c");
|
||||
let foregroundColorRange = null;
|
||||
let previousSecsIntegral = -1;
|
||||
|
||||
function saturate(val) {
|
||||
return val < 0 ? 0 : val > 1 ? 1 : val;
|
||||
}
|
||||
|
||||
function clipToSrgb(color) {
|
||||
return color.to("srgb").toGamut({ method: "clip" });
|
||||
}
|
||||
|
||||
function nudgeCielab(backgroundColor, foregroundColor) {
|
||||
const backgroundCielab = backgroundColor.to("lab-d65");
|
||||
const foregroundCielab = foregroundColor.to("lab-d65");
|
||||
|
||||
const de1 = Color.deltaE(foregroundColor, backgroundCielab, "2000");
|
||||
if (de1 >= 12.0) {
|
||||
return foregroundColor;
|
||||
}
|
||||
|
||||
for (let i = 0; i <= 1; i++) {
|
||||
const step = (i == 0) ? 5.0 : -5.0;
|
||||
foregroundCielab.l += step;
|
||||
|
||||
while (((i == 0) && foregroundCielab.l <= 100) || (i == 1 && foregroundCielab.l >= 0)) {
|
||||
const de2 = Color.deltaE(foregroundCielab, backgroundCielab, "2000");
|
||||
if (de2 >= 20.0) {
|
||||
return clipToSrgb(foregroundCielab);
|
||||
}
|
||||
foregroundCielab.l += step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nudgeOklab(backgroundColor, foregroundColor) {
|
||||
const backgroundOklab = backgroundColor.to("oklab");
|
||||
const foregroundOklab = foregroundColor.to("oklab");
|
||||
const deltaSquared = {
|
||||
l: (backgroundOklab.l - foregroundOklab.l) ** 2,
|
||||
a: (backgroundOklab.a - foregroundOklab.a) ** 2,
|
||||
b: (backgroundOklab.b - foregroundOklab.b) ** 2,
|
||||
};
|
||||
const distance = deltaSquared.l + deltaSquared.a + deltaSquared.b;
|
||||
|
||||
if (distance >= 0.25) {
|
||||
return foregroundColor;
|
||||
}
|
||||
|
||||
let deltaL = Math.sqrt(0.25 - deltaSquared.a - deltaSquared.b);
|
||||
if (foregroundOklab.l < backgroundOklab.l)
|
||||
{
|
||||
deltaL = -deltaL;
|
||||
}
|
||||
|
||||
foregroundOklab.l = backgroundOklab.l + deltaL;
|
||||
if (foregroundOklab.l < 0 || foregroundOklab.l > 1)
|
||||
{
|
||||
foregroundOklab.l = backgroundOklab.l - deltaL;
|
||||
}
|
||||
|
||||
return clipToSrgb(foregroundOklab);
|
||||
}
|
||||
|
||||
function contrastStringLevels(num, level0, level1) {
|
||||
const str = num.toFixed(1);
|
||||
if (num < level0) {
|
||||
return `<span style="color:crimson">${str}</span>`;
|
||||
}
|
||||
if (num < level1) {
|
||||
return `<span style="color:coral">${str}</span>`;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function contrastString(foregroundColor) {
|
||||
const contrastWCAG21 = contrastStringLevels(foregroundColor.contrast(backgroundColor, "WCAG21"), 3, 4.5);
|
||||
const contrastAPCA = contrastStringLevels(Math.abs(foregroundColor.contrast(backgroundColor, "APCA")), 45, 60);
|
||||
return `${contrastWCAG21}<br/>${contrastAPCA}`;
|
||||
}
|
||||
|
||||
function animate(time) {
|
||||
const timeScale = time / 1000;
|
||||
const secsIntegral = Math.trunc(timeScale);
|
||||
const secsFractional = timeScale % 1;
|
||||
|
||||
if (previousSecsIntegral != secsIntegral) {
|
||||
const foregroundColorTarget = new Color("srgb", backgroundColor.coords.map(c => saturate(c + Math.random() - 0.5)));
|
||||
foregroundColorRange = foregroundColor.range(foregroundColorTarget, { space: "srgb" });
|
||||
previousSecsIntegral = secsIntegral;
|
||||
}
|
||||
|
||||
foregroundColor = foregroundColorRange(secsFractional);
|
||||
input.style.color = foregroundColor.toString({ inGamut: false });
|
||||
|
||||
const foregroundCielabNudged = nudgeCielab(backgroundColor, foregroundColor);
|
||||
const foregroundOklabNudged = nudgeOklab(backgroundColor, foregroundColor);
|
||||
|
||||
cielab.style.color = foregroundCielabNudged;
|
||||
oklab.style.color = foregroundOklabNudged;
|
||||
|
||||
statsInput.innerHTML = contrastString(foregroundColor);
|
||||
statsCielab.innerHTML = contrastString(foregroundCielabNudged);
|
||||
statsOklab.innerHTML = contrastString(foregroundOklabNudged);
|
||||
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
document.getElementById("background-color").addEventListener("input", event => {
|
||||
backgroundColor = new Color(event.target.value);
|
||||
document.documentElement.style.backgroundColor = backgroundColor;
|
||||
}, false);
|
||||
|
||||
document.documentElement.style.backgroundColor = backgroundColor;
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,410 @@
|
||||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2021-03-03
|
||||
last updated: 2022-11-04
|
||||
issue id: #2634
|
||||
---
|
||||
|
||||
# Broadcast Input
|
||||
|
||||
## Abstract
|
||||
|
||||
"Broadcast Input" is a feature present on other terminals which allows the user
|
||||
to send the same input to multiple tabs or panes at the same time. This can make
|
||||
it simpler for the user to run the same command in multiple directories or
|
||||
servers at the same time.
|
||||
|
||||
With a viable prototype in [#9222], it's important that we have a well-defined
|
||||
plan for how we want this feature to be exposed before merging that PR. This
|
||||
spec is intended to be a lighter-than-usual spec to build consensus on the
|
||||
design of how the actions should be expressed.
|
||||
|
||||
## Background
|
||||
|
||||
### Inspiration
|
||||
|
||||
This spec is heavily inspired by the [iTerm2 implementation]. @carlos-zamora did
|
||||
a great job of breaking down how iTerm2 works in [this comment].
|
||||
|
||||
SecureCRT also implements a similar feature using a "chat window" that can send
|
||||
the input in the chat window to all tabs. This seemed like a less ergonomic
|
||||
solution, so it was not seriously considered.
|
||||
|
||||
Additionally, Terminator (on \*nix) allows for a similar feature through the use
|
||||
of "groups". From [@zljubisic]:
|
||||
|
||||
> In Linux terminator you can define groups, and than put each pane in one of
|
||||
> defined groups. Afterwards, you can choose broadcasting to all panes, only
|
||||
> certain group or no broadcast at all.
|
||||
|
||||
This also seemed like a less powerful version of broadcast input than the
|
||||
iterm2-like version, so it was also not further investigated.
|
||||
|
||||
### User Stories
|
||||
|
||||
iTerm2 supports the following actions:
|
||||
|
||||
* **Story A:** _Send input to current session only_: The default setting.
|
||||
* **Story B:** _Broadcast to all panes in all tabs_: Anything you type on the
|
||||
keyboard goes to all sessions in this window.
|
||||
* **Story C:** _Broadcast to all panes in current tab_: Anything you type on the
|
||||
keyboard goes to all sessions in this tab.
|
||||
* **Story D:** _Toggle broadcast input to current session_: Toggles whether this
|
||||
session receives broadcasted keystrokes within this window.
|
||||
|
||||
|
||||
## Solution Design
|
||||
|
||||
### Proposal 1: iTerm2-like Modal Input Broadcast
|
||||
|
||||
iTerm2 implements broadcast input as a type of "modal" system. The user is in
|
||||
one of the following modes:
|
||||
|
||||
* Broadcast to all panes in all tabs
|
||||
* Broadcast to all panes in the current tab
|
||||
* Broadcast to some set of panes within the current tab
|
||||
* Don't broadcast input at all (the default behavior)
|
||||
|
||||
These modes are vaguely per-tab state. There's a global "broadcast to all tabs &
|
||||
panes" property. Then, each tab also has a pair of values:
|
||||
* Should input be sent to all panes in this tab?
|
||||
* If not, which panes should input be sent to?
|
||||
|
||||
It's not possible to send input to one pane in tab A, then another pane in tab
|
||||
B, without enabling the global "broadcast to everyone" mode.
|
||||
|
||||
This seems to break down into the following actions:
|
||||
|
||||
```json
|
||||
{ "action": "toggleBroadcastInput", "scope": "window" },
|
||||
{ "action": "toggleBroadcastInput", "scope": "tab" },
|
||||
{ "action": "toggleBroadcastInput", "scope": "pane" },
|
||||
{ "action": "disableBroadcastInput" },
|
||||
```
|
||||
|
||||
Which would be accompanied by the following internal properties:
|
||||
* A window (`TerminalPage`-level) property for `broadcastToAllPanesAndTabs`
|
||||
* A per-tab property for `broadcastToAllPanes`
|
||||
* A per-tab set of panes to broadcast to
|
||||
|
||||
The scopes would work as follows:
|
||||
|
||||
* `"scope": "window"`: Toggle the window's "broadcast to all tabs and panes"
|
||||
setting.
|
||||
* `"scope": "tab"`: Toggle the tab's "broadcast to all panes in this tab"
|
||||
setting.
|
||||
- This does not modify the set of panes that the user is broadcasting to in
|
||||
the tab, merely toggles the tab's setting. If the user has a set of panes
|
||||
they're broadcasting to in this tab, then toggles this setting on and off,
|
||||
we'll return to broadcasting to that set.
|
||||
* `"scope": "pane"`: Add this pane to the set of panes being broadcasted to in
|
||||
this tab.
|
||||
- **TODO!: FOR DISCUSSION**: Should this disable the tab's
|
||||
"broadcastToAllPanes" setting? Or should it leave that alone?
|
||||
* `"disableBroadcastInput"`: Set the global setting to false, the tab's setting
|
||||
to false, and clear the set of panes being broadcasted to for this tab.
|
||||
- **TODO!** This could also just be `"action": "toggleBroadcastInput",
|
||||
"scope": "none"`
|
||||
|
||||
#### Pros
|
||||
* This is exactly how iTerm2 does it, so there's prior art.
|
||||
* If you're not globally broadcasting, then you're only ever broadcasting to
|
||||
some (sub)set of the panes in the current tab. So global broadcast mode is
|
||||
the only time a user would need to worry about input being to be sent to
|
||||
an inactive tab.
|
||||
* You can have a set of panes to broadcast to in the first tab, then a
|
||||
_separate_ set to broadcast to in a second tab. Broadcasting in one tab
|
||||
does not affect the other.
|
||||
|
||||
#### Cons
|
||||
* I frankly think the `tab`/`pane` interaction can be a little weird. Like for
|
||||
this scenario:
|
||||
- enable broadcast input for tab 1
|
||||
- switch to tab 2
|
||||
- enable broadcast input for a pane in tab 2
|
||||
|
||||
There's valid confusion to be had between the following two behaviors:
|
||||
1. input goes to all of tab 1 _and_ the pane in tab 2
|
||||
2. input only goes to the pane in tab 2
|
||||
* You can't broadcast to a subset of panes in inactive tabs, in addition to
|
||||
the active tab. All panes you want to broadcast to must be in the active
|
||||
tab.
|
||||
* Does creating a new split in a pane that's being broadcast to add that pane to
|
||||
the broadcast set?
|
||||
|
||||
#### What would this mean for PR #9222?
|
||||
|
||||
The prototype PR [#9222] basically just implemented `{ "action":
|
||||
"toggleBroadcastInput", "scope": "tab" }`. We could make `tab` the default
|
||||
`scope` if no other one is specified, and then the PR would need basically no
|
||||
modifications. Future PRs could add args to the `toggleBroadcastInput` action,
|
||||
without breaking users who bind a key to that action now.
|
||||
|
||||
### Proposal 2: Broadcast Set
|
||||
|
||||
This was the design I had originally came up with before investigating iTerm2
|
||||
much closer. This design involves a "broadcast set" of panes. All the panes in
|
||||
the broadcast set would also get the `KeySent` and `CharSent` events, in
|
||||
addition to the active pane. (The active pane may be a part of the broadcast
|
||||
set). If a pane is read-only in the broadcast set, then it won't handle those
|
||||
broadcasted events (obviously).
|
||||
|
||||
As far as actions, we're looking at something like:
|
||||
|
||||
* **A** Only send input to the active pane
|
||||
* Remove all the panes from the broadcast set
|
||||
* **B** send input to all panes in all tabs
|
||||
* If all the panes are in the broadcast set, remove them all. Otherwise, add
|
||||
all panes in all tabs to the broadcast set.
|
||||
* **C** send input to all panes in the current tab
|
||||
* If all the panes in the current tab are in the broadcast set, remove them
|
||||
from the broadcast set. Otherwise, add all the panes from this tab to the
|
||||
broadcast set.
|
||||
* **D** toggle sending input to the current pane
|
||||
* If this pane is in the broadcast set, remove it. Otherwise add it.
|
||||
This seems to break down into the following actions:
|
||||
|
||||
```json
|
||||
{ "action": "disableBroadcastInput" },
|
||||
{ "action": "toggleBroadcastInput", "scope": "window" },
|
||||
{ "action": "toggleBroadcastInput", "scope": "tab" },
|
||||
{ "action": "toggleBroadcastInput", "scope": "pane" },
|
||||
```
|
||||
|
||||
Which would be accompanied by the following internal properties:
|
||||
* A window (`TerminalPage`-level) set of panes to broadcast to.
|
||||
|
||||
#### Pros:
|
||||
* Mentally, you're either adding panes to the set of panes to broadcast to, or
|
||||
removing them.
|
||||
* You can broadcast to panes in multiple tabs, without broadcasting to _all_
|
||||
panes in all tabs.
|
||||
|
||||
#### Cons:
|
||||
* is _slightly_ different from iTerm2.
|
||||
* Does creating a new split in a pane that's being broadcast to add that pane to
|
||||
the broadcast set?
|
||||
* You can't have a set of panes to broadcast to in the one tab, and a different
|
||||
set in another tab. As an example:
|
||||
1. in tab 1, you add panes A and B to the broadcast set. Typing in either one
|
||||
goes to both A and B.
|
||||
2. in tab 1, switch to pane C. Now input goes to A, B and C.
|
||||
3. in tab 1, switch to pane D. Now input goes to A, B and D.
|
||||
4. switch to tab 2, pane E. Now input goes to A, B and E.
|
||||
|
||||
You can't have like, a set with A & B (in 1), then E & F (in 2). So if someone
|
||||
wants to type to both panes in 1, then both panes in 2, then both panes in 1,
|
||||
they need to keep toggling which panes are in the broadcast set.
|
||||
|
||||
#### What would this mean for PR #9222?
|
||||
|
||||
Similar to Proposal 1, we'd use `tab` as the default value for `scope`. In the
|
||||
future, when we add support for the other scopes, we'd change how the
|
||||
broadcasting works, to use a set of panes to broadcast to, instead of just the
|
||||
tab-level property.
|
||||
|
||||
### Proposal 3: It's iTerm2, but slightly different
|
||||
|
||||
While typing this up, I thought maybe it might make more sense if we took the
|
||||
iTerm2 version, and changed it slightly:
|
||||
|
||||
* `"scope": "tab"`: If all the panes are in the broadcast set for this tab, then
|
||||
remove them all. Otherwise, add all the panes in this tab to this tab's
|
||||
broadcast set.
|
||||
* `"scope": "pane"`: If this pane is in the broadcast set for a tab, then remove
|
||||
it. Otherwise, add it.
|
||||
|
||||
With this, we get rid of the tab-level setting for "broadcast to all the panes
|
||||
in this tab", and rely only on the broadcast set for that tab.
|
||||
|
||||
#### Pros:
|
||||
* All the pros from proposal A
|
||||
* Does away with the seemingly weird toggling between "all the panes in a tab"
|
||||
and "some of the panes in a tab" that's possible with proposal A
|
||||
|
||||
#### Cons:
|
||||
* You can't broadcast to a subset of panes in inactive tabs, in addition to
|
||||
the active tab. All panes you want to broadcast to must be in the active
|
||||
tab.
|
||||
* is _slightly_ different from iTerm2. Just _slightly_.
|
||||
* Does creating a new split in a pane that's being broadcast to add that pane to
|
||||
the broadcast set?
|
||||
|
||||
#### What would this mean for PR #9222?
|
||||
|
||||
Same as with proposal A, we wouldn't change anything in the current PR. A future
|
||||
PR that would add the other scope's to that action would need to change how the
|
||||
broadcasting within a tab works, to use a set of panes to broadcast to, instead
|
||||
of just the tab-level property.
|
||||
|
||||
## Conclusion
|
||||
|
||||
I'm proposing these settings for broader discussion. I'm not really sure which I
|
||||
like most at this point. 1 & 3 have the advantage of being most similar to the
|
||||
prior art, but 2 is more easily extendable to "groups" (see [Future
|
||||
Considerations](#Future-Considerations)).
|
||||
|
||||
**TODO!**: Make a decision.
|
||||
|
||||
_**Fortunately**_: All these proposals actually use the same set of actions. So
|
||||
it doesn't _really_ matter which we pick right now. We can unblock [#9222] as
|
||||
the implementation of the `"tab"` scope, and address other scopes in the future.
|
||||
We should still decide long-term which of these we'd like, but the actions seem
|
||||
universal.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
This is supposed to be a quick & dirty spec, so I'm LARGELY skipping this.
|
||||
|
||||
As far as indicators go, we'll throw something like:
|
||||
|
||||

|
||||
|
||||
in the tab when a pane is being broadcasted to. If all tabs are being
|
||||
broadcasted to, then they'll all have that icon. If a tab is inactive, and any
|
||||
pane in that tab is being broadcast to, then show the icon in the tab.
|
||||
|
||||
It probably makes the most sense to have pane titlebars ([#4998]) also display
|
||||
that icon.
|
||||
|
||||
In the original PR, it was suggested to use some variant of the [accent color]
|
||||
to on the borders of panes that are currently receiving broadcasted input. We're
|
||||
already using the accent color on the borders of the active pane.
|
||||
`SystemAccentColorLight*`/`SystemAccentColorDark*` would provide a way of using
|
||||
a similar hue with different lightness/saturation. This would be a decent visual
|
||||
indicator that they're _not_ the active pane, but they are going to receive
|
||||
input. Something a bit like:
|
||||
|
||||

|
||||
|
||||
This should obviously be able to be overridden in the user's theme, similar to
|
||||
the pane border colors.
|
||||
|
||||
iTerm2 also supports displaying "stripes" in the background of all the panes
|
||||
that are being broadcast too. That's certainly another way of indicating this
|
||||
feature to the user. I'm not sure how we'd layer it with the background image
|
||||
though. **I recommend we ignore this for now, and leave this as a follow-up**.
|
||||
|
||||
### Tab context menu items
|
||||
|
||||
For reference, refer to the following from iTerm2:
|
||||

|
||||
|
||||
We don't have a menu bar like on MacOS, but we do have a tab context menu. We
|
||||
could add these items as a nested entry under each tab. If we wanted to do this,
|
||||
we should also make sure to dynamically change the icon of the MenuItem to
|
||||
reflect the current broadcast state.
|
||||
|
||||
## Potential Issues
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td><strong>Compatibility</strong></td>
|
||||
<td>
|
||||
|
||||
[comment]: # Will the proposed change break existing code/behaviors? If so, how, and is the breaking change "worth it"?
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
[comment]: # If there are any other potential issues, make sure to include them here.
|
||||
|
||||
## Implementation plan
|
||||
|
||||
* [ ] Resurrect [#9222], and use that to implement `"scope": "tab"`. This is
|
||||
implemented the same, regardless of which proposal we chose.
|
||||
* [ ] Add a tab context menu entry for toggling broadcast input, with a dynamic
|
||||
icon based on the current state.
|
||||
* [ ] Implement `"scope": "window"`. Again, this is implemented the same regardless
|
||||
of which proposal we pursue.
|
||||
* [ ] Decide between the two proposals here.
|
||||
* [ ] Implement `"scope": "pane"`.
|
||||
|
||||
Doing the first element here is probably the most important one for most users,
|
||||
and can be done regardless of the proposal chosen here. As such, we could even
|
||||
suggest the default value of `scope` be `tab`. If we did that, then we wouldn't
|
||||
need to do any args at all in the initial version.
|
||||
|
||||
## Future Considerations
|
||||
|
||||
Let's look to iTerm2, who's supported this feature for years, for some
|
||||
inspiration of future things we should be worried about. If their users have
|
||||
asked for these features, then it's inevitable that our users will too 😉
|
||||
|
||||
* [iterm2#6709] - Broadcast Input to multiple windows
|
||||
- This is pretty straightforward. Would require coordination with the Monarch
|
||||
though, and I'm worried about the perf hit of tossing every keystroke across
|
||||
the process boundary.
|
||||
- I suppose this would be `{ "action": "toggleBroadcastInput", "scope":
|
||||
"global" }`
|
||||
* [iterm2#6451], [iterm2#5563] - "Broadcast commands"
|
||||
- iTerm2 has an action that lets the user manually clear the terminal-side
|
||||
buffer. (This is tracked on the Windows Terminal as [#1882]). It might make
|
||||
sense for there to be a mode where some _actions_ are also broadcast to
|
||||
panes, not just key strokes. But which actions would those be? Moving the
|
||||
selection anchors? Copy doesn't really make sense. Paste _does_ though.
|
||||
Maybe the open find dialog / next&prev search match actions?
|
||||
- This probably would require it's own spec.
|
||||
* [iterm2#6007] - Different stripe color for different broadcast modes
|
||||
- Have one color to indicate when broadcasting in `global` scope, another in
|
||||
`tab` scope, a third in `pane` scope.
|
||||
- This might mesh well with theming ([#3327]), for properties like
|
||||
`pane.broadcastBorderColor.globalScope`,
|
||||
`pane.broadcastBorderColor.paneScope`. Don't love those names, but you get
|
||||
the idea.
|
||||
* **[iterm2#5639]: Broadcast groups**, [iterm2#3372] - Broadcast Input to
|
||||
multiple but not all tabs
|
||||
- This is probably the most interesting request. I think this one identifies a
|
||||
major shortcoming of the above proposals. With proposal 2, there's only ever
|
||||
one top-level broadcast group. With proposals 1 & 3, there's per-tab
|
||||
broadcast groups. In neither proposal can you have multiple concurrent
|
||||
side-by-side broadcast groups.
|
||||
- Groups should probably work across tabs. This would suggest that Proposal 2
|
||||
is closer to how groups would work. Instead of there being one top-level
|
||||
set, there would be multiple. **I'm not sure how proposals 1&3 would
|
||||
seamlessly transition into also supporting groups**.
|
||||
- The major trick here is: how do we differentiate these different groups to
|
||||
the user? If we used the broadcast icon with a number, maybe in the corner
|
||||
of the tab? Like [📡: 1]? Can a pane be in multiple broadcast sets at the
|
||||
same time?
|
||||
- The natural arg idea would be `{ "action": "toggleBroadcastInput", "scope":
|
||||
"tab", "group": 1 }` to say "add all panes in the tab to broadcast group 1",
|
||||
or "remove all panes in the tab from broadcast group 1". If panes are in
|
||||
another group, they'd be moved to the specified group. If all panes are in
|
||||
that group, then remove them all.
|
||||
- The UI for this would certainly get complex fast.
|
||||
- This also matches the Terminator-style broadcasting to groups.
|
||||
* Re: stripes in the background of the tab. We could expose a pane's current
|
||||
broadcast state to the pixel shader, and a user could use a custom pixel
|
||||
shader to add stripes behind the text in the shader code. That's one possible
|
||||
solution.
|
||||
|
||||
## Resources
|
||||
|
||||
[comment]: # Be sure to add links to references, resources, footnotes, etc.
|
||||
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]:
|
||||
|
||||
|
||||
[#1882]: https://github.com/microsoft/terminal/issues/1882
|
||||
[#2634]: https://github.com/microsoft/terminal/issues/2634
|
||||
[#4998]: https://github.com/microsoft/terminal/issues/4998
|
||||
[#3327]: https://github.com/microsoft/terminal/issues/3327
|
||||
[#9222]: https://github.com/microsoft/terminal/pull/9222
|
||||
[this comment]: https://github.com/microsoft/terminal/issues/2634#issuecomment-789116413
|
||||
[iTerm2 implementation]: https://iterm2.com/documentation-one-page.html#documentation-menu-items.html
|
||||
[@zljubisic]: https://github.com/microsoft/terminal/pull/9222#issuecomment-789143189
|
||||
[accent color]: https://docs.microsoft.com/en-us/windows/uwp/design/style/color#accent-color-palette
|
||||
|
||||
|
||||
[iterm2#6709]: https://gitlab.com/gnachman/iterm2/-/issues/6709
|
||||
[iterm2#6451]: https://gitlab.com/gnachman/iterm2/-/issues/6451
|
||||
[iterm2#6007]: https://gitlab.com/gnachman/iterm2/-/issues/6007
|
||||
[iterm2#5639]: https://gitlab.com/gnachman/iterm2/-/issues/5639
|
||||
[iterm2#5563]: https://gitlab.com/gnachman/iterm2/-/issues/5563
|
||||
[iterm2#3372]: https://gitlab.com/gnachman/iterm2/-/issues/3372
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 336 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1,380 @@
|
||||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2021-08-31
|
||||
last updated: 2021-08-31
|
||||
issue id: #642
|
||||
---
|
||||
|
||||
# Buffer Exporting and Logging
|
||||
|
||||
## Abstract
|
||||
|
||||
A common user need is the ability to export the history of a terminal session to
|
||||
a file, for later inspection or validation. This is something that could be
|
||||
triggered manually. Many terminal emulators provide the ability to automatically
|
||||
log the output of a session to a file, so the history is always captured. This
|
||||
spec will address improvements to the Windows Terminal to enable these kinds of
|
||||
exporting and logging scenarios.
|
||||
|
||||
## Background
|
||||
|
||||
### Inspiration
|
||||
|
||||
Below are screenshots from the settings pages of three different terminal
|
||||
emulators with similar features - PuTTY, SecureCRT, and ConEmu:
|
||||
|
||||

|
||||
|
||||
_figure 1: PuTTY settings_
|
||||
|
||||

|
||||
|
||||
_figure 2: SecureCRT settings_
|
||||
|
||||

|
||||
|
||||
_figure 3: ConEmu settings_
|
||||
|
||||
These applications all offer some settings in common. Primarily, the important
|
||||
feature is the ability to specify a path to a log file which contains some
|
||||
special string formatting. This allows the user to log to different files based
|
||||
on the time & date of the session, or based on the session name.
|
||||
|
||||
### User Stories
|
||||
|
||||
* **Story A**: The user is able to use a context menu entry on the tab to export
|
||||
the contents of the buffer to a file, which they are prompted for.
|
||||
- This is explicitly what was requested in [#642]
|
||||
* **Story B**: The user can bind an action to export the contents of the buffer
|
||||
to a file, which they are prompted for.
|
||||
- Very similar to **A**, but via the command palette or a keybinding.
|
||||
* **Story C**: The user can export to an explicit file via an action
|
||||
- similar to **B**, but allowing for declaring the path to a file rather than
|
||||
prompting at runtime.
|
||||
* **Story D**: The user can choose to append to a file when exporting, rather
|
||||
than overwriting.
|
||||
* **Story E**: The user can specify a format string in the path to the file to
|
||||
export to, which the Terminal will automatically replace with variables like
|
||||
the time, date, and profile name.
|
||||
* **Story F**: When opening a specific profile, the user can automatically log
|
||||
to a file
|
||||
* **Story G**: The user can execute an action to start or stop logging to a
|
||||
given file.
|
||||
|
||||
|
||||
## Solution Design
|
||||
|
||||
I'm proposing the following actions and profile settings
|
||||
|
||||
* New Action: `exportBuffer()`.
|
||||
- Export the contents of the buffer to a file.
|
||||
- `path` (string, defaults to `""`): When empty, prompt the user for a name of
|
||||
a file to export to, using a file picker. This path accepts special
|
||||
formatting strings that will be substituted with certain variables
|
||||
(discussed [below](#path-formatting)).
|
||||
- `append` (boolean, defaults to `false`): When `false`, the file's contents
|
||||
will be overwritten. When `true`, the buffer contents will be appended to
|
||||
the end of the file.
|
||||
* New Profile Settings object: `logSettings`
|
||||
- This is an object that describes a set of behavior for logging a profile.
|
||||
- `path`: Same as the `path` in the `ExportBufferArgs` above
|
||||
- `append`: Same as the `append` in the `ExportBufferArgs` above
|
||||
- `captureAllOutput`: (boolean, defaults to `false`) When true, don't log only
|
||||
printable characters, also log non-printable escape characters written to
|
||||
the Terminal.
|
||||
- `captureInput`: (boolean, defaults to `false`) Additionally log input to the
|
||||
Terminal to the file. Input will be formatted as the traditional VT
|
||||
sequences, rather than the full `win32-input` encoding.
|
||||
- `newFileEveryDay`: (boolean, defaults to `false`) This requires the `day` to
|
||||
be an element of the path format string. When logging with this setting,
|
||||
opens a new file at midnight and starts writing that one.
|
||||
<!-- TODO! - `flushFrequently`: (boolean, defaults to `true`) -->
|
||||
* New Profile setting: `logAutomatically` (boolean, default `false`). When true,
|
||||
terminals with this profile will begin logging automatically.
|
||||
* New Action: `toggleLogging()`.
|
||||
- Start or stop logging to the configured file. If the terminal is already
|
||||
logging with different settings than in this action, then stop logging
|
||||
regardless (don't just start logging to the new file)
|
||||
- This action accepts all the same args the profile's `logSettings` object.
|
||||
- If _any_ args are provided, use those args. If _none_ are provided, then use
|
||||
the logging settings present in the profile (if there are any).
|
||||
- If there's not path provided (either in the args to the action or in the
|
||||
profile), prompt the user to pick a file to log to.
|
||||
|
||||
### Examples
|
||||
```json
|
||||
{
|
||||
"actions": [
|
||||
{ "keys": "f1", "command": "exportBuffer" },
|
||||
{ "keys": "f2", "command": { "action": "exportBuffer", "path": "c:\\logs\\${year}-${month}-${date}\\{profile}.txt" } },
|
||||
|
||||
{ "keys": "f3", "command": "toggleLogging" },
|
||||
{ "keys": "f4", "command": { "action": "toggleLogging", "path": "c:\\logs\\${profile}.log", "append": true } },
|
||||
],
|
||||
"profiles": [
|
||||
{
|
||||
"name": "foo",
|
||||
"logging": {
|
||||
"path": "c:\\foo.txt",
|
||||
"append": true
|
||||
},
|
||||
"automaticallyLog": false
|
||||
},
|
||||
{
|
||||
"name": "bar",
|
||||
"logging": {
|
||||
"path": "c:\\logs\\${date}\\bar.txt",
|
||||
"append": false
|
||||
},
|
||||
"automaticallyLog": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Revisiting our original stories:
|
||||
|
||||
* **Story A**: This is already implemented in [#11062]
|
||||
* **Story B**: This is the action bound to <kbd>f1</kbd>.
|
||||
* **Story C**: This is the action bound to <kbd>f2</kbd>.
|
||||
* **Story D**: This is the `append` property in the actions, profile settings.
|
||||
* **Story E**: An example of this is in the action bound to <kbd>f2</kbd>,
|
||||
<kbd>f4</kbd>, and in the profile "bar"'s logging settings.
|
||||
* **Story F**: The profile "bar" is configured to automatically log when opened.
|
||||
* **Story G**: This is the action bound to <kbd>f4</kbd>.
|
||||
|
||||
In addition,
|
||||
* When opening the profile "foo", it will not automatically log to a file.
|
||||
- Pressing <kbd>f3</kbd> will begin logging to `c:\foo.txt`
|
||||
- Pressing <kbd>f4</kbd> will begin logging to `c:\logs\foo.log`
|
||||
|
||||
### Path formatting
|
||||
|
||||
[TODO!]: # TODO!
|
||||
|
||||
For discussion: What syntax do we want?
|
||||
* PuTTY uses `&Y`, `&M`, `&D`, `&T`, `&H`, `&P` for year, month, day, time, host
|
||||
and port respectively.
|
||||
* SecureCRT uses:
|
||||
- `%H` – hostname
|
||||
- `%S` – session name
|
||||
- `%Y` – four-digit year
|
||||
- `%M` – two-digit month
|
||||
- `%D` – two-digit day of the month
|
||||
- `%h` – two-digit hour
|
||||
- `%m` – two-digit minute
|
||||
- `%s` – two-digit seconds
|
||||
- `%t` – three-digit milliseconds
|
||||
- `%%` – percent (%)
|
||||
- `%envvar%` – environment variable (for instance `%USERNAME%`)
|
||||
|
||||
We have some precedent for formatting with `${braces}`, a la the iterable
|
||||
command in the Command Palette (e.g `${profile.name}`). Additionally, [#9287]
|
||||
implements support for environment variables in the Terminal with the
|
||||
`${env:VARIABLE}` syntax.
|
||||
|
||||
What variables do we want exposed, and how do we want users to be able to format
|
||||
them?
|
||||
|
||||
This doc was initially authored assuming we'd go with a `${braces}` syntax, like:
|
||||
- `${profile}` – profile name
|
||||
- `${year}` – four-digit year
|
||||
- `${month}` – two-digit month
|
||||
- `${day}` – two-digit day of the month
|
||||
- `${hour}` – two-digit hour
|
||||
- `${minute}` – two-digit minute
|
||||
- `${second}` – two-digit second
|
||||
- `${ms}` – three-digit milliseconds
|
||||
- `${env:variable}` – environment variable (for instance `${env:USERPROFILE}`)
|
||||
(inspired by [#9287])
|
||||
|
||||
### Exporting vs Logging
|
||||
As far as specific implementation details goes, exporting is the easier work to
|
||||
do. [#11062] already wires up the `TerminalApp` to retrieve the buffer contents
|
||||
from the `TermControl`, so writing them at request is easy.
|
||||
|
||||
Logging is harder. We don't want the `TermControl` telling the `TerminalApp`
|
||||
layer about every piece of output logged. Especially in the post-[#5000] world
|
||||
where that's a cross-process hop. Instead, we'll want the `ControlCore` /
|
||||
`ControlInteractivity` to do _logging_ themselves.
|
||||
|
||||
### Logging Mechanics
|
||||
|
||||
#### When do we log?
|
||||
|
||||
[TODO!]: # TODO!
|
||||
|
||||
When do we decide to actually log? Take for example typing in a `pwsh` or
|
||||
`bash` prompt. Imagine the user types
|
||||
<kbd>w</kbd><kbd>h</kbd><kbd>a</kbd><kbd>t</kbd>, then hits
|
||||
<kbd>Bksp</kbd><kbd>Bksp</kbd>, such that the prompt is just `wh`. What should
|
||||
the log contain? `what^h ^h^h ^h`<sup>[[1]](#footnote-1)</sup>? `wh`?
|
||||
|
||||
My worry with logging the backspaces is that conpty is sometimes a bit noisier
|
||||
than it needs to be with using `^H` as a cursor positioning sequence. Should we
|
||||
only log lines when the cursor newlines or otherwise moves from the line it is
|
||||
currently on?
|
||||
|
||||
I'll need to look at what PuTTY emits for the "Printable output" option.
|
||||
|
||||
#### What happens when we _start_ logging?
|
||||
|
||||
If the user has a terminal that did not start with logging enabled, but then
|
||||
started logging with `toggleLogging`, what should we log? All future output? Or
|
||||
should we log the current buffer contents as well?
|
||||
|
||||
I'm inclined to lean towards simply "all future output", and ignore any current
|
||||
buffer content. If the user rally wants to log the current buffer contents _and_
|
||||
start logging, they can use a `multipleActions` action ([#11045]) to
|
||||
`exportBuffer` to a file, then `toggleLogging` to that same file with
|
||||
`"append":true`.
|
||||
|
||||
## Potential Issues
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td><strong>Compatibility</strong></td>
|
||||
<td>
|
||||
|
||||
Since this functionality is entirely new, nothing here should negatively affect
|
||||
existing functionality.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Performance, Power, and Efficiency</strong></td>
|
||||
<td>
|
||||
|
||||
When logging, it's expected there will be a measurable performance hit. We can
|
||||
try to mitigate this by only writing to the file on a background thread,
|
||||
separate from the connection or rendering thread. Since auto-logging will only
|
||||
take place in the content process, we're not worried about the file writing
|
||||
occurring on the UI thread.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Also frequently requested is the ability to log timestamps of when commands are
|
||||
executed. I don't think that this is a valuable feature for the Terminal to
|
||||
implement ourselves. Windows Terminal is fundamentally just a _terminal
|
||||
emulator_, it doesn't really know what's going on behind the scenes with
|
||||
whatever client application (`cmd`, `powershell`, `bash`, `vim`) that is
|
||||
connected to it. WT doesn't know when the user is typing in commands to the
|
||||
shell, or if the user is just typing in text in `emacs` or something. There's no
|
||||
way for the terminal to know that. It's _typically_ the client application's
|
||||
responsibility to save it's own command history. `bash` and `powershell` both do
|
||||
a pretty good job of saving this to another file to restore across sessions,
|
||||
while `cmd.exe` doesn't.
|
||||
|
||||
Windows is a messy world and this model gets a little tricky here. `cmd.exe`
|
||||
isn't actually managing it's own command history _at all_. `conhost` is doing
|
||||
that work on behalf of the client applications. Some long time ago someone
|
||||
thought it would be a good idea to have the `readline` functionality baked
|
||||
directly into the console host. Whether that was a good idea or not remains to
|
||||
be seen - it's certainly made things like `python.exe`'s REPL easier to
|
||||
implement, since they don't need to maintain their own history buffer, but it
|
||||
makes it hard to de-tangle behavior like this from the console itself.
|
||||
|
||||
I'm not sure how it would be possible to add a keybinding to the Windows
|
||||
Terminal that would be able to save the console's _command_ history. Especially
|
||||
considering the Terminal might _not_ be connected to a console host session at
|
||||
all. If the Windows Terminal were directly running a `wsl` instance (something
|
||||
that's not possible today, but something we've considered adding in the future),
|
||||
then there wouldn't be a `conhost` in the process tree at all, and now
|
||||
requesting the command history from the console wouldn't work _mysteriously_.
|
||||
|
||||
Furthermore, shells can always be configured to emit timestamps in their prompts
|
||||
themselves. Since the Terminal has no knowledge of when a command is actually
|
||||
entered, but the _shell_ does, it makes the most sense to configure the user's
|
||||
_shell_ to emit that information. The Terminal will then dutifully log that
|
||||
output along with everything else.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
Below is a rough outline of how I'd go about implementing these features. Each
|
||||
lop-level checkbox could be its own PR, following from [#11062].
|
||||
|
||||
### Buffer exporting
|
||||
|
||||
* [ ] Add an `exportBuffer()` action that opens the file picker
|
||||
* [ ] Add a string `path` parameter to `exportBuffer()` that allows the user to
|
||||
press a key and immediately export the buffer to a whole path
|
||||
- default to `""`, which indicates "open the file picker"
|
||||
* [ ] add a boolean `append` (default to `false`) parameter to `exportBuffer`.
|
||||
When true, export to the file given by appending, not overwriting the file
|
||||
* [ ] Enable string formatting in the `path` parameter.
|
||||
- What format do we want? `yyyy-mm-dd`? `%Y-%m-%D`? `&Y-&m-&D`? `${year}-${month}-${day}`?
|
||||
- What are all the variables we want?
|
||||
- Year, month, day, hour, minute - those are easy
|
||||
- `WT_SESSION`, for a uuid for each session maybe?
|
||||
- Profile name perhaps? Commandline?
|
||||
* [ ] more...
|
||||
|
||||
### Automatic logging
|
||||
|
||||
* [ ] `toggleLogging()` Action for start/stop logging, with `path`, `append`
|
||||
properties (like `exportBuffer()`)
|
||||
- `ToggleLoggingArgs` contains a single member `LoggingSettings`, which
|
||||
contains `path` and `append` properties. This will make sense below.
|
||||
* [ ] add `LoggingSettings` property for "log all output" (default would just be
|
||||
"log printable output")
|
||||
* [ ] add `LoggingSettings` property for "log input" (Though, we'd probably want
|
||||
to log it as normal VT encoded, not as `win32-input` encoded)
|
||||
* [ ] Per-profile setting for `logSettings`, which can contain an entire
|
||||
`LoggingSettings` (like the `ToggleLoggingArgs`). When `toggleLogging` with no
|
||||
args, try to use the profile's `loggingSettings` instead.
|
||||
* [ ] Per-profile setting for `automaticallyLog`, which would log by default
|
||||
when the profile is opened
|
||||
* [ ] `LoggingSettings` property for "New file every day", which only works when
|
||||
the `{day}` is in the path string. When auto-logging with this setting, opens
|
||||
a new file at midnight and starts writing that one.
|
||||
<!-- * [ ] `LoggingSettings` property for "Flush log frequently", defaults to
|
||||
`true`(?). This causes us to flush all output to the file, instead of just...
|
||||
on close? on newline? It's unclear exactly when PuTTY flushes with this off.
|
||||
Need more coffee. -->
|
||||
|
||||
### Future Considerations
|
||||
|
||||
* When logging begins, the Terminal could display a toast for "Logging to
|
||||
{filename}", and a similar one for "Stopped logging to {filename}".
|
||||
* There's no good way of displaying a UI element to indicate that a pane is
|
||||
currently logging to a file. I don't believe PuTTY displays any sort of
|
||||
indicator. SecureCRT only displays a checkbox within the context menus of the
|
||||
application itself.
|
||||

|
||||
|
||||
Maybe when logging to a file, we could replace the "Export Text" context menu
|
||||
entry with "Stop Logging"
|
||||
* We could maybe add a setting to disable logging from the alt buffer. This
|
||||
might help make this setting more valuable for users who are using full-screen
|
||||
applications like `vim`. Since those applications redraw the entire viewport
|
||||
contents frequently, the log might be unnecessarily noisy. Disabling logging
|
||||
while in the alt buffer would show that the user opened vim, and then they did
|
||||
some things after vim exited.
|
||||
* Logging all output will be VERY helpful to us in the future for trying to
|
||||
recreate bugs on our end that users can repro but we can't!
|
||||
|
||||
## Resources
|
||||
|
||||
PuTTY Logging documentation: https://tartarus.org/~simon/putty-snapshots/htmldoc/Chapter4.html#config-logfilename
|
||||
ConEmu Logging documentation: https://conemu.github.io/en/AnsiLogFiles.html
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]: Remember that `^H` is non-destructive, so the
|
||||
sequence `what^h ^h^h ^h` is can be read as:
|
||||
* print "what"
|
||||
* move the cursor back one
|
||||
* print a space (overwriting 't')
|
||||
* move the cursor back one (now it's on the space where 't' was)
|
||||
* move the cursor back one
|
||||
* print a space (overwriting 'a')
|
||||
* move the cursor back one (now it's on the space where 'a' was)
|
||||
|
||||
[#642]: https://github.com/microsoft/terminal/issues/642
|
||||
[#5000]: https://github.com/microsoft/terminal/issues/5000
|
||||
[#9287]: https://github.com/microsoft/terminal/pull/9287
|
||||
[#11045]: https://github.com/microsoft/terminal/pull/11045
|
||||
[#11062]: https://github.com/microsoft/terminal/pull/11062
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user