Squirrel / Squirrel.Windows

An installation and update framework for Windows desktop apps
MIT License
7.22k stars 1.02k forks source link

azure devops --releasify #1580

Open greengumby opened 4 years ago

greengumby commented 4 years ago

Can anyone provide any guidance on how to perform a --releasify on azure devops yaml pipeline. I have tried cmdline@2 but this always results in a exit code of -1 and no futher detail. Thanks

lightlike commented 4 years ago

I did that for my own project. Debugging is very annoying when you do not get any error codes.

What I did is download the Squirrel executables as a zip and unpack them. After that, I used the command at the bottom to --releasify an already created nupkg.

I have not found out why, but if you are using certain hosted agents (e.g. release-agents) the creation of delta-packages will not work. (Probably because some system stuff is not installed on those light-weight machines)

variables:
  Version: '$(Build.BuildNumber)'

steps:
- task: CmdLine@1
  displayName: 'Releasify Squirrel'
  inputs:
    filename: '$(System.DefaultWorkingDirectory)/Squirrel/Squirrel.exe'
    arguments: '--releasify $(System.DefaultWorkingDirectory)\Release\*NupkgName*.$(Version).nupkg -r $(System.DefaultWorkingDirectory)\Output -n "/a /f $(pfx.secureFilePath) /p $(Sign.Password)" --framework-version=net461 --no-msi'
    workingFolder: '$(System.DefaultWorkingDirectory)\Release'
greengumby commented 4 years ago

Thanks @lightlike

For some reason I get the following output from the cmd. Hoping you had come across the same issue.

