Skip to content

⚡Improve Build Performance by Using Invoke-Build Incremental Builds #3619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

⚡Improve Build Performance by Using Invoke-Build Incremental Builds #3619

wants to merge 1 commit into from

Conversation

JustinGrote
Copy link
Collaborator

@JustinGrote JustinGrote commented Oct 15, 2021

Improves the InvokeBuild script to use the Incremental Tasks feature to only rebuild components that have changed. Dramatically shortens the inner dev loop when making changes.
https://github.com/nightroman/Invoke-Build/wiki/Incremental-Tasks

PR Summary

PR Checklist

Note: Tick the boxes below that apply to this pull request by putting an x between the square brackets.
Please mark anything not applicable to this PR NA.

  • PR has a meaningful title
  • Summarized changes
  • PR has tests
  • This PR is ready to merge and is not work in progress
    • If the PR is work in progress, please add the prefix WIP: to the beginning of the title and remove the prefix when the PR is ready

}

#endregion
#region Build tasks

task BuildEditorServices -If (Get-EditorServicesPath) {
Task BuildEditorServices -Input {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is going to work. This task and build script is specifically setup to allow the build to work when the PSES repo does not exist, but a drop of PSES (like from the signing build) has been placed in the appropriate location.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't something like substituting in a separate PSES be explicit? I could add a -UseExistingPSES switch or something to the script and the appropriate same place on the CI for that scenario

@JustinGrote
Copy link
Collaborator Author

JustinGrote commented Oct 15, 2021

Not sure if this is going to work. This task and build script is specifically setup to allow the build to work when the PSES repo does not exist, but a drop of PSES (like from the signing build) has been placed in the appropriate location.

I thought that's what specifying the EditorServicesRepoPath via the param is supposed to do...

Wait I kind of see what you are saying, one sec.

Copy link
Member

@andyleejordan andyleejordan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand why these changes need to be made to this build script. As it exists, it simply invokes the build in the PSES repo (if it exists) and copies it to the appropriate location. Improvements to the PSES build script to rebuild itself incrementally would be welcome, but definitely don't belong here, they should be as decoupled as possible in order to support dropping PSES builds manually (or via automation). And that improvement shouldn't require changes here, as the cd PSES && Invoke-Build would automatically become incremental if done there.

@andyleejordan
Copy link
Member

Don't get me wrong, I appreciate it, but I massaged this build script to hell that it it guarantees a clean and correct build for both dev and release/signing scenarios, with that prioritized over speed (and the slowest thing here is restore Node modules, running TSC to check types, and running the PSES build itself).

@JustinGrote
Copy link
Collaborator Author

Not sure I understand why these changes need to be made to this build script. As it exists, it simply invokes the build in the PSES repo (if it exists) and copies it to the appropriate location. Improvements to the PSES build script to rebuild itself incrementally would be welcome, but definitely don't belong here, they should be as decoupled as possible in order to support dropping PSES builds manually (or via automation). And that improvement shouldn't require changes here, as the cd PSES && Invoke-Build would automatically become incremental if done there.

The intent was to enable changes to be made to the PSES repository and be able to just click "run extension" to see the changes, as of today you have to clean and do a full rebuild, so the time between change and testing the change is 30-45 seconds. I have a small separate PR to allow incremental builds in PSES and a further PR to do incremental builds to that script as well.

@andyleejordan
Copy link
Member

I had an idea last night @JustinGrote: What if we introduced a Link task that instead of copying ../pses/module to the extension build, it symlinked it! It would need to be separate because that would NOT work in a VSIX package, but as a dev we could use the task to set things up. Then the incremental build of PSES will just update the files directly in that folder and the extension just needs to be relaunched.

@JustinGrote
Copy link
Collaborator Author

@andschwa seems fine to me, only issue I can think of are really edge case.

Write-Host "`n### Running extension tests" -ForegroundColor Green
exec { & npm run test }
if ($ENV:TERM_PROGRAM -eq 'vscode') {
Write-Warning 'E2E Tests cannot be performed from the CLI while vscode is running, please close vscode and run again or use the "Launch Extension Tests" launch config'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure they can, that's the whole reason it opens up a copy of Insiders.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe because I was running on insiders, it threw an error for me every time and I couldn't find a way to specific like a "data-only" copy of insiders.

$editorServicesPath = Get-EditorServicesPath
$editorServicesBuildScriptPath = Get-EditorServicesBuildScriptPath
} catch {
throw 'Powershell Editor Services repo was not detected. Specify its path via the -EditorServicesRepoPath parameter or ensure it is available in the directory above {0}' -f $PSScriptRoot
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so this change should no longer be necessary with #3623.


$restoreCheckpoint = "$PSScriptRoot/node_modules/restored"
#This will run when node_modules is empty or when package.json is updated
Task Restore -Input $PSScriptRoot/package.json -Output { $RestoreCheckpoint } {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just -Input package.json -Output node_modules?

#We use these files as a freshness indicator since they always gets updated on a build
#TODO: More granular incremental build on PSES tasks
Join-Path $editorServicesPath 'module/PowerShellEditorServices/bin/Core/Microsoft.PowerShell.EditorServices.Hosting.dll'
} -If $editorServicesBuildScriptPath {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this shouldn't be necessary any more.

Write-Host "`n### Copying PowerShellEditorServices module files" -ForegroundColor Green
Copy-Item -Recurse -Force "$(Split-Path (Get-EditorServicesPath))/module/*" ./modules
Copy-Item $PSESModulePath/* -Recurse -Force -Destination (Join-Path $PSScriptRoot 'modules')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

} -Output {
Join-Path $PSScriptRoot 'out/main.js'
Get-ChildItem -File -Recurse (Join-Path $PSScriptRoot 'out')
} CopyEditorServices, Restore, {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this, since esbuild is soooo quick, what if we moved the calls of tsc all to the lint step and did the lint when running the tests instead? Then rebuilding the extension doesn't need to be incremental, and the tests can be the "slower" part. (Note that esbuild does not build the test files, just the extension.)

@@ -104,13 +145,21 @@ task UpdateReadme -If { $script:IsPreviewExtension } {
$readmePath = (Join-Path $PSScriptRoot README.md)

$readmeContent = Get-Content -Path $readmePath
if (!($readmeContent -match "This is the PREVIEW version of the PowerShell extension")) {
if (!($readmeContent -match 'This is the PREVIEW version of the PowerShell extension')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we save changes like this for a different PR?

Comment on lines +155 to +161
Get-ChildItem $PSScriptRoot -Exclude '.vscode-test', 'logs', 'sessions', 'node_modules', '.git' |
Get-ChildItem -Recurse -File
} -Output {
$vsix = Get-ChildItem $PSScriptRoot/*.vsix
if (-not $VSIX) {
'No VSIX Created Yet'
} else { $vsix }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this is necessary. The VSIX is only really created by the release pipeline, and only occasionally by a developer (and doesn't need to be incremental).

@JustinGrote JustinGrote marked this pull request as draft November 10, 2021 19:42
@andyleejordan
Copy link
Member

Gonna close this one Justin as the build has changed a lot (though it was inspirational!)

@JustinGrote JustinGrote deleted the JustinGrote/incrementalBuilds branch January 20, 2022 23:12
@JustinGrote
Copy link
Collaborator Author

Fair!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants