Run environment
The same automation tests in staging and operates in production. What changes from one place to the other (system address, user, password) lives in the environment, registered in Proton, instead of being repeated in every dataset. The script asks for the value by name and gets the one from the environment the run is using.
The run uses the environment chosen when it was triggered (screen, scheduled run, recurring run or connector) or, if none was chosen, the dataset's default environment. Without either, it runs without an environment.
Read the variables
- Python
- Java
from proton.proton_automation import start_component
from proton.proton_environment import get_environment_name, get_environment_value, is_production
from proton.proton_logs import set_log
start_component() # already reads the run environment, once
url = get_environment_value("SAP_URL")
usuario = get_environment_value("SAP_USUARIO")
senha = get_environment_value("SAP_SENHA")
set_log(f"Environment: {get_environment_name()}")
if is_production():
set_log("Production run: not saving a test document")
Function (proton.proton_environment) | What it does |
|---|---|
get_environment_value(nome, allow_empty=False) | Value of the variable; error if it doesn't exist or is empty (allow_empty=True accepts "") |
get_environment_variables() | Copy of all the variables; empty without an environment or outside Proton |
get_environment_name() | Name of the environment; None without an environment or outside Proton |
is_production() | Whether the environment has the production flag |
mask_environment_values(texto) | The text with the environment values replaced by •••••• |
load_environment(force=False) | Reads the environment; force=True reads it again |
import br.com.atomicsolutions.proton.ProtonAutomation;
import br.com.atomicsolutions.proton.ProtonEnvironment;
import static br.com.atomicsolutions.proton.ProtonLogs.setLog;
ProtonAutomation.startComponent(); // already reads the run environment, once
String url = ProtonEnvironment.get("SAP_URL");
String usuario = ProtonEnvironment.get("SAP_USUARIO");
String senha = ProtonEnvironment.get("SAP_SENHA");
setLog("Environment: " + ProtonEnvironment.getName());
if (ProtonEnvironment.isProduction()) {
setLog("Production run: not saving a test document");
}
Method (ProtonEnvironment) | What it does |
|---|---|
get(nome) and get(nome, allowEmpty) | Value of the variable; error if it doesn't exist or is empty (allowEmpty = true accepts "") |
getAll() | All the variables, read-only; empty without an environment or outside Proton |
getName() | Name of the environment; null without an environment or outside Proton |
isProduction() | Whether the environment has the production flag |
mask(texto) | The text with the environment values replaced by •••••• |
load() and reload() | Reads the environment once; reload() reads it again |
In the environments, use the same names for the variables (SISTEMA_URL in Staging and in Production):
the script always reads the same name, and the environment decides the value. Only what behaves differently
in production uses the production flag. The name is compared exactly, including uppercase and lowercase.
One read per run
The SDK asks Proton for the environment once per run, in start_component() (Python) or in
startComponent() (Java), and keeps everything in memory. Without this call, the read happens on the first
access to the environment. The entire run uses the same values, even if someone changes the environment
midway.
The values never go to disk, to the log or to the process variables. The run output gets only one line with the environment name and the number of variables.
Proton delivers the environment only while the run is in progress. The read uses the same token and the same permission as the other run routes (Executions: view).
Errors
A read by name never returns an empty value instead of an error: it stops the script with
ProtonEnvironmentError (Python) or ProtonEnvironmentException (Java). The message states the variable
and the environment, never the value.
Since 5.5.0, the component executor counts this error as an environment failure. In Java, don't confuse it
with ProtonEnvironmentError (5.5.0), which the step throws to mark an environment failure: see
Run status. In Python, this step exception is called
ProtonEnvironmentFailure: see Run status.
Reason (reason) | When |
|---|---|
environmentVariableNotFound | The environment doesn't have the variable |
emptyVariable | The variable exists, but is empty |
runWithoutEnvironment | The run has no environment: set the dataset's default environment or choose one when triggering the run |
notProtonExecution | Read by name outside a Proton run |
runAlreadyFinished | The run has already finished |
datasetRunNotFound | The run doesn't exist in the token's organization |
httpError | No access (HTTP 401 or 403: check the token and the permission), another status or no response |
A failure in the read done when the step opens doesn't bring down the component: an automation that doesn't use the environment carries on normally, and the error comes back on the first access to the environment, including the name and the production flag. This way, a network failure doesn't turn into "not production".
Masking in the logs
Proton doesn't tell the SDK which variables are secrets, so the SDK masks all the environment values in
what it sends to the run log: each value becomes ••••••, from the longest to the shortest.
- Values shorter than 4 characters aren't masked, otherwise the log would become unreadable. Don't keep secrets shorter than 4 characters.
- Output parameters are recorded as they came: they are written on purpose.
- What the script prints on its own doesn't go through the SDK. For that, use
mask_environment_values(Python) orProtonEnvironment.mask(Java).
From the dataset category to the environment
In Proton 4, the script decided the address, user and password based on the dataset category. In Proton 5 the dataset has no category: the category functions are deprecated and log a warning. Read the values from the environment:
- Python
- Java
# Before (Proton 4)
if get_dataset_category_name() == "PRD":
url = "https://sistema.empresa.com.br"
else:
url = "https://sistema-hml.empresa.com.br"
# After (Proton 5)
url = get_environment_value("SISTEMA_URL")
// Before (Proton 4)
String url = "PRD".equals(ProtonAutomation.getDatasetCategory()) ? URL_PRD : URL_HML;
// After (Proton 5)
String url = ProtonEnvironment.get("SISTEMA_URL");
Don't compare the environment name with the old category: it's free text ("Production", "PRD", "Staging 2"). For what behaves differently in production, use the production flag.