Skip to content

Footprint elements

Stamps deployment details into the files themselves. It scans a directory tree for files carrying the marker @(#), and in each one it removes the marker and replaces bracketed placeholders with the environment, the file name, the user and the job. What ships is a file that says on its own face which job put it there.

This is an old op built for the job contents model. It works off an element list naming the files that belong to the job, the kind Fill job elements was written to build, and it does nothing without one. A pipeline built on changesets has no use for it. For substituting values into files in a current rule, use Replace Strings, which takes its patterns from a form and works on any file in the job directory.

scan the tree for @(#) in the job element list? yes a text file? yes rewritten with the values filled in no no left alone, debug only left alone, no message

Configuration

This op has no form. Its Config tab is an empty YAML editor, and nothing you type there is read. Everything it needs comes from the job state.

What it needs before it runs

Two things, and both come from the state saved at the end of the previous job step rather than from the live stash.

The job element list, naming the files that belong to the job. With no element list the op stops the job immediately, before it scans anything. Check that first when the op fails for no visible reason.

Getting a list in there is the hard part. Fill job elements builds one, but its list lives only for the length of that op and is dropped when the step ends, so it does not reach this op even when the two run in the same job. Treat a working pairing as something your installation has to arrange, not as something the two ops do on their own.

A value named path holding the directory to scan. Set it in an earlier step, for example with SET VAR, pointing at the job directory or a subtree of it. Setting it in the same step this op runs in does not reach it, because the value is read from the saved state. An unset path does not stop the job. The scan fails instead and you get the warning described below.

The scan

Every file under that directory, at any depth, is searched for the literal text @(#). The search covers the whole tree, not only the files in the element list, so it will look inside a checked-out source tree as well as inside build output.

Each file that carries the marker is then matched against the element list by full path, built from the scan root, the element path and the element name. A file that carries the marker but is not in the list is left untouched, with a debug-level line saying no footprinting data was found for it.

A matched file is rewritten only when it looks like text. Binary files are skipped without any message at all.

Placeholders

Inside a matched text file, every line carrying @(#) has the marker removed and the placeholders below substituted. Matching ignores case and tolerates trailing spaces inside the brackets, so [STATE] and [state ] both work. A space after the opening bracket does not.

Placeholder Replaced with
[state] the job's environment
[project] the first directory in the element's path
[item] the element's file name
[viewpath] the element's path
[user] the user the job runs for
[pase] the job name
[pasefechahora] the moment the op started, down to the minute

Three more placeholders are recognised and always resolve to nothing: [version], [package] and [date]. They are removed from the file and replaced with an empty string. Do not use them.

[project] has its own catch. It is taken from the first directory component of the element path, which requires the path to start with a separator and to have at least one directory in it. When that does not hold, the placeholder is skipped rather than cleared, so a literal [project] can ship in the file. On a run where an earlier file did produce a project name, the skipped file can pick that earlier name up instead, and stamp the wrong project. Element paths coming from Fill job elements always carry a project directory, so this only bites on lists assembled some other way.

Lines without the marker are copied through unchanged. A file with the marker on one line only has that one line rewritten, and the rest is untouched. The marker itself always goes, even when no placeholder followed it.

Because the marker is what the scan looks for and the rewrite deletes it, the op does not stamp the same file twice. Run it again in the same job and the second pass finds nothing and reports zero elements modified.

What you see in the log

One summary entry at the end reading how many elements were modified, with the list of file paths attached as Footprinting.txt. The entry is flagged as a milestone, so it stands out on the job timeline.

If the scan itself cannot run, for example because the directory is missing or unreadable, the op writes a warning telling you to check the dispatcher log, and returns without touching a single file. The job carries on as if the op had succeeded. That is the failure mode to watch for: a green job with unstamped files. An unreadable subdirectory anywhere under the scan root is enough to trigger it, even when the rest of the tree scanned fine.

At debug level the op is loud. For each marker-carrying file it writes one line per element it compares against, stopping at the element that matches. A file that matches nothing costs a line for every element in the list, so a tree full of unmatched files against a long element list runs into tens of thousands of debug lines. Keep the job log at info level on real trees.

The messages this op writes to the job log are not translated and appear in Spanish whatever language the interface is set to.

Rollback

The op has no reverse. It does not restore the marker it removed and it does not put back the text it replaced. Running it on a rollback pass stamps whatever markers it finds with the environment, user and job name of the same job, so those come out identical to the forward pass. The timestamp does not: [pasefechahora] is read at the moment the op runs, so the rollback stamp carries the rollback time. Guard the op with IF ROLLBACK when that matters.

Combining with other ops

Fill job elements is the companion this op was designed around, in an earlier step. Read the note above about the element list before you rely on that pairing.

Replace Strings is the op to use instead for new work. It takes the search and replacement from a form, runs over a path you name, and does not need an element list.

Put the op ahead of Ship File Remotely so the stamped copy is the one that reaches the node.

Example

A stamping step in a job built on the older contents model. Both the scan root and the element list have to be in place by the end of an earlier step, which is why nothing this op needs sits in the same step as the op itself.

JOB STEP: INIT
  SET VAR
    Variable: path
    Value:    ${job_dir}
  Fill job elements

JOB STEP: PRE
  Footprint elements

With a source file containing:

// @(#) built for [state] by [user] in job [pase] at [pasefechahora]

shipping as:

// built for PROD by foo_user in job N.PROD-00000123 at 2026-09-16 11:42