##[section]Starting: Releasify Squirrel
==============================================================================
Task         : Command Line
Description  : Run a command line with arguments
Version      : 1.1.3
Author       : Microsoft Corporation
Help         : [More Information](https://go.microsoft.com/fwlink/?LinkID=613735)
==============================================================================
##[command]D:\a\1\packages\squirrel.windows.1.9.1\tools\Squirrel.exe --releasify D:\a\1\a\nuget\XXX.1.0.20200120.7.nupkg --releaseDir D:\a\1\a\drop
##[error]Process completed with exit code -1.
##[section]Finishing: Releasify Squirrel

The yaml I am using is

- task: CmdLine@1 displayName: 'Releasify Squirrel' inputs: filename: 'D:\a\1\packages\squirrel.windows.1.9.1\tools\Squirrel.exe' arguments: '--releasify $(build.ArtifactStagingDirectory)\nuget\XXX.$(Build.BuildNumber).nupkg --releaseDir $(build.ArtifactStagingDirectory)\drop' workingFolder: '$(build.ArtifactStagingDirectory)\drop'

Thanks for your help

lightlike commented 4 years ago

That command should work.

The next thing I would test is either the nupkg or try --no-msi (at least I think that I had a reason to put that in the command). The problem might also be the squirrel.exe in the nuget package. Maybe test that too.

Maybe it would be a good idea to download the build-output and test this on your computer. That should be much faster. It might also be a good idea, if you do the packaging and the releasifying in a release pipeline. It is much faster that way, if you do not have to build the project every time.

I would also advise against project packaging, if you are using that. Some nuget-stuff might conflict with squirrel. The nuspec I use is this one.

Rodric75 commented 4 years ago

Never used azure pipelines before, can either/both of you post a bit more guidance? yaml samples / steps / youtube explanation / blog walkthrough / consulting agreement? Pretty much anything helps. @lightlike @greengumby

lightlike commented 4 years ago

@Rodric75

I mostly use the overlay instead of YAML. But I could imagine it is fairly easy to generate one from that.

I split the work into two Pipelines

  1. Normal Release Build Configuration, pushing the relevant files as artifacts
  2. Release Configuration with the following steps based on the Build Artifacts of 1

Release Steps

Most of this should be pretty self explanatory but the command I use for the releasify is:

--releasify $(System.DefaultWorkingDirectory)\Release\Drachenhorn.$(Version).nupkg -r $(System.DefaultWorkingDirectory)\Output -n "/a /f $(pfx.secureFilePath) /p $(Sign.Password)" --framework-version=net461 --no-msi

If you want to see the project and the result. You can find that here.

I first had the releasify inside the build itself but that was far to annoying to test because every time it had to rebuild everything and pull all the nuget packages for net-standard which took some time. But now I can no longer generate any Delta-Packages until I get my own agent up and running.

The most annoying part is testing and fixing anything that goes wrong. But that just takes time and many tries.

Rodric75 commented 4 years ago

Having some issues extracting the squirrel zip file? Can you show the yaml for those 2 steps?

Sent from my iPad

On Jan 24, 2020, at 4:24 PM, DanielN notifications@github.com wrote:



@Rodric75https://github.com/Rodric75

I mostly use the overlay instead of YAML. But I could imagine it is fairly easy to generate one from that.

I split the work into two Pipelines

  1. Normal Release Build Configuration, pushing the relevant files as artifacts
  2. Release Configuration with the following steps based on the Build Artifacts of 1

[Release Steps]https://user-images.githubusercontent.com/12970722/73107369-f79b0080-3efd-11ea-9944-8cd5d310f261.png

Most of this should be pretty self explanatory but the command I use for the releasify is:

--releasify $(System.DefaultWorkingDirectory)\Release\Drachenhorn.$(Version).nupkg -r $(System.DefaultWorkingDirectory)\Output -n "/a /f $(pfx.secureFilePath) /p $(Sign.Password)" --framework-version=net461 --no-msi

If you want to see the project and the result. You can find that herehttps://github.com/Drachenhorn-Team/Drachenhorn.

I first had the releasify inside the build itself but that was far to annoying to test because every time it had to rebuild everything and pull all the nuget packages for net-standard which too some time. But now I can no longer generate any Delta-Packages until I get my own agent up and running.

The most annoying part is testing and fixing anything that goes wrong. But that just takes time and many tries.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/Squirrel/Squirrel.Windows/issues/1580?email_source=notifications&email_token=AF6WXN2PAOO3ZW4LJKXP363Q7NS7PA5CNFSM4KI2A73KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJ4I2YI#issuecomment-578325857, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AF6WXN2I2XKNUC4OWOI3KGTQ7NS7PANCNFSM4KI2A73A.

lightlike commented 4 years ago

The Squirrel.zip is just one, that I packed from the release of Squirrel here on Github.

The dowload is simply a "secure file download" task:

steps:
- task: DownloadSecureFile@1
  displayName: 'Download Squirrel'
  inputs:
    secureFile: Squirrel.zip

The unzip is something you can get from the marketplace and just takes the output path from the download task and unzips based on that.

steps:
- task: ExtractFiles@1
  displayName: 'Extract Squirrel'
  inputs:
    archiveFilePatterns: '$(Squirrel.secureFilePath)'
    destinationFolder: '$(System.DefaultWorkingDirectory)/Squirrel'
MovGP0 commented 4 years ago

I am wondering if I can just use Azure DevOps integrated NuGet feed for updates. This way, there would be no changes needed to the build pipeline.

lightlike commented 4 years ago

I don't think that would work, as you would need to also download the RELEASE textfile from the same base url and I do not think that the nuget feed would allow non-nupkg files. I might work if you wrote your own UpdateManager or do some workaroundy stuff.

MovGP0 commented 4 years ago

Then don't use a RELEASE textfile. The NuGet feed itself should provide enough information to support the update process.

uygary commented 4 years ago

@MovGP0 I bet it could be made work, but it'd be a breaking change for all the production apps that currently use Squirrel. Feel free to create a fork that does exactly what you need though.

lightlike commented 4 years ago

@MovGP0 As I said, that could work but you would need to create your own UpdateManager or at lease overload the download functionality of the existing ones. Feel free to do that.

@uygary This could also work in default squirrel if you make it a new UpdateManager like the GitHubUpdateManager. The setup does not need any nupkg-Files so I don't see any problem with that. But I do not know if it would be accepted though.

gabrielbarceloscn commented 3 years ago

Here's my WORKING build pipeline using Azure DevOps.

Important facts:

  1. It's using Squirrel 2.0.1
  2. I've installed an extension named Assembly Info Reader to get Assembly Version.
  3. I've lost so much time with problems caused by slash/backslash.
  4. Working directory is important when running power shell and command line operations.
  5. I´m storing binary in an Azure Blob Storage.
  6. Before build a new installer, I need to download previous version, along with the RELEASES file, and .NUPKG to create a DELTA and append to RELEASES file, new version information.
  7. Nuget tools are already installed in this Windows Hosted Image.
  8. I´m using Azure CLI to invoke az storage blob commands. I´m in an authenticated connection inside Azure DevOps.
  9. I´m using a MONOREPO strategy. Modules folder have 5 distinct projects. Then I´m using path filters with my continuous build process.
  10. Folder structure became a bit more complex because Azure Blob strategy. When downloading, i needed to replicate folder structure like: bin/posdesktop/production/.
trigger:
 branches:
   include:
     - main
 paths:
   include:
     - modules/frontendDesktop/src/*
   exclude:
     - modules/frontendDesktop/docs
     - modules/frontendDesktop/img
     - modules/frontendDesktop/dist
     - modules/frontendDesktop/tools
     - modules/frontendDesktop/tests
     - modules/frontendDesktop/installer

pool:
  vmImage: 'windows-latest'

variables:
  solution: 'modules/frontendDesktop/ErpFrontendDesktop.sln'
  projectFolder: 'modules/frontendDesktop/src/pos.winforms'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:
- task: AssembyInfoReader@2
  displayName: 'Get Assembly Info'
  inputs:
    searchPattern: '$(projectFolder)/Properties/AssemblyInfo.cs'

- task: NuGetCommand@2
  displayName: 'NuGet Restore'
  inputs:
    restoreSolution: '$(solution)'

- task: VSBuild@1
  displayName: 'Build'
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: VSTest@2
  displayName: 'UI Tests'
  inputs:
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: PowerShell@2
  displayName: 'Create folder \PosDesk\Prod'
  inputs:
    targetType: 'inline'
    workingDirectory: '$(projectFolder)'
    script: "mkdir -p bin/posdesktop/production"

- task: AzureCLI@2
  displayName: 'Download previous installer'
  inputs:
    azureSubscription: 'Azure-Subscription-Name'
    scriptType: 'ps'
    scriptLocation: 'inlineScript'
    inlineScript: '
      az storage blob download-batch 
        --source appreleases
        --pattern posdesktop/production/*
        --destination bin 
        --account-key $(stor_releases_key) 
        --account-name sterppublic'
    workingDirectory: '$(projectFolder)'

- task: PowerShell@2
  displayName: 'Create folder \ReleasePublish'
  inputs:
    targetType: 'inline'
    workingDirectory: '$(projectFolder)'
    script: "mkdir -p bin/releasePublish"

- task: PowerShell@2
  displayName: 'Copy to Release Publish'
  inputs:
    targetType: 'inline'
    workingDirectory: '$(projectFolder)'
    script: "mv bin/posdesktop/production/* bin/releasePublish"

- task: CmdLine@2
  displayName: 'Create .nupkg'
  inputs:
    script: 'nuget pack BuildPipeline\PosWinforms.nuspec 
                -Version $(AssemblyInfo.AssemblyVersion) 
                -Properties Configuration=Release 
                -OutputDirectory bin\releasePkg
            '
    workingDirectory: '$(projectFolder)'

- task: CmdLine@2
  displayName: 'Create Installer'
  inputs:
    script: '..\..\packages\squirrel.windows.2.0.1\tools\squirrel 
                --releasify bin\releasePkg\PosWin.$(AssemblyInfo.AssemblyVersion).nupkg 
                -r bin\releasePublish 
                --setupIcon Icon.ico 
                --no-msi'
    workingDirectory: '$(projectFolder)'
    failOnStderr: true

- task: PublishBuildArtifacts@1
  displayName: 'Publish Installer'
  inputs:
    PathtoPublish: '$(projectFolder)/bin/releasePublish'
    ArtifactName: 'squirrel_release'
    publishLocation: 'Container'
lobbo232 commented 5 months ago

I did something similar to @gabrielbarceloscn except I used a release pipeline instead so I can avoid generating deltas for every build and instead only create deltas for a release.

My build pipeline creates the NuGet package used by squirrel in the release pipeline. My Releases are stored in a blob storage folder. I have put the contents of the Squirrel package in my agent/_work/_tool folder on the self-hosted agent so it can be accessed without downloading secure files or installing packages. image

The first thing I do is use PowerShell to get the name of the package in the artifact drop and store it as a pipeline variable. Originally I was renaming the package to something simple like ABC.nupkg so I can look it up easily later, however Squirrel seems to use the file name to get the Semantic version number, not the package version, so this didn't work. Keep the package named appropriately.

# find the .nupkg file in the artifact folder
$packageFile = Get-ChildItem `
              -Filter *.nupkg `
              -Path "$(System.DefaultWorkingDirectory)\developmentdrop\developmentdrop" |
           ForEach-Object { $_.fullname } |
           Select-Object -First 1

# create a variable with the full path to the file
Write-Host "##vso[task.setvariable variable=packageFile]$packageFile"

Then I download my previous releases/deltas (including the RELEASE text file) to temp storage on my self-hosted agent via Azure CLI task. (Note: $(Releases) is a pipeline variable to the blob storage folder containing the releases).

az storage blob directory download -c releases -s $(Releases) -d "$(Agent.TempDirectory)" --account-name REDACTED --account-key REDACTED --recursive

Finally I can run squirrel like this with another PowerShell task

$(Agent.ToolsDirectory)\Squirrel\squirrel --releasify $(packageFile) --releaseDir $(Agent.TempDirectory)\Release--no-msi

Do what you want with the releases after that. I put them back in blob, and attempt to remove some of the older deltas and full releases to avoid slow delta installs.

Here Some reasons I got the --releasify exited with code 1 error:

  1. Make sure you're not accidentally running your task on an azure hosted agent. Remember to pick your own self-hosted agent (lost too long to this... 🤦‍♂️)
  2. Invalid characters in file path. I was trying to get the package with *.nupkg. It requires the full name
  3. Squirrel requires the semantic version in the file name, so keep the name as the build creates it. Don't rename it.
  4. Make sure all this is done in the same Task/Step in the release. If you split it up you will have to put your releases/target to something else other than the _temp folder as it get's cleared between steps on your agent.