Set environment variable - asp.net-core

I need some environment variables for my project. I placed it in the launchSettings.json as described here. I know it is VS-specific feature but it works fine with dotnet run cli command and it looks good for me. However it doesn't work for dotnet publish command. How should I set environment variables for production? I'd like to place it inside the project without using powershell, docker etc.

The entire purpose of using environment variables is so that they are not part of your project. If you want them to be in your project, then just use appsettings.json. That's what it's for.

Related

How to set process.env.var in devops Azure pipeline

I have a task to deploy aspnet core React application to 2 different environments: development and production environments. Each of this environments should be configured separately.
I use Azure devops for CI/CD
AspNet project contains following commands for building application
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />
I use adal for authorization that is why I have to pass some secret variables that are different for Dev and Prod
const adalConfig = {
tenant: process.env.REACT_APP_TENANT,
clientId: process.env.REACT_APP_CLIENT_ID,
redirectUri: process.env.REACT_APP_REDIRECT_URI,
In Azure devops I set params with command:
echo ##vso[task.setvariable variable=REACT_APP_TENANT;isOutput=true]c00000-00ce-000-0f00-0000000004000
in the azure devops I have next standard commands for aspnet core build app
.Net core installer
Resore
run command (to set env variables)
Build
publish
Issues:
Environment variable is not set.
I even don't know how to build another artefact for production, but not for development.
Maybe you already had task to deploy core react app to 2 different environments? Or please give advice if I need to change deployment strategy at all.
The only solutions what I found is to use .env file but I have to commit this file to git - to deploy it from master. And I still don't know how to use different files for dev and prod.
TLDR;
You have isOutput=true in your task.setvariable command. This only sets a variable in Pipelines engine, to be available to other steps, but doesn't actually map to an env variable. Remove isOutput and you shall see REACT_APP_TENANT env variable.
But only in the following steps - the env variable is not immediately accessible in the same pipeline step.
You can define variables at pipeline level if you know their values upfront - that should simplify things. task.setvariable is more useful for dynamic variables.
If you need different process (or a different set of variables) for different environments, I recommend using multistage YAML pipelines or classic Releases. They both allow for setting up different stages, each with their set of variables.
Long story
We need to distinguish two separate processes:
Deployment pipeline that's executed on CI agent
Web application that may be hosted in many different ways - Azure Web Apps, self hosting, docker/k8s, etc.
Doing echo ##vso[task.setvariable ...] sets the variable in the pipeline (1.).
The place where reading variables takes place (like tenant: process.env.REACT_APP_TENANT) isn't that obvious. If it's nodejs server-side code, it'll be executed in 2. If it's a part of some build script, it'll be read in 1.
React is tricky, because:
It react behaves differently in development and release mode. In Release mode, during the build phase, the whole client-side code is compiled down to a static JS file. So the env variables you set in your pipeline should work.
It cannot simply access any env variable (to protect you from exposing your server env variables on client browser by accident). If using create-react-app (which is what ASP.NET React App does by default), you have to prefix env variables with REACT_APP_ to use them. If using Webpack directly, you'll need some plugin for this.

Unable to change environment variable

I am having trouble changing the publish variable within web.config because it amounts to nothing.
Once I set the variable in web.config to Development, for example, when I launch the application, it still says that the environment variable is Production.
As you can see below, the web.config states that I have set the variable to Development.
I am out of ideas and genuinely unsure whether variables can be set this way anymore.
Looking at your first screenshot, it looks like you are running your application from the command line, probably using dotnet run. In this case, you should note that the web.config is completely ignored.
The web.config is only to configure IIS for when you actually deploy your application on IIS. If you run it in any other way, the web.config is not being used and you will have to configure the environment in a different way.
If you want to run the application from the command line, you can set the environment variable using set:
set ASPNETCORE_ENVIRONMENT=Development
dotnet run
If you use a standard ASP.NET Core template, there should also be a launchSettings.json file which configures the default launch settings. If you specify the environment there, dotnet run will automatically pick it up when you run the application from the application’s root directory.

How can I pass MSDeploy-style parameters to MSBuild via the commandline?

I am setting up TeamCity to deploy our Website Project application (using a *.wdproj) and Web Deploy application to IIS.
I have a build configuration that uses MSBuild.exe with the MSDeployPublish to build and then deploy the application.
We now want to get the application to deploy to multiple target environments, therefore need a way to supply different settings based on the target environment.
I have added a parameters.xml file to the Web Deployment Project, and have verified that the parameters set in here are making all the way through the target IIS server and being correctly applied - great!
Now what I want to do is have different parameter settings per environment. I was hoping I could use something like the MSDeploy.exe -setParam argument to specify different values for each environment, however I can find no way to get my parameter values into MSBuild via the commandline.
I suspect I might need to do one of the following:
Split MSBuild and MSDeploy into separate build steps.
Configure a task somewhere in the pipeline to take 1 of n versions of parameters.something.xml and move it into parameters.xml so it gets picked up by the rest of the pipeline.
I'm looking for the simplest way to move ahead at this point, any suggestions welcome.
For reference, here is the command I'm experimenting with now:
msbuild /target:MSDeployPublish MySite_deploy.wdproj /P:Configuration=Debug
/P:DeployOnBuild=True /P:DeployTarget=MSDeployPublish
/P:MsDeployServiceUrl=www.myserver.com:8172/MsDeploy.axd
/P:AllowUntrustedCertificate=True /P:MSDeployPublishMethod=WMSvc
/P:CreatePackageOnPublish=True /P:UserName=MyUser /p:Password=MyPassword
/P:DeployIisAppPath=www.myserver.com/MySite
/P:ServerURL=http://www.tryingtoforcethis.com
It's working beautifully except the value for ServerURL, which is a parameter I've defined in my parameters.xml, is not making its way into the target site. The default I specified in parameters.xml, however, is. So I know that the parameters are working, I just can't figure out how to add them to the msbuild commandline.
Well, I think the short answer is that with MSBuild 4.0 and VS2010, you can't just pass arbitrary parameters into MSDeployPublish from the call to MSBuild.
I found these posts helpful:
http://forums.iis.net/t/1167657.aspx/1 - Ming Chen's comments
http://www.hanselman.com/blog/TinyHappyFeatures3PublishingImprovementsChainedConfigTransformsAndDeployingASPNETAppsFromTheCommandLine.aspx - the comments from Richard Szalay at the bottom
After reading these, and sifting through the Microsoft.Web.Publishing.targets file for some time trying to find a "way in", I finally settled on having multiple copies of Parameters.xml in my project folder in source control, labelled according to their environment eg:
Parameters.Test.xml
Parameters.Staging.xml
Parameters.Live.xml
Then, prior to the package and deploy, I just copy one of these files into Parameters.xml and it gets picked up by the rest of the pipeline - done!
BTW I had a temporary problem getting the parameters.xml copy and subsequent cleanup to work within a single MSBuild.exe call due to what seems to be some sort of file access issue, I've detailed it here:
MSBuild.exe Copy task not working properly unless a version of the file already appears in target
To answer your question, the parameterization of your command line is not a concern of MSBuild. Instead, you should utilize external tools. For example, if you run your msbuild command from a batch file you could pass the parameters to the batch file and run it for each environment with different parameters. Another approach is to use a build system like TeamCity or VSTS and utilize their parameterization mechanism. Adapted for the VSTS or TFS, your command could look like this:
msbuild MySite_deploy.wdproj /target:MSDeployPublish /p:Configuration=Debug
/p:DeployOnBuild=True /p:MsDeployServiceUrl=$(IIsHostNameIp)
/p:AllowUntrustedCertificate=True /p:MSDeployPublishMethod=WMSvc
/p:CreatePackageOnPublish=True /p:UserName=$(IIsUserName) /p:Password=$(IIsPassword)
/p:DeployIisAppPath=$(IIsSite)
In addition, I would suggest some clean up for your origianl command line:
Using both /p:target and /p:DeployTarget is redundant. Any one of them is enough. Also it could be replaced with /p:WebPublishMethod.
For /p:MSDeployServiceUrl it is enough to only provide a DNS name or IP. the port and the Url is automatically derived from the /p:MSDeployPublishingMethod=WMSVC.
The custom parameter /p:ServerURL is unknown and won't be mapped anywhere.
msbuild.exe {build-script.proj} /property:{someParameter=someValue}
In your build script you can use $(someParameter) as a variable

Running rsvars.bat before Teamcity build starts

I have a C++ Builder 2010 project that's being built using TeamCity. I noticed some strange errors and after reading up on them I understand that I have to set a few variables located in rsvars.bat. I would like the build script to execute the bat file to set up the environment before performing the actual build. How do I best accomplish this?
Can I just use a <exec /> command at the very beginning of the file or is there a better way?
One way would be to run wrap the build in a script that calls rsvars.bat AND build commands. That would make the variables survive during the execution of the build.
But since I use TeamCity I like it to be a real msbuild step and not msbuild wrapped in something else. I was thinking of having the buildscript setting the variables from rsvars.bat into Machine or User at the start of the build and then remove them at the end, not nice though.
I finally just went with just adding the configurations to the Build Agents environment configuration in TeamCity and keeping installation paths identical between agents.
You can create a new build step and then specify a custom build step order so a new build step will be the first one.
See Configuring Build Steps
Add them as Build Parameters -> Environment Variables (in the build configuration), straight forward and generally works. The build parameter/environment variables will be setup automatically as environment variables on the build agent running the job.
You can then make a template of the build and reuse it.
Assumes that the 'paths' are the same on all build agents, which is generally the case. If not your suggestion of doing it by build agent is the way to go.

Using a variable obtained using a pre-build shell command to set an option for the Maven build in Hudson

I have a Hudson job that runs a maven goal. Before this maven goal is executed I have added a step to run before the build starts, it is a shell script that obtains the version number that I want to use in the 'Goals and options' field.
So in my job configuration, under Build Environment I have checked the Configure M2 Extra Build Steps box and added a shell script before the build. The script looks like this:
export RELEASE={command to extract release version}
echo $RELEASE
And then under the Build section I point to my 'root pom'. In the Goals and options I then want to be able to do something like this:
-Dbuild.release.version=${RELEASE} deploy
Where build.release.version is a maven property referenced in the POM. However since the shell doesn't seem to make its variables global it doesn't work. Any ideas?
The only one I have is to install the Envfile plugin and get the shell script to write out the RELEASE property to a file and then get the plugin to read the file, but the order in which everything is run may cause problems and it seems like there must be simpler way...is there?
Thanks in advance.
I recently wanted to do the same, but AFAIK it's not possible to export values from a pre-build shell to the job environment. If there is a Hudson Plugin for this I've missed it.
What did work, however, was a setup similar to what you were suggesting: having the pre-build shell script write the desired value(s) to a property-file in the workspace, and then using the Parametrized Trigger Plugin to trigger another job that actually does the work (in your case, invoke the Maven job). The plugin can be configured to read the parameters it passes from the property file. So the first job has just the shell script and the post-build triggers, and the second one does the actual work, having the correct parameters available as environment variables.
General idea of the shell script:
echo "foo=bar
baz=`somecmd`" > build.properties
And for your Goals and options, something like:
-Dbuild.release.version=${foo} deploy
Granted, this isn't as elegant as one might want but worked really well for us, since our build was broken into several jobs to begin with, and we can actually reuse the other jobs that the first one triggers (that is, invoke them with different parameters).
When you say it doesn't work, do you mean that your RELEASE variable is not passed to the maven command? I believe the problem is that by default, each line of the shell script is executed separately, so environment variables get lost.
If you want the entire shell script to execute as if it was one script file, make the first line:
#!/bin/sh
I think this is described in the Help information alongside the shell script build step (and if I'm wrong, that's a good place to look for the right syntax).