Compare commits

...

46 Commits

Author SHA1 Message Date
Leonard Hecker
5bfa47ec33 Simplify passing color tables 2023-08-29 19:15:35 +02:00
Leonard Hecker
d54ce33afc Fix pattern coordinates to be viewport relative (#15892)
Pattern tree coordinates are viewport-relative.

Closes #15891

## Validation Steps Performed
* Print some text so the viewport scrolls down
* Print a URL
* URL is underlined on hover 
2023-08-29 18:47:26 +02:00
Leonard Hecker
c4436157c1 A small optimization of COOKED_READ_DATA::_erase (#15879)
This is a small optimization that makes COOKED_READ_DATA erase short
runs of text more quickly. It's not really necessary to do this as
this code is not a hotpath, but I felt like it's neater this way.
It requires no heap allocations even for long runs of text.

## Validation Steps Performed
* Deleting text anywhere in a prompt erases it 
2023-08-28 11:23:17 +00:00
Leonard Hecker
821ae3af2d Rewrite COOKED_READ_DATA (#15783)
This massive refactoring has two goals:
* Enable us to go beyond UCS-2 support for input editing
* Bring clarity into `COOKED_READ_DATA`'s inner workings

Unfortunately, over time, knowledge about its exact operation was lost.
While the new code is still complex it reduces the amount of code by 4x
which will make preserving knowledge hopefully significantly easier.

The new implementation is simpler and slower than the old one in a way,
because every time the input line is modified it's rewritten to the text
buffer from scratch. This however massively simplifies the underlying
algorithm and the amount of state that needs to be tracked and results
in a significant reduction in code size. It also makes it more robust,
because there's less code now that can be incorrect.

This "optimization laziness" can be afforded due the recent >10x
improvements to `TextBuffer`'s text ingestion performance.
For short inputs (<1000 characters) I still expect this implementation
to outperform the conhost from the past.
It has received one optimization already however: While reading text
from the `InputBuffer` we'll now defer writing into the `TextBuffer`
until we've stopped reading. This improves the overhead of pasting text
from O(n^2) to O(n), which is immediately noticeable for inputs >100kB.

Resizing the text buffer still ends up corrupting the input line
however, which unfortunately cannot be fixed in `COOKED_READ_DATA`.
The issue occurs due to bugs in `TextBuffer::Reflow` itself, as it
misplaces the cursor if the prompt is on the last line of the buffer.

Closes #1377
Closes #1503
Closes #4628
Closes #4975
Closes #5033
Closes #8008

This commit is required to fix #797

## Validation Steps Performed
* ASCII input 
* Chinese input (中文維基百科) 
  * Resizing the window properly wraps/unwraps wide glyphs 
    Broken due to `TextBuffer::Reflow` bugs
* Surrogate pair input (🙂) 
  * Resizing the window properly wraps/unwraps surrogate pairs 
    Broken due to `TextBuffer::Reflow` bugs
* In cmd.exe
  * Create 2 file: "a😊b.txt" and "a😟b.txt"
  * Press tab: Autocompletes "a😊b.txt" 
  * Navigate the cursor right past the "a"
  * Press tab twice: Autocompletes "a😟b.txt" 
* Backspace deletes preceding glyphs 
* Ctrl+Backspace deletes preceding words 
* Escape clears input 
* Home navigates to start 
* Ctrl+Home deletes text between cursor and start 
* End navigates to end 
* Ctrl+End deletes text between cursor and end 
* Left navigates over previous code points 
* Ctrl+Left navigates to previous word-starts 
* Right and F1 navigate over next code points 
  * Pressing right at the end of input copies characters
    from the previous command 
* Ctrl+Right navigates to next word-ends 
* Insert toggles overwrite mode 
* Delete deletes next code point 
* Up and F5 cycle through history 
  * Doesn't crash with no history 
  * Stops at first entry 
* Down cycles through history 
  * Doesn't crash with no history 
  * Stops at last entry 
* PageUp retrieves the oldest command 
* PageDown retrieves the newest command 
* F2 starts "copy to char" prompt 
  * Escape dismisses prompt 
  * Typing a character copies text from the previous command up
    until that character into the current buffer (acts identical
    to F3, but with automatic character search) 
* F3 copies the previous command into the current buffer,
  starting at the current cursor position,
  for as many characters as possible 
  * Doesn't erase trailing text if the current buffer
    is longer than the previous command 
  * Puts the cursor at the end of the copied text 
* F4 starts "copy from char" prompt 
  * Escape dismisses prompt 
  * Erases text between the current cursor position and the
    first instance of a given char (but not including it) 
* F6 inserts Ctrl+Z 
* F7 without modifiers starts "command list" prompt 
  * Escape dismisses prompt 
  * Minimum size of 40x10 characters 
  * Width expands to fit the widest history command 
  * Height expands up to 20 rows with longer histories 
  * F9 starts "command number" prompt 
  * Left/Right paste replace the buffer with the given command 
    * And put cursor at the end of the buffer 
  * Up/Down navigate selection through history 
    * Stops at start/end with <10 entries 
    * Stops at start/end with >20 entries 
    * Wide text rendering during pagination with >20 entries 
  * Shift+Up/Down moves history items around 
  * Home navigates to first entry 
  * End navigates to last entry 
  * PageUp navigates by 20 items at a time or to first 
  * PageDown navigates by 20 items at a time or to last 
* Alt+F7 clears command history 
* F8 cycles through commands that start with the same text as
  the current buffer up until the current cursor position 
  * Doesn't crash with no history 
* F9 starts "command number" prompt 
  * Escape dismisses prompt 
  * Ignores non-ASCII-decimal characters 
  * Allows entering between 1 and 5 digits 
  * Pressing Enter fetches the given command from the history 
* Alt+F10 clears doskey aliases 
2023-08-25 18:25:39 +00:00
Carlos Zamora
2fb4a7fa91 Make screen reader announce successful MovePane and MoveTab actions (#15771)
Uses the `RaiseNotificationEvent()` API from UIA automation peers to
announce successful `MovePane` and `MoveTab` actions. The announcements
are localized in the resw file.

Closes #15159
Based on #13575
2023-08-25 16:38:41 +00:00
Leonard Hecker
cd80f3c764 Use ICU for text search (#15858)
The ultimate goal of this PR was to use ICU for text search to
* Improve Unicode support
  Previously we used `towlower` and only supported BMP glphs.
* Improve search performance (10-100x)
  This allows us to search for all results in the entire text buffer
  at once without having to do so asynchronously.

Unfortunately, this required some significant changes too:
* ICU's search facilities operate on text positions which we need to be
  mapped back to buffer coordinates. This required the introduction of
  `CharToColumnMapper` to implement sort of a reverse-`_charOffsets`
  mapping. It turns text (character) positions back into coordinates.
* Previously search restarted every time you clicked the search button.
  It used the current selection as the starting position for the new
  search. But since ICU's `uregex` cannot search backwards we're
  required to accumulate all results in a vector first and so we
  need to cache that vector in between searches.
* We need to know when the cached vector became invalid and so we have
  to track any changes made to `TextBuffer`. The way this commit solves
  it is by splitting `GetRowByOffset` into `GetRowByOffset` for
  `const ROW` access and `GetMutableRowByOffset` which increments a
  mutation counter on each call. The `Search` instance can then compare
  its cached mutation count against the previous mutation count.

Finally, this commit makes 2 semi-unrelated changes:
* URL search now also uses ICU, since it's closely related to regular
  text search anyways. This significantly improves performance at
  large window sizes.
* A few minor issues in `UiaTracing` were fixed. In particular
  2 functions which passed strings as `wstring` by copy are now
  using `wstring_view` and `TraceLoggingCountedWideString`.

Related to #6319 and #8000

## Validation Steps Performed
* Search upward/downward in conhost 
* Search upward/downward in WT 
* Searching for any of ß, ẞ, ss or SS matches any of the other 
* Searching for any of Σ, σ, or ς matches any of the other 
2023-08-24 22:56:40 +00:00
Dustin L. Howett
5651f08770 Add a Nightly build pipeline for the Canary branding (#15869)
To make this happen, I moved most of `release.yml` into a shared
_pipeline_ template (which is larger than a steps or jobs template).
Most of the diffs are due to that move.

If you compare main:build/pipelines/release.yml against 
dev/duhowett/nightly-build:build/pipelines/templates-v2/pipeline-full-release-build.yml,
you will see that the changes are much more minimal than they look.

I also added a parameter to configure how long symbols will be kept. It
defaults to 36530 days (which is the default for the PublishSymbols
task! Yes, 100 years!) but nightly builds will get 15 days.
2023-08-24 22:15:54 +00:00
Mike Griese
0f61b5f97d Remove the FontSizeChanged event from TermControl (#15867)
I originally just wanted to close #1104, but then discovered that hey,
this event wasn't even used anymore. Excerpts of Teams convo:

* [Snap to character grid when resizing window by mcpiroman · Pull
Request #3181 · microsoft/terminal
(github.com)](https://github.com/microsoft/terminal/pull/3181/files#diff-d7ca72e0d5652fee837c06532efa614191bd5c41b18aa4d3ee6711f40138f04c)
added it to Tab.cpp
  * where it was added 
  * which called `pane->Relayout` which I don't even REMEMBER
* By [Add functionality to open the Settings UI tab through openSettings
by leonMSFT · Pull Request #7802 · microsoft/terminal
(github.com)](https://github.com/microsoft/terminal/pull/7802/files#diff-83d260047bed34d3d9d5a12ac62008b65bd6dc5f3b9642905a007c3efce27efd),
there was seemingly no FontSizeChanged in Tab.cpp (when it got moved to
terminaltab.cpp)
 

> `Pane::Relayout` functionally did nothing because sizing was switched
 to `star` sizing at some point in the past, so it was just deleted.

From [Misc pane refactoring by Rosefield · Pull Request #11373 ·
microsoft/terminal](https://github.com/microsoft/terminal/pull/11373/files#r736900998)

So, great. We can kill part of it, and convert the rest to a
`TypedEvent`, and get rid of `DECLARE_` / `DEFINE_`.

`ScrollPositionChangedEventArgs` was ALSO apparently already promoted to
a typed event, so kill that too.
2023-08-24 19:53:03 +00:00
Mike Griese
7a05501907 A first couple Suggestion UI nits (#15848)
Closes the active checkboxes in #15845. I'll leave that open till we get
to the endgame, I'm sure more will show up.

Closes:

- [x] Accessibility tags all have `CommandPalette_` strings 🤣 
- [x] useCommandline should leave the cursor at the _end_ of the input,
not at the start
- [x] useCommandline, when bottom-up, should leave the _last_ list item
selected, not the first.
- [x] ^ Probably applies to any changes to the filter text when bottom
up.
2023-08-24 14:13:49 -05:00
Dustin L. Howett
b024efb3b7 Disambiguate the test job artifact based on attempt number (#15877)
Closes #15876
2023-08-24 19:11:42 +00:00
John HU
10ea38c9a7 README: Explain why 1.17/1.18 don't winget (#15840)
We chose to link to the Terminal issue rather than the WinGet one,
because ours has more contextual information.
2023-08-24 10:32:36 -05:00
Mike Griese
30eb9eed49 Raise ShortcutActions with the sender (tab, control) context (#15773)
This PR's goal is to allow something like a `Tab` to raise a
ShortcutAction, by saying "this action should be performed on ME". We've
had a whole category of these issues in the past:

* #15734
* #15760 
* #13579
* #13942
* #13942
* Heck even dating back to #10832

So, this tries to remove a bit of that footgun. This probably isn't the
_final_ form of what this refactor might look like, but the code is
certainly better than before.

Basically, there's a few bits:

* `ShortcutActionDispatch.DoAction` now takes a `sender`, which can be
_anything_.
* Most actions that use a "Get the focused _thing_ then do something to
it" are changed to "If there was a sender, let's use that - otherwise,
we'll use the focused _thing_".
* TerminalTab was largely refactored to use this, instead of making
requests to the `TerminalPage` to just do a thing to it.

I've got a few TODO!s left, but wanted to get initial feedback. 
* [x] `TerminalPage::_HandleTogglePaneZoom`
* [x] `TerminalPage::_HandleFocusPane`
* [x] `TerminalPage::_MoveTab`


Closes #15734
2023-08-24 10:31:09 -05:00
hanpuliu-charles
e10b7e4fb9 Add --appendCommandLine flag for appending to command (#15822)
Added --appendCommandLine flag that when set, appends the command to the
preset command in the profile instead of replacing it.

Previously, there was no good way to launch wt while running a command
appended to the set command in the profile. Some uses include profiles
that are set to login or start an application.

Additional comments: Looking for a review, and expecting additional
changes that needs to be done. For example, I am not really sure on how
to include the the option's information in the CallForHelp() screen.
Also, would be great if someone could guide me on including tests for
this new feature. Thanks!

Closes #5528

---------

Co-authored-by: Charles Liu <hliu729@outlook.com>
2023-08-24 06:45:28 -05:00
Mike Griese
921d7c3316 Add a Canary branding option (#15865)
Obviously, icons are all wrong. Color is about right but they need CAN
icons.

I'll leave that as an exercise for @DHowett to generate the right ones
as a follow-up.

Related to #774
2023-08-23 11:17:11 -05:00
Dustin L. Howett
8f20ea6b2d Include our Azure client ID in AzureConnection (#15866)
Some folks over in MSAL land told us that client IDs don't need to be
kept secret.

This reduces the delta between "public" terminal and "release build"
terminal by one more file, leaving only the telemetry header left (which
won't be going public for obvious reasons).

This will also make it easier for contributors to test out Azure Cloud
Shell changes... and testing out VT without ConPTY interfering[^1].

[^1]: When Dev branding is selected, Azure Cloud Shell has the added
perk of being wired directly to TerminalCore rather than going through
ConPTY.
2023-08-23 14:25:06 +02:00
Dustin L. Howett
333fcd89b3 Use a different schema for each branding (#15856)
Switch the schema depending on the branding we're being built for

Ever since we started writing the entire settings file out ourselves,
we've had the opportunity to control which schema it uses.

This is a quality-of-life improvement for Preview users, and might make
life easier for Dev users as well.

For Debug builds, it even switches over to a local `file://` path to
the schema in the source directory!

Closes #6601
2023-08-22 05:39:14 -05:00
Tushar Singh
21c2dee50a [Tests] Add test for subparameter based GraphicOptions (#15844)
Add test for subparameter based `GraphicOptions`.

`GraphicsSingleWithSubParamTests` is added for subparameter based
`GraphicOptions`. This should've been included with #15729.

Also, while working on #15795, I realized creating and passing
subparameters for the tests is painful right now. I've added a small
util `MakeSubParamsAndRanges(...)` that eases creating subparameters and
subparameter ranges from a simple list of (lists of) subparameters.

## Validation Steps Performed
- All tests passed.
2023-08-21 15:18:36 -05:00
Dustin L. Howett
df648208d5 Remove outdated or implied build conditions and parameters (#15842)
We no longer multiplex PGO through the test runner. We also removed the
compliance build.
2023-08-21 18:55:50 +00:00
Dustin L. Howett
6cb14d226d Allow skipping artifact publication in all release build jobs (#15846)
The OneBranch build system relies on the *build container host* being
able to publish all artifacts all at once. Therefore, our build steps
must not publish any artifacts.

I made it configurable so that the impact on existing pipelines was
minimal.

For every job that produces artifacts and is part of the release
pipeline, I am now exposing two variables that we can pass to OneBranch
so that it can locate and name artifacts:
- `JobOutputDirectory`, the output folder for the entire job
- `JobOutputArtifactName`, the name of the artifact produced by the job

I have also added a `variables` parameter to every job, so consuming
pipelines can override or insert their own variables.
2023-08-21 13:09:17 -05:00
Tushar Singh
59a7dabf3b Fix C# warnings during a clean build (#15857)
#### Fix warnings due to formatting during a clean build

Seems like the compiler cares about them more than our formatter.
Possibly introduced in https://github.com/microsoft/terminal/pull/15062

## Validation Steps Performed
- Tests passed
2023-08-21 12:41:43 -05:00
Dustin L. Howett
d28b6bf1f2 Move the Azure Cloud Shell icons from terminal-internals (#15841)
I put them in that package like 40 years ago to get them into the build
system faster. They actually belong here.

I made them based on SVGs the Azure Cloud Shell team shared with us.
2023-08-17 16:18:16 -05:00
Leonard Hecker
a7a44901c2 AtlasEngine: Fix ligature splitting for JetBrains Mono (#15810)
Some fonts implement ligatures by replacing a string like "&&" with
a whitespace padding glyph, followed by the actual "&&" glyph which
has a 1 column advance width. In that case the algorithm in
`_drawTextOverlapSplit` will get confused because it strictly scans
the input from left to right, searching for color changes.
The initial color is the glyph's color and so it breaks for such fonts
because then the first split will retain the last column's color.

## Validation Steps Performed
* Use JetBrains Mono
* Print ``"`e[91m`&`e[96m&`e[m"``
* Red and blue `&` appear 

---------

Co-authored-by: Tushar Singh <tusharvickey1999@gmail.com>
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
2023-08-15 19:50:47 +00:00
Leonard Hecker
3701d0ee95 Avoid async infinite loop on tab close (#15335)
When a tab gets closed, `_RemoveTab` will call `TabBase::Shutdown()`,
which then re-raises the `Closed` event, which will end up calling
`_RemoveTab` again, etc. The only reason this didn't crash WT so far
is because `_RemoveOnCloseRoutine` contains a `resume_foreground`,
which would resolve the recursion and turn it into CPU usage.
It would spin as long as WinUI hasn't discard the tab object,
which takes an unpredictable amount of time.

Raising the `Closed` event from `Shutdown()` is unnecessary, because
the handlers of the event end up calling `_RemoveTab` anyways.
Technically the entire `Closed` event can be removed now, but I left it
in anyways because resolving the architectural "knot" around the way
tab closing after the last pane closes is implemented requires much
more significant changes.

This commit additionally removes the `_createCloseLock` mutex in `Pane`
as it was very likely not working as intended anyways. Only some methods
were protected by it and it doesn't avoid any STA/MTA/NA issues either.

## Validation Steps Performed
* Closing tabs and panes always ends up calling `Shutdown()` 
2023-08-15 19:12:19 +00:00
Mike Griese
127df073fa Add support for "Tasks" in the Suggestions UI (#15664)
_targets #15027_

Adds a new suggestion source, `tasks`, that allows a user to open the
Suggestions UI with `sendInput` commands saved in their settings.
`source` becomes a flag setting, so it can be combined like so:

```json
        {
            "keys": "ctrl+shift+h", "command": { "action": "suggestions", "source": "commandHistory", "useCommandline":true },
        },
        {
            "keys": "ctrl+shift+y", "command": { "action": "suggestions", "source": "tasks", "useCommandline":false },
        },
        {
            "keys": "ctrl+shift+b", "command": { "action": "suggestions", "source": ["all"], "useCommandline":true },
        },
```

If a nested command has `sendInput` commands underneath it, this will
build a tree of commands that only include `sendInput`s as leaves (but
leave the rest of the nesting structure intact).


## References and Relevant Issues

Closes #1595

See also #13445 
As spec'd in #14864 

## Validation Steps Performed

Tested manually
2023-08-15 19:01:34 +00:00
Mike Griese
3afe7a8d11 Add a useCommandline property to the suggestions action (#15027)
_targets #14943_

When this is true, this will re-use the existing commandline to
pre-filter the results. This is especially helpful for completing a
suggestion based on the text that's already been typed.

Like with command history, this requires that shell integration is
enabled before it will work.## Summary of the Pull Request

## References and Relevant Issues

See also #13445 
As spec'd in #14864 

## Validation Steps Performed

Tested manually
2023-08-15 15:39:36 +00:00
Mike Griese
8f4c63e81b Plumb test failures through to github (#15831)
This does two bits:
1. correctly marks our tests as failed in xUnit, so that AzDo will pick
up that the tests have failed.
2. Actually intentionally mark skipped tests as skipped in xUnit. We
were doing this accidentally before.
3. Add a CI step to log test failures in a way that they can show up on
GitHub


Probably regressed around #6992 and #4490.

### details

#### Part the first
We were relying on the MUX build scripts to convert our WTT test logs to
xUnit format, which AzDo then ingests. That script we used relied on
some WinUI-specific logic around retrying tests. They have some logic to
auto-retry failed tests. They then mark a test as "skipped" if it passed
less than some threshold of times. Since we were never setting that
variable, we would mark a test as "skipped" if it had _0_ passes. So,
all failures showed up on AzDo as "skipped".

Why didn't we notice this? Well, the `Run-Tests.ps1` script will still
return `1` if _any_ tests failed. So the test job would fail if there
was a failure, AzDo just wouldn't know which test it was.

#### part the second
Updates `ConvertWttLogToXUnitLog` in `HelixTestHelpers.cs` to understand
that a test can be skipped, in addition to pass/fail. Removes all the
logic for dealing with retries, cause we didn't need that.

#### part the third
TAEF doesn't emit error messages in a way that AzDo can immediately pick
up on which tests failed. This means that Github gives us this useless
error message:

![image](https://github.com/microsoft/terminal/assets/18356694/3be6de00-22e1-421c-93d4-176bd2be4cab)
That's the only "error" that AzDo knows about. 

This PR changes that by adding a build step to manually parse the xUnit
results, and log the names of any tests that failed. By logging them
with a prefix of `##vso[task.logissue type=error]`, then AzDo will
surface that text as an error message. GitHub can then grab that text
and surface it too.

### Addenda: Why aren't we using the VsTest module
as noted in
https://github.com/microsoft/terminal/pull/4490#issuecomment-583104982,
the vstest module is literally 6x slower than just running TAEF
directly.
2023-08-15 09:50:15 -05:00
Mike Griese
e5a430ff68 Add support for opening the Suggestions UI with recent commands (#14943)
This adds support for a new action, `showSuggestions`, as described in
#14864. This adds just one `source` currently, `recentCommands`. This
requires shell integration to be enabled in the shell to work properly.
When it is enabled, activating that action will invoke the suggestions
UI as a palette, populated with `sendInput` actions for each of the
user's recent commands.

* These don't persist across reboots. 
* These are per-control.

There's mild plans to remedy that in a follow-up, though that needs a
bit more design consideration.

Closes #14779
2023-08-15 08:48:09 -05:00
Mike Griese
b556594793 Add an experimental setting for moving the cursor with the mouse (#15758)
## Summary of the Pull Request

This adds a new experimental per-setting to the terminal. 

```ts
"experimental.repositionCursorWithMouse": bool
```

When:
* the setting is on 
* AND you turn on shell integration (at least `133;B`)
* AND you click is somewhere _after_ the "active command" mark

we'll send a number of simulated keystrokes to the terminal based off
the number of cells between the place clicked and where the current
mouse cursor is.


## PR Checklist
- [ ] Related to #8573. I'm not marking as _closed_, because we should
probably polish this before we close that out. This is more a place to
start.

## Detailed Description of the Pull Request / Additional comments

There was a LOT of discussion in #8573. This is kinda a best effort
feature - it won't always work, but it should improve the experience
_most of the time_. We all kinda agreed that as much as the shell
probably should be responsible for doing this, there's myriad reasons
that won't work in practicality:
* That would also disable selection made by the terminal. That's a hard
sell.
* We'd need to invent some new mouse mode to support
click-to-reposition-but-drags-to-select-I-don't-want
* We'd then need shells to adopt that functionality.

And eventually settled that this was the least horrifying comprimise.

This has _e d g e  c a s e s_: 
* Does it work for wrapped lines? Well, kinda okay actually.
* Does it work for `vim`/`emacs`? Nope. 
* Does it work for emoji/wide glyphs? I wouldn't expect it to! I mean,
emoji input is messed up anyways, right?
* Other characters like `ESC` (which are rendered by the shell as two
cells "^[")? Nope.
* Does it do selections? Nope.
* Clicking across lines with continuation prompts? Nope.
* Tabs? Nope.
* Wraps within tmux/screen? Nope.


https://github.com/xtermjs/xterm.js/blob/master/src/browser/input/MoveToCell.ts
has probably a more complete implementation of how we'd want to generate
the keypresses and such.
2023-08-14 07:37:13 -05:00
Mike Griese
a0c88bb511 Add Suggestions UI & experimental shell completions support (#14938)
There's two parts to this PR that should be considered _separately_.
1. The Suggestions UI, a new graphical menu for displaying suggestions /
completions to the user in the context of the terminal the user is
working in.
2. The VsCode shell completions protocol. This enables the shell to
invoke this UI via a VT sequence.

These are being introduced at the same time, because they both require
one another. However, I need to absolutely emphasize:

### THE FORMAT OF THE COMPLETION PROTOCOL IS EXPERIMENTAL AND SUBJECT TO
CHANGE

This is what we've prototyped with VsCode, but we're still working on
how we want to conclusively define that protocol. However, we can also
refine the Suggestions UI independently of how the protocol is actually
implemented.

This will let us rev the Suggestions UI to support other things like
tooltips, recent commands, tasks, INDEPENDENTLY of us rev'ing the
completion protocol.

So yes, they're both here, but let's not nitpick that protocol for now. 

### Checklist

* Doesn't actually close anything
* Heavily related to #3121, but I'm not gonna say that's closed till we
settle on the protocol
* See also:
  * #1595
  * #14779
  * https://github.com/microsoft/vscode/pull/171648

### Detailed Description

#### Suggestions UI

The Suggestions UI is spec'ed over in #14864, so go read that. It's
basically a transient Command Palette, that floats by the user's cursor.
It's heavily forked from the Command Palette code, with all the business
about switching modes removed. The major bit of new code is
`SuggestionsControl::Anchor`. It also supports two "modes":
* A "palette", which is like the command palette - a list with a text
box
* A "menu", which is more like the intellisense flyout. No text box.
This is the mode that the shell completions use

#### Shell Completions Protocol

I literally cannot say this enough times - this protocol is experimental
and subject to change. Build on it at your own peril. It's disabled in
Release builds (but available in preview behind
`globals.experimental.enableShellCompletionMenu`), so that when it
ships, no one can take a dependency on it accidentally.

Right now we're just taking a blob of JSON, passing that up to the App
layer, who asks `Command` to parse it and build a list of `sendInput`
actions to populate the menu with. It's not a particularly elegant
solution, but it's good enough to prototype with.

#### How do I test this?

I've been testing this in two parts. You'll need a snippet in your
powershell profile, and a keybinding in the Terminal settings to trigger
it. The work together by binding <kbd>Ctrl+space</kbd> to _essentially_
send <kbd>F12</kbd><kbd>b</kbd>. Wacky, but it works.

```json
{ "command": { "action": "sendInput","input": "\u001b[24~b" }, "keys": "ctrl+space" },
```

```ps1
function Send-Completions2 {
  $commandLine = ""
  $cursorIndex = 0
  # TODO: Since fuzzy matching exists, should completions be provided only for character after the
  #       last space and then filter on the client side? That would let you trigger ctrl+space
  #       anywhere on a word and have full completions available
  [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$cursorIndex)
  $completionPrefix = $commandLine

  # Get completions
  $result = "`e]633;Completions"
  if ($completionPrefix.Length -gt 0) {
    # Get and send completions
    $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex
    if ($null -ne $completions.CompletionMatches) {
      $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);"
      $result += $completions.CompletionMatches | ConvertTo-Json -Compress
    }
  }
  $result += "`a"

  Write-Host -NoNewLine $result
}

function Set-MappedKeyHandlers {
  # VS Code send completions request (may override Ctrl+Spacebar)
  Set-PSReadLineKeyHandler -Chord 'F12,b' -ScriptBlock {
    Send-Completions2
  }
}

# Register key handlers if PSReadLine is available
if (Get-Module -Name PSReadLine) {
  Set-MappedKeyHandlers
}

```


### TODO

* [x] `(prompt | format-hex).`<kbd>Ctrl+space</kbd> -> This always
throws an exception. Seems like the payload is always clipped to

```{"CompletionText":"Ascii","ListItemText":"Ascii","ResultType":5,"ToolTip":"string
Ascii { get```
  and that ain't JSON. Investigate on the pwsh side?
2023-08-14 05:46:42 -05:00
Dustin L. Howett
69eff7e9fd Rewrite the entire Azure DevOps build system (#15808)
This pull request rewrites the entire Azure DevOps build system.

The guiding principles behind this rewrite are:

- No pipeline definitions should contain steps (or tasks) directly.
- All jobs should be in template files.
- Any set of steps that is reused across multiple jobs must be in
  template files.
- All artifact names can be customized (via a property called
  `artifactStem` on all templates that produce or consume artifacts).
- No compilation happens outside of the "Build" phase, to consolidate
  the production and indexing of PDBs.
- **Building the project produces a `bin` directory.** That `bin`
  directory is therefore the primary currency of the build. Jobs will
  either produce or consume `bin` if they want to do anything with the
  build outputs.
- All step and job templates are named with `step` or `job` _first_,
  which disambiguates them in the templates directory.
- Most jobs can be run on different `pool`s, so that we can put
  expensive jobs on expensive build agents and cheap jobs on cheap
  build agents. Some jobs handle pool selection on their own, however.

Our original build pipelines used the `VSBuild` task _all over the
place._ This resulted in Terminal being built in myriad ways, different
for every pipeline. There was an attempt at standardization early on,
where `ci.yml` consumed jobs and steps templates... but when
`release.yml` was added, all of that went out the window.

The new pipelines are consistent and focus on a small, well-defined set
of jobs:

- `job-build-project`
    - This is the big one!
    - Takes a list of build configurations and platforms.
    - Produces an artifact named `build-PLATFORM-CONFIG` for the entire
      matrix of possibilities.
    - Optionally signs the output and produces a bill of materials.
    - Admittedly has a lot going on.
- `job-build-package-wpf`
    - Takes a list of build configurations and platforms.
    - Consumes the `build-` artifact for every config/platform
      possibility, plus one for "Any CPU" (hardcoded; this is where the
      .NET code builds)
    - Produces one `wpf-nupkg-CONFIG` for each configuration, merging
      all platforms.
    - Optionally signs the output and produces a bill of materials.
- `job-merge-msix-into-bundle`
    - Takes a list of build configurations and platforms.
    - Consumes the `build-` artifact for every config/platform
    - Produces one `appxbundle-CONFIG` for each configuration, merging
      all platforms for that config into one `msixbundle`.
    - Optionally signs the output and produces a bill of materials.
- `job-package-conpty`
    - Takes a list of build configurations and platforms.
    - Consumes the `build-` artifact for every config/platform
    - Produces one `conpty-nupkg-CONFIG` for each configuration, merging
      all platforms.
    - Optionally signs the output and produces a bill of materials.
- `job-test-project`
    - Takes **one** build config and **one** platform.
    - Consumes `build-PLATFORM-CONFIG`
    - Selects its own pools (hardcoded) because it knows about
      architectures and must choose the right agent arch.
    - Runs tests (directly on the build agent).
- `job-run-pgo-tests`
    - Just like the above, but runs tests where `IsPgo` is `true`
    - Collects all of the PGO counts and publishes a `pgc-intermediates`
      artifact for that platform and configuration.
- `job-pgo-merge-pgd`
    - Takes **one** build config and multiple platforms.
    - Consumes `build-$platform-CONFIG` for each platform.
    - Consumes `pgc-intermediates-$platform-CONFIG` for each platform.
    - Merges the `pgc` files into `pgd` files
    - Produces a new `pgd-` artifact.
- `job-pgo-build-nuget-and-publish`
    - Consumes the `pgd-` artifact from above.
    - Packs it into a `nupkg` and publishes it.
- `job-submit-windows-vpack`
    - Only expected to run against `Release`.
    - Consumes the `appxbundle-CONFIG` artifact.
    - Publishes it to a vpack for Windows to consume.
- `job-check-code-format`
    - Does not use artifacts. Runs `clang-format`.
- `job-index-github-codenav`
    - Does not use artifacts.

Fuzz submission is broken due to changes in the `onefuzz` client.

I have removed the compliance and security build because it is no longer
supported.

Finally, this pull request has some additional benefits:

- I've expanded the PGO build phase to cover ARM64!
- We can remove everything Helix-related except the WTT parser
    - We no longer depend on Helix submission or Helix pools
- The WPF control's inner DLLs are now codesigned (#15404)
- Symbols for the WPF control, both .NET and C++, are published
  alongside all other symbols.
- The files we submit to ESRP for signing are batched up into a single
  step[^1]

Closes #11874
Closes #11974
Closes #15404

[^1]: This will have to change if we want to sign the individual
per-architecture `.appx` files before bundling so that they can be
directly installed.
2023-08-11 14:06:30 -05:00
Mike Griese
d943fa41f6 Add walkthroughs to CONTRIBUTING.md (#15799)
Change the "good first issues" text to talk about walkthroughs instead.
2023-08-11 14:57:40 +00:00
Leonard Hecker
5b44476048 Replace IInputEvent with INPUT_RECORD (#15673)
`IInputEvent` makes adding Unicode support to `InputBuffer` more
difficult than necessary as the abstract class makes downcasting
as well as copying quite verbose. I found that using `INPUT_RECORD`s
directly leads to a significantly simplified implementation.

In addition, this commit fixes at least one bug: The previous approach
to detect the null key via `DoActiveModifierKeysMatch` didn't work.
As it compared the modifier keys as a bitset with `==` it failed to
match whenever the numpad key was set, which it usually is.

## Validation Steps Performed
* Unit and feature tests are 
2023-08-11 14:06:08 +00:00
Leonard Hecker
e9c8391fd5 Fix compilation with Visual Studio 17.8 (#15819)
This broke with https://github.com/microsoft/STL/pull/3721
It's a minor issue and a minor fix. :)
2023-08-11 15:17:18 +02:00
Mike Griese
256d46ad6b Fix the TilWinRT tests (#15820)
It's unknown how this ever worked, or why it stopped working recently.

We removed our desire to directly compare property against T at some point.
2023-08-10 22:13:36 +00:00
LitoMore
6a29ca2ada README: Fix GitHub built-in note highlight styles (#15807)
## Summary of the Pull Request

I updated the note prefix for blockquotes with GitHub latest built-in
styles.

## References and Relevant Issues

- https://github.com/orgs/community/discussions/16925

## Detailed Description of the Pull Request / Additional comments

This PR fixed the broken style due to their format change.

## Related former Pull Request

- https://github.com/microsoft/terminal/pull/13615
2023-08-08 11:15:16 -05:00
Mike Griese
1ed57cc5c9 Add a note about how to run the UIA tests locally (#15806)
Carlos and I spent an hour rediscovering how to make this work. I
figured it'd be best to leave notes behind for future archeologists.
2023-08-08 11:14:47 -05:00
Tushar Singh
9b70a40bf9 ConHost: Ignore WM_[SYS]KEYDOWN/WM_[SYS]KEYUP events with an invalid virtual keycode and a scan code of 0 (#15753)
## Summary
Applications like PowerToys, with their keyboard remapping features
frequently (i.e whenever a remapped shortcut is triggerred) send
`KeyEvent` with out-of-range virtual keycode values (E.g. 0xFF). This is
fixed for WT in #7145, we just needed it in our good ol' `conhost`.

After this PR, Key events with an invalid virtual keycode and
scancode==0 are ignored, and are not added to the `InputBuffer`. Incase,
only virtual keycode is valid but not scancode, we will try to infer the
correct scancode using the virtual keycode mapping.

## References and Relevant Issues
#7145 
#7064 

## Validation Steps Performed

- Triggered a remapped shortcut and verified that `showkey -a` doesn't
output `^@` unexpectedly.
- Key events with an Invalid virtual Keycode and Scancode == 0 are
ignored.
- This PR doesn't include any changes for `WM_[SYS][DEAD]CHAR` messages,
they are left unchanged.
2023-08-08 10:58:34 -05:00
Leonard Hecker
c6e5f79115 Modernize CommandHistory and switch to int32 (#15782)
This commit slightly modernizes `CommandHistory` by leaning more heavily
on the STL container functionalities. For one, it uses for-range
iterations to loop through `_commands` instead of using `GetNth`
on every iteration. Another major improvement however is that
the code previously copied entire `CommandHistory` instances out of
the linked list `s_historyLists`, then removed the slot and copied
(not moved!) that instance into the front again. Now it uses the
`splice` function from `std::list` to do it in `O(1)` and virtually
cost-free.

Another major improvement (and the one I'm personally interested in)
is the switch from `SHORT` to `int32_t`. This will greatly simplify
the implementation of the future `COOKED_READ_DATA` class, as the
larger integer type will remove worries about over/underflow.
For instance, we can then just blindly increment/decrement the history
position and then only later clamp it to the expected range.

## Validation Steps Performed
* Existing history tests 
* History cycling with F8 
* Navigating history with F7 
2023-08-01 22:46:40 +00:00
Leonard Hecker
2d7066f5c6 Remove IsValidStringBuffer helper (#15781)
This change is a fairly subjective one. It was done because
`IsValidStringBuffer` will very soon be the only function left
in `cmdline.cpp`. Removing it allows removing `cmdline.cpp`.
While the code that replaces it is somewhat tricky, it's also much
more straightforward, as the `IsValidStringBuffer` function didn't
just check if the string buffer is valid - it also retrieved the
pointers to each of the strings contained in the buffer.

## Validation Steps Performed
Exhaustively covered by conhost feature tests 
2023-08-01 19:27:08 +00:00
Leonard Hecker
07566fac4c Merge ReadConsoleA/W API routines (#15780)
This is a minor cleanup to deduplicate the two ReadConsole methods
and will help with making changes to how `COOKED_READ_DATA` is called.
It additionally changes the initial data payload from a `string_view`
to a `wstring_view` as it is guaranteed to be `wchar_t`.
This matches the current `COOKED_READ_DATA` implementation which
blindly assumes that the initial data consists of `wchar_t`.

Closes #5618
2023-08-01 16:13:51 +00:00
Leonard Hecker
a4340af1e7 Add text based cursor movement helpers (#15779)
`COOKED_READ_DATA` is a little special and requires cursor navigation
based on the raw (buffered) text contents instead of what's in the
text buffer. This requires the introduction of new helper functions
to implement such cursor navigation. They're made part of `TextBuffer`
as these helpers will get support graphemes in the future.
It also helps keeping it close to `TextBuffer` as the cursor
navigation should optimally behave identical between the two.

Part of #8000.
2023-08-01 00:00:57 +00:00
Brandon Dong
57b9549ff8 Fix matches of multiple schemas on "colorScheme" (#15748)
Adds proper `type` for `SchemePair` definition to avoid warnings about matches of multiple schemas.

Same fix as https://github.com/microsoft/terminal/pull/4045

## Validation Steps Performed
- Pointed $schema to local file instead of https://aka.ms/terminal-profiles-schema
- Confirmed warning goes away when using a string
- Confirmed using the light/dark object format still passes validation
- Confirmed values like `"colorScheme": 3` no longer incorrectly pass validation whereas they would before
2023-07-26 17:13:49 -07:00
Carlos Zamora
1f9426b051 Fix Default Terminal and Color Scheme ComboBoxes cropping at 200% Text Size (#15762)
When the OS' "text size" setting gets set to 200% and the display
resolution is reduced quite a bit, we get some cropped text in the SUI's
Default Terminal ComboBox. Turns out, we have a height set on the items.
I went ahead and removed that so we don't crop the text. Everything
looks good still!

A similar issue occurs in the Profile > Appearance > Color Scheme
ComboBox. I went ahead and fixed that too by removing the height
restriction.

Other minor changes:
- fixed the comments
- changed "author and version" row to "auto" instead of "*" (star sizing
is great for proportional sizing, so we're not really taking advantage
of it)

Closes #15149
2023-07-26 18:25:19 -05:00
Dustin L. Howett
cbe915c554 Add support for ARM64 testing, reintroduce it in CI (#15761)
This pull request introduces the arm64 testing agents and a few build
phases to use them.

In addition to running the ARM64 tests in CI, it makes the following
changes:

- The x64 tests now run on equivalent x64 testing agents
- We now run ARM64 builds (and tests!) on all pull requests
- I've deduplicated a lot of the build and test stages
- New queue-time parameters have been added to control various phases,
  for quick pipeline testing
- A bunch of conditions have been promoted to compile-time checks to
  control the existence of stages and steps more tightly
2023-07-26 16:22:18 -07:00
Carlos Zamora
d70794a246 Add UIA element grouping to SettingsContainer (#15756)
Adds an `AutomationProperty.Name` to the main grid in the `SettingContainer`. Doing so makes it so that the group of elements is considered a "group \<header\>".

Now, when navigating with a screen reader, when you enter the group of elements, the "group \<header\>" will be presented. Thus, if the user navigates to the "reset" button, it'll be prefaced with a "group \<header\>" announcement first. If the user navigates to it from the other direction (the setting control), this announcement isn't made, but the user already has an understanding of what group of settings they're in, which is standard practice.

Closes #15158
2023-07-25 13:42:47 -07:00
Dustin L. Howett
1a40ff3746 Switch away from the WinDev agent pools (#15755)
Using our own pools like this gives us a lot of freedom in the tooling
that's installed, the OS versions it targets, and when we take on Visual
Studio updates.

As part of this effort, I've also stood up a "small" agent pool. At the
time of this PR, that pool is using D2ads-v5 SKU VMs (2 vcore 8 GiB)
versus the "large" agent pool's D8as-v5 (8 vcore 32 GiB). Smaller build
tasks have been moved over to the small pool. Compilation's the hard
part, so it gets to stay on the large pool.
2023-07-25 13:19:41 -07:00
519 changed files with 9776 additions and 14895 deletions

View File

@@ -95,6 +95,7 @@ slnt
Sos
ssh
stakeholders
sxn
timeline
timelines
timestamped
@@ -111,6 +112,8 @@ und
unregister
versioned
vsdevcmd
walkthrough
walkthroughs
We'd
wildcards
XBox

View File

@@ -52,6 +52,7 @@ futex
GETDESKWALLPAPER
GETHIGHCONTRAST
GETMOUSEHOVERTIME
GETTEXTLENGTH
Hashtable
HIGHCONTRASTON
HIGHCONTRASTW
@@ -186,6 +187,7 @@ snprintf
spsc
sregex
SRWLOC
srwlock
SRWLOCK
STDCPP
STDMETHOD

View File

@@ -21,6 +21,7 @@ BBBBCCCCC
BBGGRR
efg
EFG
efgh
EFGh
KLMNOQQQQQQQQQQ
QQQQQQQQQQABCDEFGHIJ

View File

@@ -7,7 +7,6 @@ ABCF
abgr
abi
ABORTIFHUNG
ACCESSTOKEN
acidev
ACIOSS
ACover
@@ -18,7 +17,6 @@ ADDALIAS
ADDREF
ADDSTRING
ADDTOOL
AEnd
AFew
AFill
AFX
@@ -117,10 +115,8 @@ binplace
binplaced
bitcoin
bitcrazed
bitflag
bitmask
BITOPERATION
bitsets
BKCOLOR
BKGND
Bksp
@@ -149,12 +145,12 @@ bufferout
buffersize
buflen
buildtransitive
BUILDURI
burriter
BValue
bytebuffer
cac
cacafire
CALLCONV
capslock
CARETBLINKINGENABLED
CARRIAGERETURN
@@ -198,7 +194,6 @@ CHT
Cic
cielab
Cielab
Clcompile
CLE
cleartype
CLICKACTIVE
@@ -229,7 +224,6 @@ codepage
codepath
codepoints
coinit
COLLECTIONURI
colorizing
COLORMATRIX
COLORREFs
@@ -307,7 +301,6 @@ coordnew
COPYCOLOR
CORESYSTEM
cotaskmem
countof
CPG
cpinfo
CPINFOEX
@@ -381,7 +374,6 @@ dai
DATABLOCK
DBatch
dbcs
DBCSCHAR
DBCSFONT
dbg
DBGALL
@@ -503,7 +495,6 @@ devicecode
Dext
DFactory
DFF
dhandler
dialogbox
directio
DIRECTX
@@ -521,7 +512,6 @@ dllmain
DLLVERSIONINFO
DLOAD
DLOOK
dmp
DONTCARE
doskey
dotnet
@@ -599,7 +589,6 @@ eplace
EPres
EQU
ERASEBKGND
etcoreapp
ETW
EUDC
EVENTID
@@ -641,7 +630,6 @@ FGs
FILEDESCRIPTION
FILESUBTYPE
FILESYSPATH
fileurl
FILEW
FILLATTR
FILLCONSOLEOUTPUT
@@ -690,7 +678,7 @@ FSINFOCLASS
fte
Ftm
Fullscreens
fullwidth
Fullwidth
FUNCTIONCALL
fuzzer
fuzzmain
@@ -823,7 +811,6 @@ HIWORD
HKCU
hkey
hkl
HKLM
hlocal
hlsl
HMB
@@ -831,7 +818,6 @@ HMK
hmod
hmodule
hmon
homeglyphs
homoglyph
HORZ
hostable
@@ -919,6 +905,7 @@ INSERTMODE
INTERACTIVITYBASE
INTERCEPTCOPYPASTE
INTERNALNAME
Interner
intsafe
INVALIDARG
INVALIDATERECT
@@ -935,12 +922,10 @@ itermcolors
ITerminal
itf
Ith
itoa
IUI
IUnknown
ivalid
IWIC
IXMP
IXP
jconcpp
JOBOBJECT
@@ -964,7 +949,6 @@ kernelbasestaging
KEYBDINPUT
keychord
keydown
keyevent
KEYFIRST
KEYLAST
Keymapping
@@ -1011,7 +995,6 @@ LINEWRAP
LINKERRCAP
LINKERROR
linputfile
listproperties
listptr
listptrsize
lld
@@ -1117,6 +1100,7 @@ MDs
MEASUREITEM
megamix
memallocator
meme
MENUCHAR
MENUCONTROL
MENUDROPALIGNMENT
@@ -1130,7 +1114,6 @@ MIIM
milli
mincore
mindbogglingly
minimizeall
minkernel
MINMAXINFO
minwin
@@ -1317,7 +1300,7 @@ onecoreuuid
ONECOREWINDOWS
onehalf
oneseq
ONLCR
OOM
openbash
opencode
opencon
@@ -1327,13 +1310,6 @@ openps
openvt
ORIGINALFILENAME
osc
OSCBG
OSCCT
OSCFG
OSCRCC
OSCSCB
OSCSCC
OSCWT
OSDEPENDSROOT
OSG
OSGENG
@@ -1465,8 +1441,8 @@ prc
prealigned
prect
prefast
preflighting
prefs
preinstalled
prepopulated
presorted
PREVENTPINNING
@@ -1479,7 +1455,6 @@ prioritization
processenv
processhost
PROCESSINFOCLASS
procs
PROPERTYID
PROPERTYKEY
PROPERTYVAL
@@ -1494,7 +1469,6 @@ propvariant
propvarutil
psa
PSECURITY
pseudocode
pseudoconsole
pseudoterminal
psh
@@ -1613,7 +1587,6 @@ rgrc
rgs
rgui
rgw
rgwch
RIGHTALIGN
RIGHTBUTTON
riid
@@ -1774,7 +1747,6 @@ SND
SOLIDBOX
Solutiondir
somefile
SOURCEBRANCH
sourced
spammy
SRCCODEPAGE
@@ -1809,7 +1781,6 @@ STDMETHODCALLTYPE
STDMETHODIMP
STGM
stl
stoutapot
Stri
Stringable
STRINGTABLE
@@ -1826,7 +1797,6 @@ SUBLANG
subresource
subsystemconsole
subsystemwindows
suiteless
swapchain
swapchainpanel
swappable
@@ -1865,13 +1835,11 @@ TBM
tchar
TCHFORMAT
TCI
tcome
tcommandline
tcommands
Tdd
TDelegated
TDP
TEAMPROJECT
tearoff
Teb
Techo
@@ -1883,22 +1851,16 @@ terminalrenderdata
TERMINALSCROLLING
terminfo
TEs
testbuildplatform
testcon
testd
testdlls
testenv
testlab
testlist
testmd
testmode
testname
testnameprefix
TESTNULL
testpass
testpasses
testtestabc
testtesttesttesttest
testtimeout
TEXCOORD
texel
@@ -1927,7 +1889,6 @@ TJson
TLambda
TLDP
TLEN
Tlgdata
TMAE
TMPF
TMult
@@ -1987,11 +1948,14 @@ UAC
uap
uapadmin
UAX
UBool
ucd
uch
UChars
udk
UDM
uer
UError
uget
uia
UIACCESS
@@ -2021,13 +1985,14 @@ unknwn
UNORM
unparseable
unregistering
untests
untextured
untimes
UPDATEDISPLAY
UPDOWN
UPKEY
UPSS
uregex
URegular
usebackq
USECALLBACK
USECOLOR
@@ -2049,6 +2014,9 @@ USESIZE
USESTDHANDLES
usp
USRDLL
utext
UText
UTEXT
utr
UVWX
UVWXY
@@ -2110,7 +2078,6 @@ vtseq
vtterm
vttest
VWX
waaay
waitable
WANSUNG
WANTARROWS
@@ -2132,7 +2099,6 @@ WDDMCONSOLECONTEXT
wdm
webpage
websites
websockets
wekyb
wex
wextest
@@ -2160,7 +2126,6 @@ windbg
WINDEF
windll
WINDOWALPHA
Windowbuffer
windowdpiapi
WINDOWEDGE
windowext
@@ -2230,7 +2195,6 @@ wprp
wprpi
wregex
writeback
writechar
WRITECONSOLE
WRITECONSOLEINPUT
WRITECONSOLEOUTPUT
@@ -2304,7 +2268,6 @@ xunit
xutr
XVIRTUALSCREEN
XWalk
xxyyzz
yact
YCast
YCENTER

View File

@@ -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 ["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!
The best place to start is the list of ["walkthroughs"](https://aka.ms/terminal-walkthroughs). This is a collection of issues where we've written a "walkthrough", little guides to help get started with a particular issue. These are usually good first issues, and are a great way to get familiar with the codebase. Additionally, 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 is another set of issues that might be easier for first-time contributors. 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 any 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.

View File

@@ -21,7 +21,8 @@ Related repositories include:
## Installing and running Windows Terminal
> **Note**: Windows Terminal requires Windows 10 2004 (build 19041) or later
> **Note**\
> Windows Terminal requires Windows 10 2004 (build 19041) or later
### Microsoft Store [Recommended]
@@ -52,9 +53,10 @@ fails for any reason, you can try the following command at a PowerShell prompt:
Add-AppxPackage Microsoft.WindowsTerminal_<versionNumber>.msixbundle
```
> **Note**: If you install Terminal manually:
> **Note**\
> If you install Terminal manually:
>
> * You may need to install the [VC++ v14 Desktop Framework Package](https://docs.microsoft.com/troubleshoot/cpp/c-runtime-packages-desktop-bridge#how-to-install-and-update-desktop-framework-packages).
> * You may need to install the [VC++ v14 Desktop Framework Package](https://docs.microsoft.com/troubleshoot/cpp/c-runtime-packages-desktop-bridge#how-to-install-and-update-desktop-framework-packages).
> This should only be necessary on older builds of Windows 10 and only if you get an error about missing framework packages.
> * Terminal will not auto-update when new builds are released so you will need
> to regularly install the latest Terminal release to receive all the latest
@@ -70,7 +72,8 @@ package:
winget install --id Microsoft.WindowsTerminal -e
```
> **Note** Due to a dependency issue, Terminal's current versions cannot be installed via the Windows Package Manager CLI. To install the stable release 1.17 or later, or the Preview release 1.18 or later, please use an alternative installation method.
> **Note**\
> Due to [a dependency issue](https://github.com/microsoft/terminal/issues/15663), Terminal's current versions cannot be installed via the Windows Package Manager CLI. To install the stable release 1.17 or later, or the Preview release 1.18 or later, please use an alternative installation method.
#### Via Chocolatey (unofficial)
@@ -237,7 +240,8 @@ Cause: You're launching the incorrect solution in Visual Studio.
Solution: Make sure you're building & deploying the `CascadiaPackage` project in
Visual Studio.
> **Note**: `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic
> **Note**\
> `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic
> Windows Console that hosts Windows' command-line infrastructure. OpenConsole
> is used by Windows Terminal to connect to and communicate with command-line
> applications (via

View File

@@ -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"
}
}
}
}

View File

@@ -20,9 +20,7 @@ Param(
$helixResultsContainerUri = $Env:HELIX_RESULTS_CONTAINER_URI
$helixResultsContainerRsas = $Env:HELIX_RESULTS_CONTAINER_RSAS
$rerunPassesRequiredToAvoidFailure = $env:rerunPassesRequiredToAvoidFailure
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)
$testResultParser.ConvertWttLogToXUnitLog($WttInputPath, $WttSingleRerunInputPath, $WttMultipleRerunInputPath, $XUnitOutputPath, $rerunPassesRequiredToAvoidFailure)
$testResultParser.ConvertWttLogToXUnitLog($WttInputPath, $WttSingleRerunInputPath, $WttMultipleRerunInputPath, $XUnitOutputPath)

View File

@@ -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

View File

@@ -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

View File

@@ -20,32 +20,13 @@ namespace HelixTestHelpers
public string Name { get; set; }
public string SourceWttFile { get; set; }
public bool Passed { get; set; }
public bool Skipped { get; set; }
public bool CleanupPassed { get; set; }
public TimeSpan ExecutionTime { get; set; }
public string Details { get; set; }
public List<string> Screenshots { get; private set; }
public List<TestResult> RerunResults { get; private set; }
// Returns true if the test pass rate is sufficient to avoid being counted as a failure.
public bool PassedOrUnreliable(int requiredNumberOfPasses)
{
if(Passed)
{
return true;
}
else
{
if(RerunResults.Count == 1)
{
return RerunResults[0].Passed;
}
else
{
return RerunResults.Where(r => r.Passed).Count() >= requiredNumberOfPasses;
}
}
}
}
//
@@ -221,7 +202,9 @@ namespace HelixTestHelpers
testsExecuting--;
// If any inner test fails, we'll still fail the outer
currentResult.Passed &= element.Attribute("Result").Value == "Pass";
var value = element.Attribute("Result").Value;
currentResult.Passed = value == "Pass";
currentResult.Skipped = value == "Skipped";
// Only gather execution data if this is the outer test we ran initially
if (testsExecuting == 0)
@@ -498,7 +481,7 @@ namespace HelixTestHelpers
return subResultsJsonByMethod;
}
public void ConvertWttLogToXUnitLog(string wttInputPath, string wttSingleRerunInputPath, string wttMultipleRerunInputPath, string xunitOutputPath, int requiredPassRateThreshold)
public void ConvertWttLogToXUnitLog(string wttInputPath, string wttSingleRerunInputPath, string wttMultipleRerunInputPath, string xunitOutputPath)
{
TestPass testPass = TestPass.ParseTestWttFileWithReruns(wttInputPath, wttSingleRerunInputPath, wttMultipleRerunInputPath, cleanupFailuresAreRegressions: true, truncateTestNames: false);
var results = testPass.TestResults;
@@ -510,8 +493,8 @@ namespace HelixTestHelpers
// If the test failed sufficiently often enough for it to count as a failed test (determined by a property on the
// Azure DevOps job), we'll later mark it as failed during test results processing.
int failedCount = results.Where(r => !r.PassedOrUnreliable(requiredPassRateThreshold)).Count();
int skippedCount = results.Where(r => !r.Passed && r.PassedOrUnreliable(requiredPassRateThreshold)).Count();
int failedCount = results.Where(r => !r.Passed).Count();
int skippedCount = results.Where(r => (!r.Passed && r.Skipped)).Count();
var root = new XElement("assemblies");
@@ -557,12 +540,13 @@ namespace HelixTestHelpers
string resultString = string.Empty;
if (result.Passed)
if (result.Passed && !result.Skipped)
{
resultString = "Pass";
}
else if(result.PassedOrUnreliable(requiredPassRateThreshold))
else if (result.Skipped)
{
resultString = "Skip";
}
else
@@ -571,31 +555,25 @@ namespace HelixTestHelpers
}
test.SetAttributeValue("result", resultString);
if (!result.Passed)
{
// If a test failed, we'll have rerun it multiple times.
// We'll save the subresults to a JSON text file that we'll upload to the helix results container -
// this allows it to be as long as we want, whereas the reason field in Azure DevOps has a 4000 character limit.
string subResultsFileName = methodName + "_subresults.json";
string subResultsFilePath = Path.Combine(Path.GetDirectoryName(wttInputPath), subResultsFileName);
if (result.PassedOrUnreliable(requiredPassRateThreshold))
if (result.Skipped)
{
var reason = new XElement("reason");
reason.Add(new XCData(GetUploadedFileUrl(subResultsFileName, helixResultsContainerUri, helixResultsContainerRsas)));
reason.Add(new XCData("Test skipped"));
test.Add(reason);
}
else
{
else {
var failure = new XElement("failure");
var message = new XElement("message");
message.Add(new XCData(GetUploadedFileUrl(subResultsFileName, helixResultsContainerUri, helixResultsContainerRsas)));
message.Add(new XCData("Test failed"));
failure.Add(message);
test.Add(failure);
}
}
test.SetAttributeValue("result", resultString);
collection.Add(test);
}

View File

@@ -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
}

View 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)

View File

@@ -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
}

View File

@@ -0,0 +1,38 @@
Param(
[Parameter(Mandatory = $true)]
[string]$XUnitOutputPath
)
# This script is used to parse the XUnit output from the test runs and print out
# the tests that failed.
#
# Why you might ask? Well, it sure seems like Azure DevOps doesn't like the fact
# that we just call our tests in a powershell script. It can't seemingly find
# the actual errors in the TAEF logs. That means when you just go to the
# "Checks" page on GitHub, the Azure DevOps integration doesn't have anything
# meaningful to say other than "PowerShell exited with code '1'". If we however,
# just manually emit the test names formatted with "#[error]" in front of them,
# well, then the integration will all work like magic.
# Load the test results as a XML object
$testResults = [xml](Get-Content -Path $XUnitOutputPath)
# Our XML looks like:
# <assemblies>
# <assembly name="MUXControls.Test.dll" test-framework="TAEF" run-date="2023-08-14" run-time="11:38:01" total="524" passed="520" failed="4" skipped="1" time="8943" errors="0">
# <collection total="524" passed="520" failed="4" skipped="1" name="Test collection" time="8943">
# <test name="ControlCoreTests::TestSimpleClickSelection" type="ControlCoreTests" method="TestSimpleClickSelection" time="0.016" result="Fail">
# Iterate over all the assemblies and print all the tests that failed
foreach ($assembly in $testResults.assemblies.assembly) {
foreach ($collection in $assembly.collection) {
foreach ($test in $collection.test) {
if ($test.result -eq "Fail") {
# This particular format is taken from the Azure DevOps documentation:
# https://github.com/microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md
# This will treat this line as an error message
Write-Output "##vso[task.logissue type=error]$($test.name) Failed"
}
}
}
}

View File

@@ -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;]"
}

View File

@@ -1,62 +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"
# Extract the unpackaged distribution of Windows Terminal to the payload directory,
# where it will create a subdirectory named terminal-0.0.1.0
# This is referenced in TerminalApp.cs later as part of the test harness.
& tar -x -v -f "$repoDirectory\Artifacts\$ArtifactName\unpackaged\WindowsTerminalDev_0.0.1.0_x64.zip" -C "$payloadDir"
Copy-Item "res\fonts\*.ttf" "$payloadDir\terminal-0.0.1.0"

View File

@@ -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 ([System.Web.HttpUtility]::HtmlDecode($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
}
}
}
}
}

View File

@@ -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>

View File

@@ -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
}

View File

@@ -1,5 +0,0 @@
{
"msbuild-sdks": {
"Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.22525.5"
}
}

View File

@@ -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>

View File

@@ -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.

View File

@@ -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%

View File

@@ -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"
}
]
}
}
]
}

View File

@@ -1,72 +0,0 @@
{
"Version": "1.0.0",
"UseMinimatch": false,
"SignBatches": [
{
"MatchedPath": [
// Namespaced DLLs
"Microsoft.Terminal.*.dll",
"Microsoft.Terminal.*.winmd",
// ConPTY and DefTerm
"OpenConsole.exe",
"OpenConsoleProxy.dll",
// VCRT Forwarders
"*_app.dll",
// Legacy DLLs with old names
"TerminalApp.dll",
"TerminalApp.winmd",
"TerminalConnection.dll",
"TerminalThemeHelpers.dll",
"WindowsTerminalShellExt.dll",
// The rest
"TerminalAzBridge.exe",
"wt.exe",
"WindowsTerminal.exe",
"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"
}
]
}
}
]
}

View 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"
}
]
}
}
]

View 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"
}
]
}
}
]

View 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"
}
]
}
}
]

View 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"
}
]
}
}
]

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View 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!

View File

@@ -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

View File

@@ -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,12 @@ parameters:
values:
- Release
- Preview
- Canary
- 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,705 +33,53 @@ parameters:
- Instrument
- None
- name: buildConfigurations
displayName: "Build Configurations"
type: object
default:
- Release
- name: buildPlatforms
displayName: "Build Platforms"
type: object
default:
- x64
- x86
- arm64
- 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:
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe'
TerminalInternalPackageVersion: "0.0.8"
# 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
- 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 }}:
${{ config }}_${{ platform }}:
BuildConfiguration: ${{ config }}
BuildPlatform: ${{ platform }}
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) }}:
- 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)
- 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 *.msix and symbols to Artifacts
inputs:
Contents: >-
**/*.msix
**/*.appxsym
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
OverWrite: true
flattenFolders: true
- pwsh: |-
$Package = (Get-ChildItem "$(Build.ArtifactStagingDirectory)/appx" -Recurse -Filter "Cascadia*.msix" | Select -First 1)
$PackageFilename = $Package.FullName
Write-Host "##vso[task.setvariable variable=WindowsTerminalPackagePath]${PackageFilename}"
& "$(MakeAppxPath)" unpack /p $PackageFilename /d "$(Build.SourcesDirectory)\UnpackedTerminalPackage"
displayName: Unpack the new Terminal package for signing
- task: EsrpCodeSigning@1
displayName: Submit Terminal's binaries for signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: '$(Build.SourcesDirectory)\UnpackedTerminalPackage'
signType: batchSigning
batchSignPolicyFile: '$(Build.SourcesDirectory)\build\config\ESRPSigning_Terminal.json'
- pwsh: |-
$PackageFilename = "$(WindowsTerminalPackagePath)"
Remove-Item "$(Build.SourcesDirectory)\UnpackedTerminalPackage\CodeSignSummary*"
& "$(MakeAppxPath)" pack /h SHA256 /o /p $PackageFilename /d "$(Build.SourcesDirectory)\UnpackedTerminalPackage"
displayName: Re-pack the new Terminal package after signing
- pwsh: |-
$XamlAppxPath = (Get-Item "src\cascadia\CascadiaPackage\AppPackages\*\Dependencies\$(BuildPlatform)\Microsoft.UI.Xaml*.appx").FullName
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 -TerminalAppX $(WindowsTerminalPackagePath) -XamlAppX $XamlAppxPath -Destination "$(Build.ArtifactStagingDirectory)/appx"
displayName: Build Unpackaged Distribution
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'Generate SBOM manifest (application)'
inputs:
BuildDropPath: '$(System.ArtifactsDirectory)/appx'
- task: DropValidatorTask@0
displayName: 'Validate application SBOM manifest'
inputs:
BuildDropPath: '$(System.ArtifactsDirectory)/appx'
OutputPath: 'output.json'
ValidateSignature: true
Verbosity: 'Verbose'
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (Terminal app)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
ArtifactName: terminal-$(BuildPlatform)-$(BuildConfiguration)
- ${{ 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)
- ${{ 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)
- 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
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@1
displayName: Download Artifacts ${{ platform }}
inputs:
# Make sure to download the entire artifact, because it includes the SPDX SBOM
artifactName: terminal-${{ platform }}-Release
# Downloading to the source directory should ensure that the later SBOM generator can see the earlier SBOMs.
downloadPath: '$(Build.SourcesDirectory)/appx-artifacts'
# 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 "$(Build.SourcesDirectory)/appx-artifacts" -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(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: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'Generate SBOM manifest (bundle)'
inputs:
BuildDropPath: '$(System.ArtifactsDirectory)/bundle'
BuildComponentPath: '$(Build.SourcesDirectory)/appx-artifacts'
- task: DropValidatorTask@0
displayName: 'Validate bundle SBOM manifest'
inputs:
BuildDropPath: '$(System.ArtifactsDirectory)/bundle'
OutputPath: 'output.json'
ValidateSignature: true
Verbosity: 'Verbose'
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: appxbundle-signed'
inputs:
PathtoPublish: $(System.ArtifactsDirectory)\bundle
ArtifactName: appxbundle-signed
- ${{ 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@1
displayName: Download ${{ platform }} ConPTY binaries
inputs:
artifactName: conpty-dll-${{ platform }}-$(BuildConfiguration)
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@1
displayName: Download ${{ platform }} PublicTerminalCore
inputs:
artifactName: wpf-dll-${{ platform }}-$(BuildConfiguration)
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 terminal-PLATFORM-CONFIG-VERSION artifact for every platform/version combo
- ${{ each platform in parameters.buildPlatforms }}:
- task: DownloadBuildArtifacts@1
displayName: Download Symbols ${{ platform }}
inputs:
artifactName: terminal-${{ platform }}-Release
itemPattern: '**/*.appxsym'
# 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@1
displayName: Download Build Artifacts
inputs:
artifactName: appxbundle-signed
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_*.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
- task: PkgESVPack@12
displayName: 'Package ES - VPack'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
inputs:
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed\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 }}

View 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@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"
}
]
- ${{ 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

View File

@@ -0,0 +1,279 @@
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
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.
- 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 | 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@1
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
- ${{ 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

View 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'

View File

@@ -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'

View File

@@ -0,0 +1,143 @@
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
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"
.\build\scripts\Create-AppxBundle.ps1 -InputPath 'bin/' -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
displayName: Create msixbundle
- ${{ if eq(parameters.codeSign, true) }}:
- 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"
}
]
- ${{ 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'
- ${{ if eq(parameters.publishArtifacts, true) }}:
- publish: $(JobOutputDirectory)
artifact: $(JobOutputArtifactName)
displayName: Publish msixbundle

View 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@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"
}
]
- ${{ 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

View File

@@ -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'

View 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"

View File

@@ -0,0 +1,86 @@
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
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 }}
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 }}
# 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
ArtifactServices_Symbol_PAT: $(ADO_microsoftpublicsymbols_PAT)

View File

@@ -0,0 +1,82 @@
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)'
- 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()

View 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

View File

@@ -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,72 +11,80 @@ 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)"
- 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)"
- task: PowerShell@2
displayName: 'Convert Test Logs from WTL to xUnit format'
condition: always()
inputs:
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')))
- task: PowerShell@2
displayName: 'Manually log test failures'
condition: always()
inputs:
targetType: filePath
filePath: build\Helix\OutputTestErrorsForAzureDevops.ps1
arguments: -XUnitOutputPath 'onBuildMachineResults.xml'
- task: PublishTestResults@2
displayName: 'Upload converted test logs'
condition: ne(variables['PGOBuildMode'], 'Instrument')
condition: always()
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'
condition: always()
inputs:
Contents: |
**/*.wtl
@@ -87,4 +95,5 @@ jobs:
flattenFolders: true
- publish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test-logs'
artifact: TestLogs$(BuildPlatform)$(BuildConfiguration)
artifact: test-logs-$(BuildPlatform)-$(BuildConfiguration)${{ parameters.outputArtifactStem }}
condition: always()

View File

@@ -0,0 +1,196 @@
# 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:
# 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
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 }}
...

View 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 }})

View File

@@ -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 }}'

View File

@@ -0,0 +1,5 @@
steps:
- task: NuGetToolInstaller@1
displayName: Use NuGet 6.6.1
inputs:
versionSpec: 6.6.1

View File

@@ -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

View File

@@ -1,14 +1,12 @@
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`

View File

@@ -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

View File

@@ -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')))

View File

@@ -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
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

View File

@@ -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'

View File

@@ -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 }}

View File

@@ -1,137 +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 *.msix to Artifacts'
inputs:
Contents: |
**/*.msix
**/*.appxsym
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
OverWrite: true
flattenFolders: true
- pwsh: |-
$TerminalMsixPath = (Get-Item "$(Build.ArtifactStagingDirectory)\appx\Cascadia*.msix").FullName
$XamlAppxPath = (Get-Item "src\cascadia\CascadiaPackage\AppPackages\*\Dependencies\$(BuildPlatform)\Microsoft.UI.Xaml*.appx").FullName
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 -TerminalAppX $TerminalMsixPath -XamlAppX $XamlAppxPath -Destination "$(Build.ArtifactStagingDirectory)/unpackaged"
displayName: Build Unpackaged Distribution
- publish: $(Build.ArtifactStagingDirectory)/unpackaged
artifact: unpackaged-$(BuildPlatform)-$(BuildConfiguration)
displayName: Publish Artifact (unpackaged)
- 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)

View File

@@ -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'

View File

@@ -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 }}

View File

@@ -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 }}'

View File

@@ -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 }}

View File

@@ -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.11.amd64.client.open.reunion'
closedHelixTargetQueues: 'windows.11.amd64.client.reunion'
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)'

View File

@@ -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 }}

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_WTBrandingPreprocessorToken Condition="'$(WindowsTerminalBranding)'=='Canary'">WT_BRANDING_CANARY</_WTBrandingPreprocessorToken>
<_WTBrandingPreprocessorToken Condition="'$(WindowsTerminalBranding)'=='Preview'">WT_BRANDING_PREVIEW</_WTBrandingPreprocessorToken>
<_WTBrandingPreprocessorToken Condition="'$(WindowsTerminalBranding)'=='Release'">WT_BRANDING_RELEASE</_WTBrandingPreprocessorToken>
<_WTBrandingPreprocessorToken Condition="'$(_WTBrandingPreprocessorToken)'==''">WT_BRANDING_DEV</_WTBrandingPreprocessorToken>

View File

@@ -9,7 +9,8 @@ Param(
[Parameter(Mandatory=$false, Position=3)]
[string]$LogPath,
[Parameter(Mandatory=$false)]
[string]$Root = ".\bin\$Platform\$Configuration"
[string]$Root = ".\bin\$Platform\$Configuration",
[string[]]$AdditionalTaefArguments
)
# Find test DLLs based on the provided root, match pattern, and recursion
@@ -26,7 +27,7 @@ if ($LogPath) {
}
# Invoke the te.exe executable with arguments and test DLLs
& "$Root\te.exe" $args $testDlls.FullName
& "$Root\te.exe" $args $testDlls.FullName $AdditionalTaefArguments
# Check the exit code of the te.exe process and exit accordingly
if ($LASTEXITCODE -ne 0) {

View File

@@ -85,6 +85,32 @@
}
]
},
"BuiltinSuggestionSource": {
"enum": [
"commandHistory",
"tasks",
"all"
],
"type": "string"
},
"SuggestionSource": {
"default": "all",
"description": "Either a single suggestion source, or an array of sources to concatenate. Built-in sources include `commandHistory`, `directoryHistory`, and `tasks`. The special value `all` indicates all suggestion sources should be included",
"$comment": "`tasks` and `local` are sources that would be added by the Tasks feature, as a follow-up",
"oneOf": [
{
"type": [ "string", "null", "BuiltinSuggestionSource" ]
},
{
"type": "array",
"items": { "type": "BuiltinSuggestionSource" }
},
{
"type": "array",
"items": { "type": "string" }
}
]
},
"AppearanceConfig": {
"properties": {
"colorScheme": {
@@ -260,7 +286,8 @@
"description": "Name of the scheme to use when the app is using dark theme",
"type": "string"
}
}
},
"type": "object"
},
"FontConfig": {
"properties": {
@@ -397,6 +424,7 @@
"sendInput",
"setColorScheme",
"setTabColor",
"showSuggestions",
"splitPane",
"switchToTab",
"tabSearch",
@@ -1766,6 +1794,30 @@
}
]
},
"ShowSuggestionsAction": {
"description": "Arguments corresponding to a Open Suggestions Action",
"allOf": [
{
"$ref": "#/$defs/ShortcutAction"
},
{
"properties": {
"action": {
"type": "string",
"const": "showSuggestions"
},
"source": {
"$ref": "#/$defs/SuggestionSource",
"description": "Which suggestion sources to filter."
},
"useCommandline": {
"default": false,
"description": "When set to `true`, the current commandline the user has typed will pre-populate the filter of the Suggestions UI. This requires that the user has enabled shell integration in their shell's config. When set to false, the filter will start empty."
}
}
}
]
},
"ShowCloseButton": {
"enum": [
"always",
@@ -2036,6 +2088,9 @@
{
"$ref": "#/$defs/SearchWebAction"
},
{
"$ref": "#/$defs/ShowSuggestionsAction"
},
{
"type": "null"
}

View File

@@ -0,0 +1,407 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48"
height="48"
viewBox="0 0 48 48"
fill="none"
version="1.1"
id="svg284"
sodipodi:docname="Terminal_Can_Pill.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata288">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="922"
inkscape:window-height="816"
id="namedview286"
showgrid="false"
inkscape:zoom="8.8541667"
inkscape:cx="-17.429862"
inkscape:cy="31.710582"
inkscape:window-x="3142"
inkscape:window-y="60"
inkscape:window-maximized="0"
inkscape:current-layer="svg284" />
<g
id="g4007"
transform="matrix(0.9375,0,0,0.9375,0,1.5)">
<path
id="path150"
d="M 0,13 H 16 V 6 H 2 C 0.9,6 0,6.9 0,8 Z"
inkscape:connector-curvature="0"
style="fill:#cccccc" />
<path
id="path152"
d="M 32,6 H 16 v 7 h 16 z"
inkscape:connector-curvature="0"
style="fill:#999999" />
<path
id="path154"
d="M 48,13 H 32 V 6 h 14 c 1.1,0 2,0.9 2,2 z"
inkscape:connector-curvature="0"
style="fill:#666666" />
<path
id="path156"
d="M 46,42 H 2 C 0.9,42 0,41.1 0,40 V 12 h 48 v 28 c 0,1.1 -0.9,2 -2,2 z"
style="fill:url(#paint0_linear)"
inkscape:connector-curvature="0" />
<g
id="g171"
style="filter:url(#filter0_dd)">
<path
id="path158"
d="m 15.2,24.3 -8.80001,8.8 c -0.5,0.5 -0.5,1.2 0,1.6 l 1.8,1.8 C 8.69999,37 9.4,37 9.8,36.5 l 8.8,-8.8 c 0.5,-0.5 0.5,-1.2 0,-1.6 l -1.8,-1.8 c -0.4,-0.4 -1.2,-0.4 -1.6,0 z"
style="fill:url(#paint1_linear)"
inkscape:connector-curvature="0" />
<mask
height="13"
width="13"
y="24"
x="6"
maskUnits="userSpaceOnUse"
mask-type="alpha"
id="mask0">
<path
id="path160"
d="m 15.2,24.3 -8.80001,8.8 c -0.5,0.5 -0.5,1.2 0,1.6 l 1.8,1.8 C 8.69999,37 9.4,37 9.8,36.5 l 8.8,-8.8 c 0.5,-0.5 0.5,-1.2 0,-1.6 l -1.8,-1.8 c -0.4,-0.4 -1.2,-0.4 -1.6,0 z"
inkscape:connector-curvature="0"
style="fill:url(#paint2_linear)" />
</mask>
<g
id="g167"
mask="url(#mask0)">
<g
id="g165"
style="filter:url(#filter1_dd)">
<path
id="path163"
d="m 9.8,17.3 8.8,8.8 c 0.5,0.5 0.5,1.2 0,1.6 l -1.8,1.8 c -0.5,0.5 -1.2,0.5 -1.6,0 L 6.39999,20.7 c -0.5,-0.5 -0.5,-1.2 0,-1.6 l 1.8,-1.8 C 8.59999,16.9 9.4,16.9 9.8,17.3 Z"
style="fill:url(#paint3_linear)"
inkscape:connector-curvature="0" />
</g>
</g>
<path
id="path169"
d="m 9.8,17.3 8.8,8.8 c 0.5,0.5 0.5,1.2 0,1.6 l -1.8,1.8 c -0.5,0.5 -1.2,0.5 -1.6,0 L 6.39999,20.7 c -0.5,-0.5 -0.5,-1.2 0,-1.6 l 1.8,-1.8 C 8.59999,16.9 9.4,16.9 9.8,17.3 Z"
style="fill:url(#paint4_linear)"
inkscape:connector-curvature="0" />
</g>
<g
id="g175"
style="filter:url(#filter2_dd)">
<path
id="path173"
d="M 40,32 H 24 c -0.6,0 -1,0.4 -1,1 v 3 c 0,0.6 0.4,1 1,1 h 16 c 0.6,0 1,-0.4 1,-1 v -3 c 0,-0.6 -0.4,-1 -1,-1 z"
style="fill:url(#paint5_linear)"
inkscape:connector-curvature="0" />
</g>
</g>
<defs
id="defs282">
<filter
id="filter0_dd"
x="3.02499"
y="15"
width="18.95"
height="25.875"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood177" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
id="feColorMatrix179" />
<feOffset
dy="0.5"
id="feOffset181" />
<feGaussianBlur
stdDeviation="0.5"
id="feGaussianBlur183" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
id="feColorMatrix185" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow"
id="feBlend187" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
id="feColorMatrix189" />
<feOffset
dy="1"
id="feOffset191" />
<feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur193" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix195" />
<feBlend
mode="normal"
in2="effect1_dropShadow"
result="effect2_dropShadow"
id="feBlend197" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect2_dropShadow"
result="shape"
id="feBlend199" />
</filter>
<filter
id="filter1_dd"
x="3.02499"
y="15"
width="18.95"
height="18.875"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood202" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
id="feColorMatrix204" />
<feOffset
dy="0.5"
id="feOffset206" />
<feGaussianBlur
stdDeviation="0.5"
id="feGaussianBlur208" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
id="feColorMatrix210" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow"
id="feBlend212" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
id="feColorMatrix214" />
<feOffset
dy="1"
id="feOffset216" />
<feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur218" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix220" />
<feBlend
mode="normal"
in2="effect1_dropShadow"
result="effect2_dropShadow"
id="feBlend222" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect2_dropShadow"
result="shape"
id="feBlend224" />
</filter>
<filter
id="filter2_dd"
x="20"
y="30"
width="24"
height="11"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood227" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
id="feColorMatrix229" />
<feOffset
dy="0.5"
id="feOffset231" />
<feGaussianBlur
stdDeviation="0.5"
id="feGaussianBlur233" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
id="feColorMatrix235" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow"
id="feBlend237" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
id="feColorMatrix239" />
<feOffset
dy="1"
id="feOffset241" />
<feGaussianBlur
stdDeviation="1.5"
id="feGaussianBlur243" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"
id="feColorMatrix245" />
<feBlend
mode="normal"
in2="effect1_dropShadow"
result="effect2_dropShadow"
id="feBlend247" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect2_dropShadow"
result="shape"
id="feBlend249" />
</filter>
<linearGradient
id="paint0_linear"
x1="36.4462"
y1="47.8257"
x2="11.8217"
y2="5.1748"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#333333"
id="stop252" />
<stop
offset="1"
stop-color="#4D4D4D"
id="stop254" />
</linearGradient>
<linearGradient
id="paint1_linear"
x1="14.5276"
y1="33.9959"
x2="10.4841"
y2="26.9924"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#999999"
id="stop257" />
<stop
offset="1"
stop-color="#B3B3B3"
id="stop259" />
</linearGradient>
<linearGradient
id="paint2_linear"
x1="14.5276"
y1="33.9959"
x2="10.4841"
y2="26.9924"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#999999"
id="stop262" />
<stop
offset="1"
stop-color="#B3B3B3"
id="stop264" />
</linearGradient>
<linearGradient
id="paint3_linear"
x1="16.2747"
y1="30.0336"
x2="8.73699"
y2="16.9781"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#CCCCCC"
id="stop267" />
<stop
offset="1"
stop-color="#E6E6E6"
id="stop269" />
</linearGradient>
<linearGradient
id="paint4_linear"
x1="16.2747"
y1="30.0336"
x2="8.73699"
y2="16.9781"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#CCCCCC"
id="stop272" />
<stop
offset="1"
stop-color="#E6E6E6"
id="stop274" />
</linearGradient>
<linearGradient
id="paint5_linear"
x1="35.1496"
y1="39.9553"
x2="28.8504"
y2="29.0447"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#CCCCCC"
id="stop277" />
<stop
offset="1"
stop-color="#E6E6E6"
id="stop279" />
</linearGradient>
</defs>
<rect
x="19"
y="31.053001"
width="29"
height="11.947"
rx="1.8238994"
id="rect29"
style="fill:#fcc024;stroke-width:1;fill-opacity:1;stroke:none;stroke-miterlimit:4;stroke-dasharray:none" />
<path
d="M29.3999 39.7363C28.9253 39.9824 28.335 40.1055 27.6289 40.1055C26.7148 40.1055 25.9824 39.8169 25.4316 39.2397C24.8809 38.6626 24.6055 37.9053 24.6055 36.9678C24.6055 35.96 24.9146 35.1455 25.5327 34.5244C26.1538 33.9033 26.9375 33.5928 27.8838 33.5928C28.4932 33.5928 28.9985 33.6792 29.3999 33.8521V34.8892C28.9751 34.6372 28.5063 34.5112 27.9937 34.5112C27.311 34.5112 26.7573 34.7295 26.3325 35.166C25.9106 35.6025 25.6997 36.1855 25.6997 36.915C25.6997 37.6094 25.8975 38.1631 26.293 38.5762C26.6885 38.9863 27.2085 39.1914 27.853 39.1914C28.4478 39.1914 28.9634 39.0508 29.3999 38.7695V39.7363ZM35.772 40H34.625L34.0581 38.396H31.5796L31.0347 40H29.8921L32.252 33.6982H33.4297L35.772 40ZM33.7812 37.5435L32.9067 35.0298C32.8804 34.9478 32.8525 34.8159 32.8232 34.6343H32.8057C32.7793 34.8013 32.75 34.9331 32.7178 35.0298L31.8521 37.5435H33.7812ZM41.9858 40H40.8433L37.833 35.3682C37.7568 35.251 37.6938 35.1294 37.644 35.0034H37.6177C37.6411 35.1382 37.6528 35.4268 37.6528 35.8691V40H36.6421V33.6982H37.8594L40.7686 38.2202C40.8916 38.4077 40.9707 38.5366 41.0059 38.6069H41.0234C40.9941 38.4399 40.9795 38.1572 40.9795 37.7588V33.6982H41.9858V40Z"
id="pill_text"
inkscape:connector-curvature="0"
style="fill:#000000;stroke-width:1;stroke:none;stroke-miterlimit:4;stroke-dasharray:none" />
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,17 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="foreground"><stop stop-color="#000000"/></linearGradient>
<linearGradient id="background"><stop stop-color="#ffffff"/></linearGradient>
</defs>
<!-- background rounded rectangle -->
<path d="M2 6C0.9 6 0 6.9 0 8L0 12L0 13L0 40C0 41.1 0.9 42 2 42L46 42C47.1 42 48 41.1 48 40L48 13L48 12L48 8C48 6.9 47.1 6 46 6L32 6L16 6L2 6Z" fill="url(#background)"/>
<!-- tab outlines -->
<rect y="12" x="0" height="1" width="48" fill="url(#foreground)"/>
<rect y="6" x="15.33" height="7" width="1" fill="url(#foreground)"/>
<rect y="6" x="31.66" height="7" width="1" fill="url(#foreground)"/>
<!-- > -->
<path d="M15.2 24.3L6.4 33.1C5.9 33.6 5.9 34.3 6.4 34.7L8.2 36.5C8.7 37 9.4 37 9.8 36.5L18.6 27.7C19.1 27.2 19.1 26.5 18.6 26.1L16.8 24.3C16.4 23.9 15.6 23.9 15.2 24.3Z" fill="url(#foreground)"/>
<path d="M9.8 17.3L18.6 26.1C19.1 26.6 19.1 27.3 18.6 27.7L16.8 29.5C16.3 30 15.6 30 15.2 29.5L6.4 20.7C5.9 20.2 5.9 19.5 6.4 19.1L8.2 17.3C8.6 16.9 9.4 16.9 9.8 17.3Z" fill="url(#foreground)"/>
<!-- "PRE" -->
<path d="m 27.279297,33.324219 c 0,2.468099 0,4.936198 0,7.404297 0.513672,0 1.027343,0 1.541015,0 0,-0.848958 0,-1.697917 0,-2.546875 0.917549,0.01484 1.927453,0.03299 2.65875,-0.616892 1.172278,-0.927905 1.176118,-3.073122 -0.17547,-3.840777 -0.981472,-0.568217 -2.13908,-0.358412 -3.218649,-0.399753 -0.268549,0 -0.537097,0 -0.805646,0 z m 5.869141,0 c 0,2.468099 0,4.936198 0,7.404297 0.513021,0 1.026041,0 1.539062,0 0,-0.950521 0,-1.901042 0,-2.851563 0.431639,-0.03621 0.908827,0.05394 1.148438,0.458985 0.525553,0.771736 0.970414,1.596546 1.458984,2.392578 0.604167,0 1.208333,0 1.8125,0 -0.638695,-0.976785 -1.211177,-1.999445 -1.914561,-2.931671 -0.241051,-0.276681 -0.636923,-0.466649 -0.07177,-0.574189 1.274395,-0.677377 1.378019,-2.774051 0.102268,-3.504493 -0.922467,-0.560429 -2.029423,-0.352936 -3.053526,-0.393944 -0.340466,0 -0.680932,0 -1.021398,0 z m 6.25,0 c 0,2.468099 0,4.936198 0,7.404297 1.440755,0 2.88151,0 4.322265,0 0,-0.454427 0,-0.908855 0,-1.363282 -0.925781,0 -1.851563,0 -2.777344,0 0,-0.566406 0,-1.132812 0,-1.699218 0.804688,0 1.609375,0 2.414063,0 0,-0.454427 0,-0.908855 0,-1.363282 -0.804688,0 -1.609375,0 -2.414063,0 0,-0.536458 0,-1.072917 0,-1.609375 0.873047,0 1.746094,0 2.619141,0 0,-0.45638 0,-0.91276 0,-1.36914 -1.388021,0 -2.776041,0 -4.164062,0 z M 34.6875,34.648438 c 0.570781,0.0371 1.28319,-0.150767 1.691507,0.358943 0.370833,0.564952 0.02331,1.464787 -0.684396,1.526855 -0.334157,0.03512 -0.67147,0.0117 -1.007111,0.0185 0,-0.634765 0,-1.269531 0,-1.904296 z m -5.867188,0.01562 c 0.61736,0.02299 1.42501,-0.135196 1.79395,0.492096 0.333428,0.657753 -0.0252,1.619083 -0.829192,1.664678 -0.319151,0.05007 -0.643164,0.0243 -0.964758,0.03073 0,-0.729167 0,-1.458333 0,-2.1875 z" fill="url(#foreground)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1002 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Some files were not shown because too many files have changed in this diff Show More