Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.

If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!

ProGet as ClickOnce publish target?



  • We're looking into using ProGet as a publish target for our ClickOnce applications. Is there an established pattern for doing this? Where would they best be pointed - a true Feed, or an Asset Directory?


  • inedo-engineer

    I'm not so familiar with ClickOnce publish targets, but my understanding is that ClickOnce is deployed to an ordinary web-based file directory, like a site in IIS that has "file browsing" enabled or something?

    IF so, then I think Asset Directory would work. That's kind of like that, and is meant for general files. Feeds require a special API to access.

    Let us know how it goes.



  • The person building this seemed to be having some luck with the Assets, he needed to use the api endpoint exposed in the download link area. I'll follow up when i get more info.



  • We had a fantastic support call with Alex and Rich, and they pointed us at this: https://docs.microsoft.com/en-us/visualstudio/deployment/server-and-client-configuration-issues-in-clickonce-deployments?view=vs-2019#use-third-party-web-servers

    we haven't tried anything yet, but if anyone else comes along here, maybe it'll help.



  • Just thought I'd drop in and describe where we ended up with this. It works for us, YMMV.

    This is running in the context of a Jenkins deploy run, but the concepts should apply to most other use cases.

    There are a lot of env vars floating around in all of this; i know it's not ideal, but it's really the easiest way to move values around in Jenkins without going crazy with OO classes that are really hard to get working in the Jenkins context. I have recently come up with a pattern to store more complex objects in env vars as json strings, and convert them when needed.

    Happy to answer any questions from anyone interested in using this admittedly obscure functionality.

    // this is called from vars/deploy.groovy when appropriate
    clickOnceDeploy([clickAppName:env.clickOnceName, clickAppPath:env.clickOnceDir, targetEnv:targetMap.key])
    
    // defined in vars/deploy.groovy
    def clickOnceDeploy(HashMap clickParms) {
      // find the zip in the download folder
      String dlFolder         = "${WORKSPACE}/${env.packageDownloadDir}"
      String clickOncePackage = "${dlFolder}/${env.releasePath}/${clickParms.clickAppPath}.zip" 
      String targetEnv        = clickParms.targetEnv
      String zipFileName      = "${clickOncePackage.replace('.zip', '')}-${targetEnv}.zip"
    
      // extract the zip - select the target env folder
      unzip zipFile: clickOncePackage, glob: "${targetEnv}/**", quiet: true
    
      // zip that folder up, use powershell to get the dir included
      pwsh "Compress-Archive -Path ${targetEnv} -DestinationPath ${zipFileName} -Force"
    
      // publish it to proget asset dir
      HashMap publishParams = [assetDir:"${clickParms.clickAppName}", zipFilePath:zipFileName]
      addToInfoMessages("Publishing ClickOnce App: ${clickParms.clickAppName}/${targetEnv}")
      publish.publishProGetAssetFromZip(publishParams)
    
    // defined in vars/publish.groovy
    def publishProGetAssetFromZip(HashMap publishParams) {
      // check for required params
      assert publishParams.assetDir != null
      assert publishParams.zipFilePath != null
    
      // sane defaults
      publishParams.get('progetBase', env.progetUrl)
      publishParams.get('overwrite', true)
      publishParams.get('format', 'zip')
    
      // build the api endpoint
      String progetAssetImportApi = "endpoints/${publishParams.assetDir}/import/?format=${publishParams.format}&overwrite=${publishParams.overwrite.toString()}"
      String assetUrl = "${publishParams.progetBase}/${progetAssetImportApi}"
    
      // need to pass the api token, so pull it from the jenkins cred store
      withCredentials([string(credentialsId: 'proget-api-key', variable: 'token')]) {
        retry(3) {
          httpRequest httpMode: 'POST', 
            url: assetUrl, 
            uploadFile: publishParams.zipFilePath,
            customHeaders: [[maskValue: true, name: 'X-APIKey', value: token]],
            ignoreSslErrors: true,
            responseHandle: 'NONE',
            contentType: 'APPLICATION_OCTETSTREAM',
            wrapAsMultipart: false,
            quiet: true
        }
      }
    
      addToInfoMessages("Published to ${publishParams.progetBase}/assets/${publishParams.assetDir}")
    }
    

Log in to reply
 

Inedo Website HomeSupport HomeCode of ConductForums GuideDocumentation