I am trying to use the "az pipelines variable-group variable create ..." command to create a variable which references a different variable. e.g.
az pipelines variable-group variable create --project MyTestProject --
group-id 15 --name ‘ApplicationName’ --value 'TestApp-$(env)'
where the variable “env” is defined in a variable-group within the same project library.
When I run the command above it gives the error:
“Failed to load python executable” “exit /b 1”.
Despite an error being generated the variable is created; in the example above the variable 'ApplicationName' has the value 'TestApp-$(env', the trailing bracket character, ")", is missing and seems to be causing the problem.
The dollar sign, "$", and/or the opening bracket character "(" don't generate any error when used without the closing bracket ")".
I have tried escaping the closing bracket character with backslashes "\" and caret "`" characters but couldn't find any combination that would create the desired variable value, "TestApp-$(env)".
Could someone tell me how to escape the closing bracket so the variable is correctly created within the variable group.
I am running the following versions of az:
azure-cli 2.0.73
command-modules-nspkg 2.0.3
core 2.0.73
nspkg 3.0.4
telemetry 1.0.3
Extensions:
azure-devops 0.12.0
Python (Windows) 3.6.6
Many Thanks,
Gary
I have finally managed to figure out how to escape a variable whose name itself contains a different variable name. By calling the az cli command and wrapping the variable value in double quotes and a single quote, the variable is correctly created in DevOps:
pipelines variable-group variable create --project MyTestProject -- group-id 15 --name ApplicationName' --value '"TestApp-$(env)"'
DevOps-LibraryVariable-screenshot
As a further expansion on this topic I had a need to pass the value as a variable. My source was in a key value pair. In this case I used the following.
$key = $var.Key
$value = '"{0}"' -f $var.Value
az pipelines variable-group variable update --group-id $groupId --org $org --project $project `
--name $key --value $value
It depends on your OS and tools.
For example, in Windows OS, you can get environment variable with %variable_name%. So, the following would be right:
az pipelines variable-group variable create --project keyvault --group-id 1 --name "ApplicationName" --value "TestApp-%java_home%"
However, in PowerShell, you can get environment with "$env:variable_name". So, the following would be right:
az pipelines variable-group variable create --project keyvault --group-id 1 --name "ApplicationName2" --value "TestApp-$($env:java_home)"
Update:
So, in Azure Pipeline, you can use group variables as following:
pool:
name: Hosted VS2017
demands:
- msbuild
- visualstudio
- vstest
variables:
- group: vargroup
steps:
- task: AzureCLI#1
inputs:
azureSubscription: 'CSP Azure (e5b0fcfa-e859-43f3-8d84-5e5fe29f4c68)'
scriptLocation: 'inlineScript'
inlineScript: |
echo the variable var1:%var1%
I have a variable group:
And you can see that: echo the variable var1:%var1% will be echo the variable var1:value1
I'm starting a python script with supervisord on a linux debian platform. The user selected for executing the script shall depend on the value of an environmental variable. How can i make the field "user=" in a supervisord configuration file conditional?
First, I have added to the supervisor.service an environmental variable SPECIALUSER=myuser (file /lib/systemd/system/supervisor.service)
[Service]
ExecStart=/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/bin/supervisorctl -c /etc/supervisor/supervisord.conf $OPTIONS reload
KillMode=process
Restart=on-failure
Environment=SPECIALUSER=myuser
Then I try to use the variable inside my supervisord.conf file:
[program:myprogram]
command=python myscript.py
user="if [ %(ENV_SPECIALUSER)s = myuser]; then root; else standarduser; fi"
But I get the following error when i try to reread the supervisord.conf
ERROR: CANT_REREAD: Invalid user name "if [ myuser = myuser ]; then root; else standarduser; fi" in section 'program:myprogram' (file: '/etc/supervisor/conf.d/supervisord.conf')
The environmental variable is interpreted correctly but the bash script, not.
I thought about entering the name of the user directly in the variable Environment=SPECIALUSER=root, but the environmental varialble is not always available.
If the environment variable is set to SPECIALUSER=myuser, I expect supervisor.d to interpret my program as
[program:myprogram]
command=python myscript.py
user=root
In all other cases as
[program:myprogram]
command=python myscript.py
user=standarduser
According to the documentation the user parameter value is never "interpreted" or sent to a shell. This means that it tries to use the entire value as the username.
http://supervisord.org/configuration.html#program-x-section-settings
All parameters aren't interpreted or sent to a shell. This means that you can't insert conditionals generally in parameters in your supervisord.conf.
If your goal is to just use different users on say different platforms or one for development and another on a deploymentserver I suggest creating a dedicated user for the service.
If your goal is to only sometimes run as superuser I suggest always using user=root in your supervisord.conf and wrapping your program in a small shell script that interprets this environment variable and drops privileges accordingly.
This other SO question might help you:
https://unix.stackexchange.com/questions/132663/how-do-i-drop-root-privileges-in-shell-scripts
For example, building a client for an API, like Twitch.
In a Dart CLI binary, I could use a generic environment variable, or a Dart definition variable. For example, using both as fallbacks:
main() {
String clientId =
// dart -dCLIENT_ID='abc bin/example.dart
// This is considered "compiled-into" the application.
const String.fromEnvironment('CLIENT_ID') ??
// CLIENT_ID='abc' dart bin/example.dart
// This is considered a runtime flag.
Platform.environment['CLIENT_ID'];
// Use clientId.
}
Does Flutter have a way of setting either/both of these, specifically...
During dev time
When shipped to prod
Happy to help with some docs once I figure out how :)
Starting from Flutter 1.17 you can define compile-time variables if you want to.
To do so just use --dart-define argument during flutter run or flutter build
If you need to pass multiple key-value pairs, just define --dart-define multiple times:
flutter run --dart-define=SOME_VAR=SOME_VALUE --dart-define=OTHER_VAR=OTHER_VALUE
and then, anywhere in your code you can use them like:
const SOME_VAR = String.fromEnvironment('SOME_VAR', defaultValue: 'SOME_DEFAULT_VALUE');
const OTHER_VAR = String.fromEnvironment('OTHER_VAR', defaultValue: 'OTHER_DEFAULT_VALUE');
Also, they can be used in native layers too.
Here is an article that explains more.
For configuration a common pattern I've seen is to use separate main files instead. i.e.
flutter run -t lib/production_main.dart
and
flutter build apk -t lib/debug_main.dart
And then in those different main files set up the configurations desired.
In terms of reading ids, you can do that from arbitrary assets https://flutter.io/assets-and-images/.
I believe it is possible in Flutter to read from the environment as you suggest, however I don't know how to set those environment variables on iOS or Android.
Since I was trying to solve this as well and encountered this thread I just wanted to add this for people looking for a solution in the future... If all you're looking for is PROD/DEV environments there is now a supported way of getting if the app is in production or not:
const bool isProduction = bool.fromEnvironment('dart.vm.product');
As suggested by:
https://twitter.com/FlutterDev/status/1048278525432791041
https://github.com/flutter/flutter/issues/4014
To run your app (in flutter run)
flutter run --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
To release your app (in flutter build)
My app wasn't letting users log in I realized that environment variables were empty strings in the app, instead of their actual values 😅.
iOS: flutter build ipa --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
Android: flutter build apk --dart-define=EXAMPLE_API_ENDPOINT=https://api.example.com/
--dart-define documentation
From the flutter run --help or flutter build ipa --help, the --dart-define shows:
Additional key-value pairs that will be available as
constants from the String.fromEnvironment, bool.fromEnvironment,
int.fromEnvironment, and double.fromEnvironment constructors.
Multiple defines can be passed by repeating "--dart-define"
multiple times.
I use simple shell script to generate dart defines. In my app there are 3 build flavors: dev, staging and prod. Environment variables were defined in a regular .env file.
env/
├── dev.env
├── prod.env
└── staging.env
Here is the script to generate dart-defines from .env file.
#!/bin/bash
# scripts/generate_dart_defines.sh
case "$1" in
"dev") INPUT="env/dev.env"
;;
"staging") INPUT="env/staging.env"
;;
"prod") INPUT="env/prod.env"
;;
*)
echo "Missing arguments [dev|staging|prod]"
exit 1
;;
esac
while IFS= read -r line
do
DART_DEFINES="$DART_DEFINES--dart-define=$line "
done < "$INPUT"
echo "$DART_DEFINES"
Here is the script to trigger a build.
#!/bin/bash
# build.sh
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
echo -e "Missing arguments: [apk|appbundle|ios] [release|debug|profile] [dev|staging|prod]"
# invalid arguments
exit 128
fi
DART_DEFINES=$(scripts/generate_dart_defines.sh $3)
if [ $? -ne 0 ]; then
echo -e "Failed to generate dart defines"
exit 1
fi
echo -e "artifact: $1, type: $2, flavor: $3\n"
echo -e "DART_DEFINES: $DART_DEFINES\n"
eval "flutter build $1 --$2 --flavor $3 $DART_DEFINES"
The script accepts 3 arguments. First one is the artifact apk, appbundle or ios. Second one is the build type release, debug or profile. Third one is the build flavor, dev, staging or prod.
./build.sh apk release prod
Please note that you also required to configure android and ios for different build flavors separately.
https://developer.android.com/studio/build/build-variants
https://shockoe.com/ideas/development/how-to-setup-configurations-and-schemes-in-xcode/
https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/ManagingSchemes.html
I do agree with the answer posted by #tatsuDn but I wanted to provide a solution that loads your environment variables from a .env file.
First create a .env file in the root folder of your project.
Ensure that you add the file to your pubspec.yaml and [git] ignore it.
Here is how your .env file should look
API_KEY=sampleapikey
# This line is a comment
# The white line above will be ignored
HEADER=sampleapiheader
ANOTHER_UNIQUE_KEY=theValueOfThisKey
KEY_CONTAINS_#=*234*5#
KEY_CONTAINS_EQUALS=IP8iwe=0&
Here is how your assets section to look like.
# To add assets to your application, add an assets section, like this:
assets:
- assets/images/
- assets/flags/
- .env
Finally, load your environment variable by reading and parsing the .env file to get a Map<String, String> that contains your key value pairs.
Future<Map<String, String>> parseStringToMap({String assetsFileName = '.env'}) async {
final lines = await rootBundle.loadString(assetsFileName);
Map<String, String> environment = {};
for (String line in lines.split('\n')) {
line = line.trim();
if (line.contains('=') //Set Key Value Pairs on lines separated by =
&&
!line.startsWith(RegExp(r'=|#'))) {
//No need to add emty keys and remove comments
List<String> contents = line.split('=');
environment[contents[0]] = contents.sublist(1).join('=');
}
}
return environment;
}
You can put a quick button in your code to test that the environment variables are being loaded properly.
ElevatedButton(
onPressed: () async {
final env = await parseStringToMap(assetsFileName: '.env');
print(env);
},
child: Text('Print Environment Variables')
),
Here is the output from the .env file above.
>>>I/flutter ( 7182): {API_KEY: sampleapikey, HEADER: sampleapiheader, ANOTHER_UNIQUE_KEY: theValueOfThisKey, KEY_CONTAINS_#: *234*5#, KEY_CONTAINS_EQUALS: IP8iwe=0&}
Notes: You will need to rerun the app (not hot reload) so that the .env assets is loaded.
You can also just load your variables in a json file[this may be helpful when you have non string environemental variables and you dont want to parse string.
To avaoid IO, it is a good Idea to just load the environment variables once and access them through out the app using service locators like GetIt.
although above answers are correct coming from python and reactjs I used dotenv and found the same for flutter to load .env file
https://pub.dev/packages/dotenv
Create a class:
import 'package:flutter/foundation.dart';
class AppUtils {
static String get clientId {
if (kDebugMode) return 'debug_id';
else if (kProfileMode) return 'profile_id';
else if (kReleaseMode) return 'production_id';
else if (kIsWeb) return 'web_mode_id';
throw ArgumentError('No mode detected');
}
}
Usage:
var id = AppUtils.clientId;
When I execute the printenv command on the go-agent
go#05f749b73185:/tmp$ printenv
HOSTNAME=05f749b73185
SHELL=/bin/bash
USER=go
LS_COLORS=
MAVEN_VERSION=3.3.9
MAIL=/var/mail/go
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
MAVEN_HOME=/usr/share/maven
PWD=/tmp
JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
LANG=en_US.UTF-8
HOME=/var/go
SHLVL=2
LOGNAME=go
LC_CTYPE=en_US.UTF-8
LESSOPEN=| /usr/bin/lesspipe %s
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/printenv
But when I execute the printenv command from inside a job i get this result
06:57:26.482 [go] Start to execute task: <exec command="printenv" />.
06:57:26.493 GO_SERVER_URL=https://go-server:8154/go/
06:57:26.493 JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/jre
06:57:26.494 SHLVL=2
06:57:26.494 MAVEN_HOME=/usr/share/maven
06:57:26.495 LOG_DIR=/var/log/go-agent
06:57:26.495 GO_TRIGGER_USER=anonymous
06:57:26.495 GO_SERVER=go-server
06:57:26.496 GO_PIPELINE_LABEL=8
06:57:26.496 GO_STAGE_NAME=build
06:57:26.497 HOSTNAME=05f749b73185
06:57:26.497 PWD=/var/lib/go-agent
06:57:26.498 GO_STAGE_COUNTER=1
06:57:26.498 AGENT_WORK_DIR=/var/lib/go-agent
06:57:26.499 GO_JOB_NAME=Compile
06:57:26.499 MAVEN_VERSION=3.3.9
06:57:26.499 OLDPWD=/etc/service/go-agent
06:57:26.500 LC_CTYPE=en_US.UTF-8
06:57:26.500 AGENT_STARTUP_ARGS=-Dcruise.console.publish.interval=10 -Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom
06:57:26.501 GO_FROM_REVISION=b6f8f0f3bedabe1cc0ffa1334c290f32da723cde
06:57:26.501 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
06:57:26.501 GO_TO_REVISION=b6f8f0f3bedabe1cc0ffa1334c290f32da723cde
06:57:26.502 USER=go
06:57:26.502 GO_SERVER_PORT=8153
06:57:26.502 GO_PIPELINE_NAME=DropwizardSeed
06:57:26.503 HOME=/var/go
06:57:26.503 UID=103
06:57:26.503 GO_ENVIRONMENT_NAME=local
06:57:26.506 INITRD=no
06:57:26.507 GO_PIPELINE_COUNTER=8
06:57:26.508 GO_REVISION=b6f8f0f3bedabe1cc0ffa1334c290f32da723cde
06:57:26.509 LANG=en_US.UTF-8
If you look at the JAVA_HOME environment variable it's different between the job call and the call directly when you're logged in the machine.
This can be solved by setting the environment variable in the pipeline, but how can I configure my go-server and go-agents so I don't have to do this? What if I want to use another JDK as default?
Where does that JAVA_HOME environment variable come from?
Have you checked /etc/default/<agent-name>
In this file you can define the default values for an agent and you can also define environment variables using export command.
I am using following code to append ";C:\Python27" to environment variable PATH..
#echo off
Setx Path "%PATH%;C:\Python27" -M
PAUSE
but if i run this batch file more than once, it is appending ";C:\Python27" many times that should not happen.
SO i have to check for ;C:\Python27 before appending it to PATH variable.
Is there any command for this purpose?
The following Powershell should do it:
$needPython = $env:path | select-string -NotMatch -SimpleMatch "c:\python27"
if ($needPython) {
[Environment]::SetEnvironmentVariable("tstpath", $env:path + ";c:\python27", "User")
}
You can change User to Machine or Process to set a machine or process level environment variable.
You can run this directly from a powershell prompt.
If you're running this from a dos command line use (you need the full path to your script or .\ if it's in the current directory):
powershell "& '.\myscript.ps1'"