question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

VSTS Capitalizes all build variables

See original GitHub issue

Description

When adding environment variables in VSTS a variable added to the Build Definition like HelloWorld will be added to the environment as HELLOWORLD making it harder to discover and impossible to ensure that the correct variable name is used when generating the json file and thus the Secrets Class.

Reproduction Steps

Create a build definition for a UWP project in App Center or any build definition in VSTS with a Windows Client (I believe this may also be occurring on the Mac agent with VSTS). Add variables to the build definition. All variables added to the environment are capitalized.

Expected Behavior

If a variable is expected to be in the json as HelloWorld, we need a way of compensating for environments that prevent us from trusting the variable name is in the format we expect.

Actual Behavior

Environment variables are either undiscovered or discovered incorrectly resulting in capitalization errors that cause the build to fail.

Environment

  • OS: Windows
  • IDE: n/a
  • BuildTools Version: all
  • IDE Version: n/a
  • CI Environment: App Center - Windows / VSTS

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:14 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
stevenenglandcommented, Jan 2, 2019

Azure Pipelines (formerly VSTS) actually has a number of problems when creating builds with Visual designer. One of the problems in Azure Pipelines is that when you use the naming convention Secret_VarName, it treats the variable as if it is actually a secret hiding it from the environment. Interestingly, this isn’t 100% accurate, as sometimes it works as expected though it generally just capitalizes the variable if it adds it at all. Another problem is that if you mark a variable as a protected variable (preventing someone from seeing the value), it is also hidden from the environment making it impossible to use. As you will see in the snippet below however, with a YAML build definition these problems go away as you can specify whatever you want, and inject the environment variables you need at the build step.

- task: XamariniOS@2
  displayName: 'Build Xamarin.iOS solution **/*.iOS.csproj'
  inputs:
    solutionFile: '**/*.iOS.csproj'
    configuration: $(BuildConfiguration)
  env:
    Manifest_AADClientId: $(ClientId)
    Secret_ClientId: $(ClientId)
    Secret_AppCenterSecret: $(AppCenterSecret)
    Secret_Tenant: $(Tenant)
    Secret_AppServiceEndpoint: $(AppServiceEndpoint)

For me the only way to get things working using a yaml file was to override the BuildHostSecretPrefix (in the .csproj file)

<PropertyGroup>
    <BuildHostSecretPrefix>SAFE_</BuildHostSecretPrefix>
 </PropertyGroup>

Then the variables were recognized:

- task: XamarinAndroid@1
  displayName: 'Build Xamarin.Android project **/*Droid*.csproj'
  inputs:
    projectFile: '**/*Droid*.csproj'
    outputDirectory: '$(build.binariesdirectory)/$(BuildConfiguration)'
    configuration: '$(BuildConfiguration)'
    msbuildArguments: '/verbosity:detailed'
  env:
    SAFE_APPCENTER_IOS_SECRET: $(AppCenter_iOS_Secret)
    SAFE_APPCENTER_ANDROID_SECRET: $(AppCenter_Android_Secret)
    SAFE_APPCENTER_WINDOWS_SECRET: $(AppCenter_Windows_Secret)
    SolutionDir: $(Build.Repository.LocalPath)
2reactions
dansiegelcommented, Oct 9, 2018

@xyashapyx if you need to use the marketplace plugins, you almost certainly should use Azure Pipelines instead of App Center. Though you should remember that you have full access to install anything you need to on the build host with App Center, so if you can script it, you can do it.

Azure Pipelines (formerly VSTS) actually has a number of problems when creating builds with Visual designer. One of the problems in Azure Pipelines is that when you use the naming convention Secret_VarName, it treats the variable as if it is actually a secret hiding it from the environment. Interestingly, this isn’t 100% accurate, as sometimes it works as expected though it generally just capitalizes the variable if it adds it at all. Another problem is that if you mark a variable as a protected variable (preventing someone from seeing the value), it is also hidden from the environment making it impossible to use. As you will see in the snippet below however, with a YAML build definition these problems go away as you can specify whatever you want, and inject the environment variables you need at the build step.

