Skip to content

Commit 1de0bb3

Browse files
committed
Add STEPUP_STEP_INP_DIGEST env var
1 parent 96181aa commit 1de0bb3

File tree

11 files changed

+119
-3
lines changed

11 files changed

+119
-3
lines changed

docs/changelog.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,23 @@ and this project adheres to [Effort-based Versioning](https://jacobtomlinson.dev
1212

1313
(no changes yet)
1414

15+
## [3.0.1][] - 2025-05-13 {: #v3.0.1 }
16+
17+
Minor tweaks, improved progress format and `STEPUP_STEP_INP_DIGEST` environment variable.
18+
19+
### Added
20+
21+
- The `STEPUP_STEP_INP_DIGEST` environment variable is set in the worker processes to
22+
the hex-formatted digest of the inputs of the step.
23+
24+
### Changed
25+
26+
- Improved timer format of running steps in progress bar.
27+
28+
### Fixed
29+
30+
- Minor documentation and configuration fixes.
31+
1532
## [3.0.0][] - 2025-05-11 {: #v3.0.0 }
1633

1734
Major release with breaking changes.
@@ -540,6 +557,7 @@ This release fixes several bugs.
540557
Initial release
541558

542559
[Unreleased]: https://github.com/reproducible-reporting/stepup-core
560+
[3.0.1]: https://github.com/reproducible-reporting/stepup-core/releases/tag/v3.0.1
543561
[3.0.0]: https://github.com/reproducible-reporting/stepup-core/releases/tag/v3.0.0
544562
[2.1.7]: https://github.com/reproducible-reporting/stepup-core/releases/tag/v2.1.7
545563
[2.1.6]: https://github.com/reproducible-reporting/stepup-core/releases/tag/v2.1.6

docs/reference/environment_variables.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Environment Variables
22

3+
## Configuration of StepUp
4+
35
The following environment variables can be used to configure StepUp.
46

57
- `STEPUP_DEBUG`: Set to `"1"` to enable debug output.
@@ -45,3 +47,17 @@ export STEPUP_ROOT=${PWD}
4547

4648
When you change to the project directory (or any of its subdirectories) in your shell,
4749
the environment variables will be set automatically.
50+
51+
## Environment Variables in Worker Processes
52+
53+
The following environment variables are set when a worker runs a step:
54+
55+
- `HERE` and `ROOT`, as documented in the tutorial on [`HERE` and `ROOT` variables](../advanced_topics/here_and_root.md)
56+
- `STEPUP_STEP_I` is a unique integer index for the current step.
57+
This is mainly relevant for StepUp and has little significance for users implementing workflows.
58+
- `STEPUP_STEP_INP_DIGEST` is a hex-formatted digest of all the inputs to the step
59+
(including environment variables used).
60+
This is useful in special cases.
61+
For example, it can be used to decide if cached results from a previously interrupted run of the step
62+
are still valid.
63+
It can also be useful when action submit jobs to a scheduler, to decide if a running job is still valid.

stepup/core/api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,8 @@ def getenv(
698698
path = path or back or multi
699699
value = os.getenv(name, default)
700700
# Do not amend environment variables set by the worker.
701-
if name not in ["HERE", "ROOT"]:
701+
# See stepup.core.worker.WorkerHandler.run
702+
if name not in ["HERE", "ROOT", "STEPUP_STEP_I", "STEPUP_STEP_INP_DIGEST"]:
702703
amend(env=name)
703704
if multi:
704705
if value is None:

stepup/core/worker.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,15 @@ class WorkerStep:
475475
inp_messages: list = attrs.field(init=False, factory=list)
476476
"""Messages related to input validation issues: unexpected changes and deleted inputs."""
477477

478+
inp_digest: bytes = attrs.field(init=False, default=b"")
479+
"""The input digest, which can be useful for some actions.
480+
481+
They may use this to decide if cached results from a previously interrupted run
482+
of the same stepo are still valid.
483+
This can also be useful when action submit jobs to a scheduler,
484+
to decide if a running job is still valid.
485+
"""
486+
478487
out_missing: list = attrs.field(init=False, factory=list)
479488
"""List of expected output files that were not created."""
480489

@@ -794,7 +803,11 @@ def compute_inp_step_hash(
794803
label = self.step.action
795804
if self.step.workdir != "./":
796805
label += f" # wd={self.step.workdir}"
797-
return StepHash.from_inp(f"{label}", self.explain_rerun, all_inp_hashes, env_var_values), []
806+
result = StepHash.from_inp(f"{label}", self.explain_rerun, all_inp_hashes, env_var_values)
807+
808+
# Copy the inp_digest, because it can be useful for some actions.
809+
self.step.inp_digest = result.inp_digest
810+
return result, []
798811

799812
@allow_rpc
800813
def compute_out_step_hash(
@@ -897,11 +910,14 @@ async def run(self):
897910
await self.reporter("START", self.step.description)
898911
await self.reporter.start_step(self.step.description, self.step.i)
899912

900-
# For internal use only:
913+
# For internal use in actions:
901914
os.environ["STEPUP_STEP_I"] = str(self.step.i)
902915
# Client code may use the following:
916+
os.environ["STEPUP_STEP_INP_DIGEST"] = self.step.inp_digest.hex()
903917
os.environ["ROOT"] = str(Path.cwd().relpath(self.step.workdir))
904918
os.environ["HERE"] = str(self.step.workdir.relpath())
919+
# Note: the variables defined here should be listed in stepup.core.api.getenv
920+
905921
# Create IO redirection for stdout and stderr
906922
step_err = io.StringIO()
907923
step_out = io.StringIO()
@@ -922,6 +938,12 @@ async def run(self):
922938
self.step.stdout = step_out.getvalue()
923939
self.step.stderr = step_err.getvalue()
924940

941+
# Clean up environment variables (to avoid potential confusion)
942+
del os.environ["STEPUP_STEP_I"]
943+
del os.environ["STEPUP_STEP_INP_DIGEST"]
944+
del os.environ["ROOT"]
945+
del os.environ["HERE"]
946+
925947
# Process results of the step.
926948
if self.show_perf:
927949
ru_final = resource.getrusage(resource.RUSAGE_CHILDREN)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.stepup
2+
current_*
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Minimal example checking that the input digest is present in the environment variables.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
root:
2+
creates file:./
3+
creates file:plan.py
4+
creates step:runpy ./plan.py
5+
6+
file:./
7+
state = STATIC
8+
created by root:
9+
supplies file:plan.py
10+
supplies step:runpy ./plan.py
11+
12+
file:plan.py
13+
state = STATIC
14+
created by root:
15+
consumes file:./
16+
supplies step:runpy ./plan.py
17+
18+
step:runpy ./plan.py
19+
state = SUCCEEDED
20+
created by root:
21+
consumes file:./
22+
consumes file:plan.py
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
0/0 | STARTUP │ (Re)initialized boot script
2+
0/0 | DIRECTOR │ Launched worker 0
3+
0/1 | PHASE │ run
4+
0/1 | START │ runpy ./plan.py
5+
1/1 | SUCCESS │ runpy ./plan.py
6+
1/1 | DIRECTOR │ Trying to delete 0 outdated output(s)
7+
1/1 | PHASE │ watch
8+
1/1 | DIRECTOR │ Stopping workers
9+
1/1 | DIRECTOR │ See you!

tests/examples/inp_digest/main.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env -S bash -x
2+
# Exit on first error and clean up.
3+
set -e
4+
trap 'kill $(pgrep -g $$ | grep -v $$) > /dev/null 2> /dev/null || :' EXIT
5+
rm -rvf $(cat .gitignore)
6+
7+
# Run the example
8+
stepup boot -n 1 -w & # > current_stdout.txt &
9+
10+
# Get the graph after completion of the pending steps.
11+
stepup wait
12+
stepup graph current_graph
13+
stepup join
14+
15+
# Wait for background processes, if any.
16+
wait
17+
18+
# Check files that are expected to be present and/or missing.
19+
[[ -f plan.py ]] || exit 1

tests/examples/inp_digest/plan.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env python3
2+
from stepup.core.api import getenv
3+
4+
digest = getenv("STEPUP_STEP_INP_DIGEST")
5+
assert digest is not None

0 commit comments

Comments
 (0)