APPLY PROJECT
Copies the variables defined on one project resource into the
stash, keeping the values that belong to the environment the rule is running in.
Every op after it can then read those values as ${name}.
You name the project. FOR projects with changes DO does the opposite, walking the projects attached to the job's changesets one at a time. Reach for APPLY PROJECT when the rule always works on the same project, or when there are no changesets to derive a project from, such as a scheduled rule or a webservice rule. Nothing nests inside this op: what it loads stays in the stash for the remainder of the rule.
Fields¶
This op has no config form. Its Config tab opens a YAML editor holding the two keys below. Quote
the values, since a bare identifier with a colon in it is easy for YAML to read the wrong way.
project¶
Which project resource to read. The usual value is a MID:
project: '1234'
A field:value lookup works too, so 'name:myapp' and 'moniker:MYAPP' save you pasting a MID
into the rule. The search is not restricted to projects. It reads every resource looking for one
whose field carries that value, so a server or a topic named myapp is as good a hit as the
project, and the rule then stops on it because a server has no variables to read. A nature or a
second project is the worse case: the op merges that resource's variables and logs the result as if
nothing were wrong. A lookup that matches nothing, or that matches more than one resource, also
stops the rule, with an error that does not repeat the text you typed. Monikers collide less often
than names, which makes them the safer of the two.
This value is used exactly as typed. A ${...} in it is not expanded, so '${my_project}' is read
as literal text and no resource matches it. To pick a project at run time, put
FOREACH CI or SET VAR to CI in front
of it instead.
Leaving the key blank, or deleting it, stops the rule with a resource-not-found error before any variable is merged. There is no quiet fallback to the current project.
bl¶
An environment key that was carried over from an older shape of this op. Nothing reads it. Setting
it to PROD does not make the op load PROD values, and clearing it does not stop it from loading
them. The environment always comes from the job the rule is running in.
Which values are picked¶
Project variables are stored per environment, with a * block for the values shared by all of them.
| Environment of the run | What gets merged |
|---|---|
empty, or * |
the * block only |
PROD and the project has a PROD block |
the * block, then the PROD block over the top |
PROD and the project has no PROD block |
the * block, plus a _no_vars_for_bl marker holding PROD |
A variable that exists in both blocks takes its environment value. There is no third level: two environments cannot inherit from each other.
Per-nature project variables are not flattened. They arrive as one nested _natures entry keyed by
resource, not as individual variable names, so a value set under Project variables for a specific
nature is not readable as ${name} after this op. Use
IF EXISTS nature THEN for those.
What lands in the stash¶
| Name | Holds |
|---|---|
| each project variable | its value for the current environment |
_no_vars_for_bl |
the environment name, when the project has no block for it |
_ctx |
the text apply project, a marker left by the merge that nothing else reads |
The merge overwrites. A project variable named path replaces whatever an earlier op left in
path, with no warning, so avoid naming project variables after values the rest of the rule
maintains.
Custom project variables, the ones defined under Deploy then Variables inside the project area, are
not loaded here. Only FOR projects with changes DO brings those in,
under CUSTOM_VARS.
The op also does not set project, project_mid, project_lc, project_uc or current_project.
That matters more than it sounds, because project variables are often written in terms of
${project}. Values are copied in exactly as the project stores them, placeholders and all, so
/tmp/${project}/war lands in the stash with ${project} still in the text. Nothing is expanded at
this point. Expansion happens when a later op reads the variable, against the stash as it stands at
that moment, and happens again on the next read.
If project is missing when that read comes, the reading op does not get a blank. It stops the rule
with a deep recursion error naming project, which is an obscure way of being told that a variable
two steps away was never set. The exception is a stored value that is nothing but the placeholder,
which comes through as the literal text ${project}. Put project in the stash with
SET VAR above the first op that reads one of these values. A ${...}
you type into an op field yourself is not affected: an unknown name there stays as text.
Two kinds of value stop the op itself: a project variable written in terms of itself, such as path
set to ${path}:/opt/foo, and a variable whose text embeds a placeholder holding a list rather than
a string. Both are raised against everything in the stash rather than the merged values alone,
so the variable named in the error is not always one of the project's. On a stash large enough to
take 30 seconds to walk, the op fails on a timeout instead.
Log, failure and rollback¶
The op writes one log line, Current project *name* (env), with the resolved variable set attached
as data you can open in the monitor. A line that shows nothing but _no_vars_for_bl is the
signature of a project with no block for that environment. The text is fixed; the node name you type
in the designer changes the step name, not this line.
A failure to load the resource stops the rule before anything is written, so the stash is untouched and the log line above never appears. A failure raised while the values are being merged is the other way round. The line is already in the log and the values are already in the stash, and they stay there for whatever handles the error.
On a rollback pass the op runs again by default and re-merges the same values, which is usually what
you want, since the rollback ops need the same paths and servers as the forward ops. Untick Run
Rollback on the node if a rule is loading variables you do not want re-applied.
Combining with other ops¶
Put it early, above the ops that consume the variables. A common opening is APPLY PROJECT followed
by LOG Message printing a ${...} value, to confirm the environment
resolved to what you expected before anything runs against a server.
Nothing takes the variables out again. STASH LOCAL reads like the op for that, but the designer treats it as a leaf and refuses to let you drop anything inside it, so it scopes nothing. Clear the names you do not want carried forward with DELETE hashkey, one op per name, at the end of the section that needed them.
To branch on a value it loaded, follow it with IF var condition THEN. To read a field the variables do not carry, such as a repository or a folder, use SET VAR to CI on the same MID and walk the resource instead.
Examples¶
Load one project by MID and use a variable from it further down.
Config (YAML)
project: '1234'
bl: ''
then, in a later op
Path: ${staging_path}/myapp.war
Find the project by moniker, so the rule survives a MID change on import.
Config (YAML)
project: 'moniker:MYAPP'
Keep a merged variable out of the rest of the rule. No block scopes the merge, so the name has to be removed by hand once the section that needs it is done.
APPLY PROJECT project: 'moniker:MYAPP'
LOG Message deploying to ${files_server}
Ship File Remotely ...
DELETE hashkey key: files_server