- task: XamariniOS@2
  displayName: 'Build Xamarin.iOS solution **/*.iOS.csproj'
  inputs:
    solutionFile: '**/*.iOS.csproj'
    configuration: $(BuildConfiguration)
  env:
    Manifest_AADClientId: $(ClientId)
    Secret_ClientId: $(ClientId)
    Secret_AppCenterSecret: $(AppCenterSecret)
    Secret_Tenant: $(Tenant)
    Secret_AppServiceEndpoint: $(AppServiceEndpoint)

@rspaulino I actually do use App Center for most of my builds. From an economic standpoint though it is sometimes more desirable to use Azure Pipelines as you may only want to pay for one or two concurrent builds with Azure Pipelines, instead of paying for one in Azure Pipelines and another in App Center. I’m sure at some point they will ultimately merge these build pipelines since Azure Pipelines is actually what App Center is using behind the scenes, and the App Center team actually maintains the MacOS build hosts for Azure Pipelines.

As for a work around for UWP what I found was that I had to do a post-clone script. There were actually a couple of problems I ran into while building UWP with App Center:

  1. Is the Capitalization issue as noted by this issue
  2. When using an authenticated Package Feed such as an Azure Artifacts Package Feed, the NuGet restore task would not pick up the NuGet.config and thus would fail to restore packages for the project.
  3. Also when using an authenticated Package Feed, the docs say to place a NuGet.config in the root directory. The problem with this is that you cannot/should not have the auth token in the config in Source Control for security reasons. This means that you are either risking accidently checking in a file that you have modified with your auth token, or that you have a templated file that Visual Studio/NuGet will automatically pick up during local development, and will fail to properly use since it’s templated. Yet another issue I found was that the App Center team didn’t coordinate between UWP and iOS/Android as to how to template the NuGet.config for automatic Regex replacement.

The work around I had for these issues was as follows:

if($env:PackageFeedPat) {
    # NuGet config named template.config to prevent Visual Studio from picking it up for local development
    (Get-Content .\build\template.config) `
      -replace '%PackageFeedPat%', "$env:PackageFeedPat" |
    Out-File NuGet.config
    Write-Host "Generated NuGet.config"
}
else {
    Write-Warning "There is no environment variable defined for the Package Feed"
}

Write-Host "Downloading latest nuget.exe"
Invoke-WebRequest -Uri https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\nuget.exe

Write-Host "Performing NuGet Restore"
.\nuget.exe restore -ConfigFile .\NuGet.config

# Hack... Windows client capitalizes all environment variables wrecking the Mobile.BuildTools
$secrets = @{
    AppCenterSecret = "$env:AppCenterSecret"
    ApplicationID = "$env:ApplicationID"
    TenantID = "$env:TenantID"
    ReturnUri = "$env:ReturnUri"
    ApiResourceUri = "$env:ApiResourceUri"
    ApiResourceId = "$env:ApiResourceId"
    TenantUrl = "$env:TenantUrl"
    SyncfusionLicense = "$env:SyncfusionLicense"
}

$secrets | ConvertTo-Json | Out-File .\src\MyProject\secrets.json
Read more comments on GitHub >

github_iconTop Results From Across the Web

Build Variables not added or added in ALL CAPS
The following demo app builds perfectly on App Center, but cannot currently build in VSTS: https://github.com/dansiegel/AppCenter.DemoApp.
Read more >
Define variables - Azure Pipelines
All variables are strings and are mutable. The value of a variable can change from run to run or job to job of...
Read more >
Use predefined variables - Azure Pipelines
A comprehensive list of all available predefined variables.
Read more >
Uppercase or lowercase for global variables?
Then I encountered an issue that a global variable should not begin with a lowercase character although it did not result in any...
Read more >
Dump all environment variables during a TFS VSTS Build
Having a list of all Environment Variables value of the agent during the build is an invaluable feature. Before moving to writing a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found