diff --git a/.github/workflows/qa-azure.yaml b/.github/workflows/qa-azure.yaml new file mode 100644 index 000000000..b23cacfaf --- /dev/null +++ b/.github/workflows/qa-azure.yaml @@ -0,0 +1,191 @@ +name: Build and run end-to-end tests +# Builds the project, and runs end-to-end tests using the generated artifacts. + +concurrency: azure-vm + +on: + pull_request: + workflow_dispatch: + push: + branches: [main] + +env: + az_name: wsl-ci-3 + az_resource_group: wsl + flutter-version: 3.13.x + +jobs: + build-wsl-pro-service: + name: Build wsl-pro-service debian package + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + - name: Build debian package + uses: canonical/desktop-engineering/gh-actions/common/build-debian@main + with: + source-dir: wsl-pro-service + token: ${{ secrets.GITHUB_TOKEN }} + docker-image: ubuntu:devel + env: + UP4W_SKIP_INTERNAL_DEPENDENCY_UPDATE: "1" + + build-ubuntu-pro-for-windows: + name: Build Windows Agent Appx + runs-on: windows-latest + steps: + - name: Set up git + uses: canonical/ubuntu-pro-for-windows/.github/actions/setup-git@main + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Check out repository + uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + go-version-file: go.work + - uses: subosito/flutter-action@v2 + with: + channel: stable + flutter-version: ${{ env.flutter-version }} + - name: Setup MSBuild (PATH) + uses: microsoft/setup-msbuild@v1.3.1 + - name: Install certificate + shell: powershell + run: | + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.CERTIFICATE }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + + $pwd = ConvertTo-SecureString '${{ secrets.CERTIFICATE_PASSWORD }}' -AsPlainText -Force + Import-PfxCertificate -Password $pwd -CertStoreLocation Cert:LocalMachine\Trust -FilePath certificate\certificate.pfx + Import-PfxCertificate -Password $pwd -CertStoreLocation Cert:CurrentUser\My -FilePath certificate\certificate.pfx + - name: Build Bundle + run: | + msbuild ` + .\msix\msix.sln ` + -target:Build ` + -maxCpuCount ` + -nodeReuse:false ` + -property:Configuration=Release ` + -property:AppxBundle=Always ` + -property:AppxBundlePlatforms=x64 ` + -property:UapAppxPackageBuildMode=SideloadOnly ` + -property:Version=0.0.1+${{ github.sha }} ` + -nologo ` + -verbosity:normal + - name: Upload sideload artifact + uses: actions/upload-artifact@v3 + with: + name: UbuntuProForWindows+${{ github.sha }} + path: | + msix/UbuntuProForWindows/AppPackages/UbuntuProForWindows_*/UbuntuProForWindows_*_x64.cer + msix/UbuntuProForWindows/AppPackages/UbuntuProForWindows_*/UbuntuProForWindows_*_x64.msixbundle + + vm-setup: + name: Set up Azure VM + runs-on: ubuntu-latest + steps: + - name: Azure login + uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_VM_CREDS }} + - name: Start the Runner + shell: bash + run: | + az vm start --name ${{ env.az_name }} --resource-group ${{ env.az_resource_group }} + + qa: + name: Run end-to-end tests on the Azure VM + runs-on: [self-hosted, Windows] + needs: [vm-setup, build-wsl-pro-service, build-ubuntu-pro-for-windows] + steps: + - name: Set up git + uses: canonical/ubuntu-pro-for-windows/.github/actions/setup-git@main + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up Ubuntu + uses: Ubuntu/WSL/.github/actions/wsl-install@main + with: + distro: "Ubuntu" + - name: Set up Go + # actions/setup-go is broken + shell: powershell + run: | + winget install GoLang.Go --accept-source-agreements --accept-package-agreements --silent --verbose + # Cannot check for error: there is no way to distinguish the two: + # - Legitimate error + # - Error because no updates found (Golang.Go is already up to date) + # + # We can check that Go works, though. + go version + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + # name: is left blank so that all artifacts are downloaded + path: ci-artifacts + - name: Set up artifacts + shell: powershell + working-directory: ci-artifacts + run: | + Write-Output "::group::Set up AppxPackage" + Get-AppxPackage -Name "CanonicalGroupLimited.UbuntuProForWindows" | Remove-AppxPackage -ErrorAction Ignore + + New-Item -Name "windows-agent" -ItemType Directory + Move-Item -Path "UbuntuProForWindows+*/UbuntuProForWindows_*/*.msixbundle" -Destination "windows-agent/" + Move-Item -Path "UbuntuProForWindows+*/UbuntuProForWindows_*/*.cer" -Destination "windows-agent/" + Remove-Item -Recurse "UbuntuProForWindows+*/" + + $cert = "$(Get-ChildItem windows-agent/UbuntuProForWindows_*.cer)" + Import-Certificate -FilePath "${cert}" -CertStoreLocation Cert:LocalMachine\TrustedPeople + + Write-Output "::endgroup::" + + Write-Output "::group::Set up WSL Pro Service" + New-Item -Name "wsl-pro-service" -ItemType Directory + Move-Item -Path "wsl-pro-service_*/wsl-pro-service_*.deb" -Destination "wsl-pro-service/" + Remove-Item -Recurse "wsl-pro-service_*/" + Write-Output "::endgroup::" + - name: Test + shell: powershell + env: + GIT_TERMINAL_PROMPT: "0" + UP4W_TEST_OVERRIDE_DESTRUCTIVE_CHECKS: "1" + UP4W_TEST_BUILD_PATH: "../ci-artifacts" + UP4W_TEST_PRO_TOKEN: "${{ secrets.UBUNTU_PRO_TOKEN }}" + run: | + go env -w "GOPRIVATE=github.com/${{ github.repository }}" + + go test .\end-to-end -shuffle=on -timeout 20m + if ( "$LastExitCode" -ne "0" ) { Exit(1) } + - name: Clean up + if: always() + shell: powershell + run: | + # Clean up artifacts + + # Remove .gitconfig so that the github URL overrides do not stack + Remove-Item -Recurse -Path "${HOME}\.gitconfig" -ErrorAction Ignore + + # Uninstall Appx + Get-AppxPackage -Name "CanonicalGroupLimited.UbuntuProForWindows" | Remove-AppxPackage -ErrorAction Ignore + + # Uninstall certificate + $thumbprint = (Get-PfxCertificate -FilePath "ci-artifacts\windows-agent\UbuntuProForWindows_*.cer").Thumbprint + Remove-Item -Path "Cert:LocalMachine\TrustedPeople\${thumbprint}" + + stop-vm: + name: Clean up the Azure VM + runs-on: ubuntu-latest + needs: [vm-setup, qa] + if: always() + steps: + - name: Azure login + uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_VM_CREDS }} + - name: Deallocate the Runner + shell: bash + run: | + az vm deallocate --name ${{ env.az_name }} --resource-group ${{ env.az_resource_group }} diff --git a/.github/workflows/qa.yaml b/.github/workflows/qa.yaml index 0fcbee84a..a8c878969 100644 --- a/.github/workflows/qa.yaml +++ b/.github/workflows/qa.yaml @@ -256,69 +256,3 @@ jobs: uses: ./.github/actions/check-diff with: files-to-validate: '${{ matrix.subproject }}/{.,**}/*.{dart,go}' - - build-wsl-pro-service: - name: Build wsl-pro-service debian package - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v4 - - name: Build debian package - uses: canonical/desktop-engineering/gh-actions/common/build-debian@main - with: - source-dir: wsl-pro-service - token: ${{ secrets.GITHUB_TOKEN }} - docker-image: ubuntu:devel - env: - UP4W_SKIP_INTERNAL_DEPENDENCY_UPDATE: "1" - - build-ubuntu-pro-for-windows: - name: Build Windows Agent Appx - runs-on: windows-latest - steps: - - name: Set up git - uses: canonical/ubuntu-pro-for-windows/.github/actions/setup-git@main - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: Check out repository - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 - with: - go-version-file: go.work - - uses: subosito/flutter-action@v2 - with: - channel: stable - flutter-version: ${{ env.flutter-version }} - - name: Setup MSBuild (PATH) - uses: microsoft/setup-msbuild@v1.3.1 - - name: Install certificate - shell: powershell - run: | - New-Item -ItemType directory -Path certificate - Set-Content -Path certificate\certificate.txt -Value '${{ secrets.CERTIFICATE }}' - certutil -decode certificate\certificate.txt certificate\certificate.pfx - - $pwd = ConvertTo-SecureString '${{ secrets.CERTIFICATE_PASSWORD }}' -AsPlainText -Force - Import-PfxCertificate -Password $pwd -CertStoreLocation Cert:LocalMachine\Trust -FilePath certificate\certificate.pfx - Import-PfxCertificate -Password $pwd -CertStoreLocation Cert:CurrentUser\My -FilePath certificate\certificate.pfx - - name: Build Bundle - run: | - msbuild ` - .\msix\msix.sln ` - -target:Build ` - -maxCpuCount ` - -nodeReuse:false ` - -property:Configuration=Release ` - -property:AppxBundle=Always ` - -property:AppxBundlePlatforms=x64 ` - -property:UapAppxPackageBuildMode=SideloadOnly ` - -property:Version=0.0.1+${{ github.sha }} ` - -nologo ` - -verbosity:normal - - name: Upload sideload artifact - uses: actions/upload-artifact@v3 - with: - name: UbuntuProForWindows+${{ github.sha }} - path: | - msix/UbuntuProForWindows/AppPackages/UbuntuProForWindows_*/UbuntuProForWindows_1.0.0.0_x64.cer - msix/UbuntuProForWindows/AppPackages/UbuntuProForWindows_*/UbuntuProForWindows_1.0.0.0_x64.msixbundle diff --git a/doc/02.-Installation.md b/doc/02.-Installation.md index 90a715d45..43028de57 100644 --- a/doc/02.-Installation.md +++ b/doc/02.-Installation.md @@ -10,7 +10,7 @@ This guide will show you how to install Ubuntu Pro For Windows for local develop ### Download -1. Go to the [repository actions page](https://github.com/canonical/ubuntu-pro-for-windows/actions/workflows/qa.yaml?query=branch%3Amain+). +1. Go to the [repository actions page](https://github.com/canonical/ubuntu-pro-for-windows/actions/workflows/qa-azure.yaml?query=branch%3Amain+). 2. Click the latest successful workflow run. 3. Scroll down past any warnings or errors, until you reach the Artifacts section. 4. Download: @@ -27,7 +27,7 @@ This is the Windows-side agent that manages the distros. 2. Follow the download steps to download UbuntuProForWindows 3. Unzip the artifact 4. Find the certificate inside. Install it into `Local Machine/Trusted people`. -5. Open Powershell in this directory and run +5. Open Powershell in this directory and run ```powershell Add-AppxPackage .\UbuntuProForWindows_*_x64.msixbundle ``` @@ -91,7 +91,7 @@ You can use a private Landscape instance (different from [landscape.canonical.co 4. Click on "Click to restart it". 9. Stop the distro you installed WSL-Pro-Service in: ```powershell - wsl --terminate DISTRO_NAME + wsl --terminate DISTRO_NAME ``` 10. Start the distro you installed WSL-Pro-Service in. 11. You should see a new "pending computer authorisation" in you Landscape dashboard. \ No newline at end of file diff --git a/end-to-end/go.sum b/end-to-end/go.sum index 5663837b9..f56bd4f8f 100644 --- a/end-to-end/go.sum +++ b/end-to-end/go.sum @@ -23,6 +23,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/ubuntu/decorate v0.0.0-20230905131025-e968fa48a85c h1:jO41xNLddTDkrfz4w4RCMWCmX8Y+ZHz5jSbJWNLDvqU= +github.com/ubuntu/decorate v0.0.0-20230905131025-e968fa48a85c/go.mod h1:edGgz97NOqS2oqzbKrZqO9YU9neosRrkEZbVJVQynAA= github.com/ubuntu/gowsl v0.0.0-20230710120903-fcfd527a92e4 h1:fci3jnfZQxfb92PRQwJHXR7Mxj5OiIWXVxkkpiXrkQI= github.com/ubuntu/gowsl v0.0.0-20230710120903-fcfd527a92e4/go.mod h1:PBcZk1oAKQn1fwC9d9G2Vu25Ypxab9+UZMaPiPNjDy8= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/end-to-end/main_test.go b/end-to-end/main_test.go index d14249565..81ccfb941 100644 --- a/end-to-end/main_test.go +++ b/end-to-end/main_test.go @@ -34,6 +34,16 @@ const ( // overrideSafety is an env variable that, if set, allows the tests to perform potentially destructive actions. overrideSafety = "UP4W_TEST_OVERRIDE_DESTRUCTIVE_CHECKS" + // prebuiltPath is an env variable that, if set, uses a build at a certain path instead of building the project anew. + // The structure is expected to be: + // └──${prebuiltPath} + // ├───wsl-pro-service + // │ └──wsl-pro-service_*.deb + // └───windows-agent + // └──UbuntuProForWindows_*.msixbundle + // + prebuiltPath = "UP4W_TEST_BUILD_PATH" + // referenceDistro is the WSL distro that will be used to generate the test image. referenceDistro = "Ubuntu" @@ -60,15 +70,15 @@ func TestMain(m *testing.M) { log.Fatalf("Setup: %v\n", err) } - wslProServiceDebPath, err := buildProject(ctx) + f := buildProject + if buildPath := os.Getenv(prebuiltPath); buildPath != "" { + f = usePrebuiltProject + } + + wslProServiceDebPath, err := f(ctx) if err != nil { log.Fatalf("Setup: %v\n", err) } - defer func() { - if err := os.RemoveAll(wslProServiceDebPath); err != nil { - log.Printf("could not remove debian artifacts at %q: %v", wslProServiceDebPath, err) - } - }() if err := assertAppxInstalled(ctx, "CanonicalGroupLimited.UbuntuProForWindows"); err != nil { log.Fatalf("Setup: %v\n", err) @@ -86,6 +96,37 @@ func TestMain(m *testing.M) { if err := cleanupRegistry(); err != nil { log.Printf("Cleanup: registry: %v\n", err) } + + cmd := powershellf(ctx, "Get-AppxPackage -Name CanonicalGroupLimited.UbuntuProForWindows | Remove-AppxPackage") + if out, err := cmd.CombinedOutput(); err != nil { + log.Printf("Cleanup: could not remove Appx: %v: %s", err, out) + } +} + +func usePrebuiltProject(ctx context.Context) (debPath string, err error) { + buildPath := os.Getenv(prebuiltPath) + + // Remove Appx before installing + cmd := powershellf(ctx, "Get-AppxPackage CanonicalGroupLimited.UbuntuProForWindows | Remove-AppxPackage") + if out, err := cmd.CombinedOutput(); err != nil { + // (Probably because it was not installed) + log.Printf("Could not remove old AppxPackage: %v. %s", err, out) + } + + // Install Appx anew + cmd = powershellf(ctx, "Add-AppxPackage %q", filepath.Join(buildPath, "windows-agent", "UbuntuProForWindows_*.msixbundle")) + if out, err := cmd.CombinedOutput(); err != nil { + return "", fmt.Errorf("could not install pre-built AppxPackage: %v. %s", err, out) + } + + // Locate WSL-Pro-Service (it'll be installed later into the distros) + debPath = filepath.Join(buildPath, "wsl-pro-service") + _, err = locateWslProServiceDeb(ctx, debPath) + if err != nil { + return "", fmt.Errorf("could not localte pre-built WSL-Pro-Service: %v", err) + } + + return debPath, err } func buildProject(ctx context.Context) (debPath string, err error) { @@ -318,7 +359,7 @@ func generateTestImage(ctx context.Context, sourceDistro, wslProServiceDebPath s return "", nil, err } - out, err = d.Command(ctx, fmt.Sprintf("apt install $(wslpath -ua '%s')", debPath)).CombinedOutput() + out, err = d.Command(ctx, fmt.Sprintf("DEBIAN_FRONTEND=noninteractive apt install -y $(wslpath -ua '%s')", debPath)).CombinedOutput() if err != nil { defer cleanup() return "", nil, fmt.Errorf("could not install wsl-pro-service: %v. %s", err, out) diff --git a/end-to-end/organization_token_test.go b/end-to-end/organization_token_test.go index 177155dce..dbb7e9cc2 100644 --- a/end-to-end/organization_token_test.go +++ b/end-to-end/organization_token_test.go @@ -3,6 +3,7 @@ package endtoend_test import ( "context" "encoding/json" + "fmt" "os" "testing" "time" @@ -40,7 +41,8 @@ func TestOrganizationProvidedToken(t *testing.T) { if tc.whenToken == beforeDistroRegistration { activateOrgSubscription(t) - startAgent(t, ctx) + cleanup := startAgent(t, ctx) + defer cleanup() } // Distro setup @@ -57,35 +59,55 @@ func TestOrganizationProvidedToken(t *testing.T) { require.NoError(t, err, "could not restart distro") activateOrgSubscription(t) - startAgent(t, ctx) + cleanup := startAgent(t, ctx) + defer cleanup() out, err := d.Command(ctx, "exit 0").CombinedOutput() require.NoErrorf(t, err, "Setup: could not wake distro up: %v. %s", err, out) } - // Give the agent some time to pro-attach - time.Sleep(5 * time.Second) - - // Validate that the distro was attached - out, err = d.Command(ctx, "pro status --format=json").Output() - require.NoErrorf(t, err, "Setup: could not call pro status: %v. %s", err, out) - - var response struct { - Attached bool - } - err = json.Unmarshal(out, &response) - require.NoError(t, err, "could not parse pro status response: %s", out) + const maxTimeout = 30 * time.Second if !tc.wantAttached { - require.False(t, response.Attached, "distro should not have been Pro attached") + time.Sleep(maxTimeout) + attached, err := distroIsProAttached(t, d) + require.NoError(t, err, "could not determine if distro is attached") + require.False(t, attached, "distro should not have been Pro attached") return } - require.True(t, response.Attached, "distro should have been Pro attached") + require.Eventually(t, func() bool { + attached, err := distroIsProAttached(t, d) + if err != nil { + t.Logf("could not determine if distro is attached: %v", err) + } + return attached + }, maxTimeout, time.Second, "distro should have been Pro attached") }) } } +func distroIsProAttached(t *testing.T, d wsl.Distro) (bool, error) { + t.Helper() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + out, err := d.Command(ctx, "pro status --format=json").Output() + if err != nil { + return false, fmt.Errorf("could not call pro status: %v. %s", err, out) + } + + var response struct { + Attached bool + } + if err := json.Unmarshal(out, &response); err != nil { + return false, fmt.Errorf("could not parse pro status response: %v: %s", err, out) + } + + return response.Attached, nil +} + func activateOrgSubscription(t *testing.T) { t.Helper() diff --git a/end-to-end/utils_test.go b/end-to-end/utils_test.go index becd8269b..a87a94cc4 100644 --- a/end-to-end/utils_test.go +++ b/end-to-end/utils_test.go @@ -1,6 +1,7 @@ package endtoend_test import ( + "bytes" "context" "errors" "fmt" @@ -60,44 +61,70 @@ func registerFromTestImage(t *testing.T, ctx context.Context) string { } // startAgent starts the GUI (without interacting with it) and waits for the Agent to start. +// It stops the agent upon cleanup. If the cleanup fails, the testing will be stopped. // //nolint:revive // testing.T must precede the contex -func startAgent(t *testing.T, ctx context.Context) { +func startAgent(t *testing.T, ctx context.Context) (cleanup func()) { t.Helper() t.Log("Starting agent") - defer t.Log("Started agent") out, err := powershellf(ctx, "(Get-AppxPackage CanonicalGroupLimited.UbuntuProForWindows).InstallLocation").CombinedOutput() require.NoError(t, err, "could not locate ubuntupro.exe: %v. %s", err, out) - ctx, cancel := context.WithCancel(ctx) - ubuntupro := filepath.Join(strings.TrimSpace(string(out)), "gui", "ubuntupro.exe") //nolint:gosec // The executable is located at the Appx directory cmd := exec.CommandContext(ctx, ubuntupro) - t.Cleanup(func() { - cancel() - //nolint:errcheck // This returns a "context cancelled" error. - cmd.Wait() - }) + var buff bytes.Buffer + cmd.Stdout = &buff + cmd.Stderr = &buff err = cmd.Start() require.NoError(t, err, "Setup: could not start agent") + cleanup = func() { + t.Log("Cleanup: stopping agent process") + + if err := stopAgent(ctx); err != nil { + // We have to abort because the tests become coupled via the agent + log.Fatalf("Could not kill ubuntu-pro-agent process: %v: %s", err, out) + } + + //nolint:errcheck // Nothing we can do about it + cmd.Process.Kill() + + //nolint:errcheck // We know that the previous "Kill" stopped it + cmd.Wait() + t.Logf("Agent stopped. Stdout+stderr: %s", buff.String()) + } + + defer func() { + if t.Failed() { + cleanup() + } + }() + require.Eventually(t, func() bool { localAppData := os.Getenv("LocalAppData") - require.NotEmpty(t, localAppData, "$env:LocalAppData should not be empty") + if localAppData == "" { + t.Logf("Agent setup: $env:LocalAppData should not be empty") + return false + } _, err := os.Stat(filepath.Join(localAppData, "Ubuntu Pro", "addr")) - if err == nil { - return true + if errors.Is(err, fs.ErrNotExist) { + return false + } + if err != nil { + t.Logf("Agent setup: could not read addr file: %v", err) + return false } - require.ErrorIsf(t, err, fs.ErrNotExist, "could not read addr file") + return true + }, 30*time.Second, 100*time.Millisecond, "Agent never started serving") - return false - }, 5*time.Second, 100*time.Millisecond, "Agent never started serving") + t.Log("Started agent") + return cleanup } // stopAgent kills the process for the Windows Agent. diff --git a/gui/packages/ubuntupro/lib/launch_agent.dart b/gui/packages/ubuntupro/lib/launch_agent.dart index d33097a6c..aa39197f5 100644 --- a/gui/packages/ubuntupro/lib/launch_agent.dart +++ b/gui/packages/ubuntupro/lib/launch_agent.dart @@ -17,8 +17,9 @@ Future launchAgent(String agentRelativePath) async { try { await Process.start( agentPath, - [], + ['-vv'], environment: Environment.instance.merged, + mode: ProcessStartMode.inheritStdio, ); return true; } on ProcessException catch (err) { diff --git a/msix/UbuntuProForWindows/UbuntuProForWindows.wapproj b/msix/UbuntuProForWindows/UbuntuProForWindows.wapproj index 6949f393b..f6b246e71 100644 --- a/msix/UbuntuProForWindows/UbuntuProForWindows.wapproj +++ b/msix/UbuntuProForWindows/UbuntuProForWindows.wapproj @@ -107,4 +107,4 @@ - \ No newline at end of file + diff --git a/tools/build/build-appx.ps1 b/tools/build/build-appx.ps1 index 33d166275..87cd5c415 100644 --- a/tools/build/build-appx.ps1 +++ b/tools/build/build-appx.ps1 @@ -44,10 +44,12 @@ function Update-Certificate { # Finding local certificate $certificate_path = "${PSScriptRoot}\.certificate_thumbprint" if (! (Test-Path "${certificate_path}") ) { - Write-Error "You need a certificate to build and install the Appx. ` + Write-Warning "You need a certificate to build and install the Appx. ` Create and install a certificate, and write its thumbprint in ${certificate_path}.` See https://learn.microsoft.com/en-us/windows/win32/appxpkg/how-to-create-a-package-signing-certificate for more details" - exit 1 + + Write-Output "Continuing with default certificate" + return } $certificate_thumbprint = Get-Content ${certificate_path} @@ -62,6 +64,8 @@ function Update-Certificate { } function Install-Appx { + Get-AppxPackage -Name "CanonicalGroupLimited.UbuntuProForWindows" | Remove-AppxPackage + $artifacts = ( Get-ChildItem ".\msix\UbuntuProForWindows\AppPackages\UbuntuProForWindows_*" ` | Sort-Object LastWriteTime ` @@ -84,7 +88,11 @@ Push-Location "${PSScriptRoot}\..\.." Update-Certificate -Start-VsDevShell +try { + msbuild.exe --version +} catch { + Start-VsDevShell +} msbuild.exe ` .\msix\msix.sln ` diff --git a/tools/build/build-deb.ps1 b/tools/build/build-deb.ps1 index c7a872329..3f405d77f 100644 --- a/tools/build/build-deb.ps1 +++ b/tools/build/build-deb.ps1 @@ -4,7 +4,7 @@ #> param( - [Parameter(Mandatory=$False,HelpMessage="The directory where the debian build artifacts will be stored in")] + [Parameter(Mandatory = $False, HelpMessage = "The directory where the debian build artifacts will be stored in")] [string]$OutputDir ) @@ -21,7 +21,7 @@ if ( $appx -eq "" ) { Write-Error "Ubuntu Preview is not installed" } -$env:WSL_UTF8=1 +$env:WSL_UTF8 = 1 if ( "$(wsl --list --verbose | Select-String Ubuntu-Preview)" -eq "" ) { ubuntupreview.exe install --root --ui=none @@ -29,12 +29,14 @@ if ( "$(wsl --list --verbose | Select-String Ubuntu-Preview)" -eq "" ) { Write-Error "could not install Ubuntu-Preview" exit 1 } + + Copy-Item -Path "${HOME}/.gitconfig" -Destination "\\wsl$\Ubuntu-Preview\etc\gitconfig" } # Write script to run -$scriptWindows=New-TemporaryFile +$scriptWindows = New-TemporaryFile -$scriptLinux=( wsl.exe -d Ubuntu-Preview -- wslpath -ua `'${scriptWindows}`' ) +$scriptLinux = ( wsl.exe -d Ubuntu-Preview -- wslpath -ua `'${scriptWindows}`' ) if ( "${LastExitCode}" -ne "0" ) { Write-Error "could not get build script's linux path" exit 1 @@ -47,9 +49,13 @@ set -eu git config --global --add safe.directory "$(pwd)" -# Update internal dependencies in the repo -# (we need git to work, and .git is not rsync'd) +# Update internal dependencies in the repo because +# we need git to work, and .git is not rsync'd. cd wsl-pro-service +go version || ( + sudo DEBIAN_FRONTEND=noninteractive apt update + sudo DEBIAN_FRONTEND=noninteractive apt install -y golang-go +) ./debian/update-internal-dependencies go mod tidy go mod vendor @@ -63,6 +69,7 @@ rsync \ --quiet \ --exclude=".git" \ --exclude="msix/UbuntuProForWindows" \ + --exclude="gui" \ --exclude="*vcxproj*" \ --exclude="*/x64/*" \ . \ @@ -79,7 +86,7 @@ cp -f ${build_dir}/wsl-pro-service_* "${OutputDir}" # Set up output directory New-Item -Force -ItemType "Directory" -Path "${OutputDir}" | Out-Null -$outputLinux=( wsl.exe -d Ubuntu-Preview -- wslpath -ua `'${OutputDir}`' ) +$outputLinux = ( wsl.exe -d Ubuntu-Preview -- wslpath -ua `'${OutputDir}`' ) if ( "${LastExitCode}" -ne "0" ) { Write-Error "could not get output dir's linux path" exit 1 diff --git a/wsl-pro-service/debian/update-internal-dependencies b/wsl-pro-service/debian/update-internal-dependencies index 59d51f0ff..3b19d2ff8 100755 --- a/wsl-pro-service/debian/update-internal-dependencies +++ b/wsl-pro-service/debian/update-internal-dependencies @@ -2,7 +2,7 @@ set -eu # Add repo as private -go env -w GOPRIVATE=github.com/canonical/ubuntu-pro-for-windows +go env -w "GOPRIVATE=github.com/canonical/ubuntu-pro-for-windows" UP4W_SKIP_INTERNAL_DEPENDENCY_UPDATE=${UP4W_SKIP_INTERNAL_DEPENDENCY_UPDATE:-""}