Skip to content

Use compath.py to define COM paths instead of hard-coded COMROOT construction#220

Open
Copilot wants to merge 10 commits into
mainfrom
copilot/use-compath-instead-of-hard-coded-paths
Open

Use compath.py to define COM paths instead of hard-coded COMROOT construction#220
Copilot wants to merge 10 commits into
mainfrom
copilot/use-compath-instead-of-hard-coded-paths

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 6, 2026

  • Explore codebase to understand COMROOT usage and compath.py pattern
  • Update job scripts to define COM variables via compath.py (with COMROOT fallback); remove ROTDIR
  • JOBSFORGE_GLOBAL_MARINE_BUFR_DUMP: update COMIN_OBSPROC to include /${RUN}.${PDY}/${cyc}
  • parm/bufr2ioda_template.yaml.j2: simplify dump_filename to use updated COMIN_OBSPROC
  • Rename COM variables with OBSFORGE prefix for explicitness
  • Add _OBS suffix to ATMOS COM variables per reviewer request
  • Merge origin/main (commit 1790f36): job scripts moved from jobs/ to dev/jobs/; jobs is now a symlink to dev/jobs/. All compath.py changes preserved in renamed locations.

Copilot AI and others added 2 commits May 6, 2026 16:47
Agent-Logs-Url: https://github.com/NOAA-EMC/obsForge/sessions/45c3ae7a-619d-4226-9de3-1730be6973aa

Co-authored-by: CoryMartin-NOAA <6354668+CoryMartin-NOAA@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor code to use compath instead of hard coded paths Use compath.py to define COM paths instead of hard-coded COMROOT construction May 6, 2026
Copilot AI requested a review from CoryMartin-NOAA May 6, 2026 16:49
Copy link
Copy Markdown
Contributor

@CoryMartin-NOAA CoryMartin-NOAA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot this isn't quite right, for JOBSFORGE_GLOBAL_MARINE_DUMP COMIN_OBSPROC should look something more like this: https://github.com/NOAA-EMC/global-workflow/blob/ee5e04eaaba44aed87d2dd4bf559dd1ef360cb79/dev/jobs/JGLOBAL_OFFLINE_ATMOS_ANALYSIS.j2#L36-L37

and we need a COMOUT_OCEAN_OBS defined here (and modified in the python script in the output section ) that looks like this:
export COMOUT_OCEAN_OBS="${ROTDIR}/${RUN}.${PDY}/${cyc}/ocean/insitu"

Basically if you see OBSPROC_COMROOT, that should be replaced by COMIN_OBSPROC and COMIN_OBSPROC should be replaced by COMOUT_OCEAN_OBS

…EAN_OBS

Agent-Logs-Url: https://github.com/NOAA-EMC/obsForge/sessions/d75cccdd-ac12-4c58-8dc6-71827e2b319c

Co-authored-by: CoryMartin-NOAA <6354668+CoryMartin-NOAA@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 6, 2026

@copilot this isn't quite right, for JOBSFORGE_GLOBAL_MARINE_DUMP COMIN_OBSPROC should look something more like this: https://github.com/NOAA-EMC/global-workflow/blob/ee5e04eaaba44aed87d2dd4bf559dd1ef...

Done in commit 8d2ca84. The changes:

  • JOBSFORGE_GLOBAL_MARINE_BUFR_DUMP now defines COMIN_OBSPROC via compath.py "${envir}/obsproc/${obsproc_ver}" (with OBSPROC_COMROOT fallback) for reading input BUFR files, and COMOUT_OCEAN_OBS="${ROTDIR}/${RUN}.${PDY}/${cyc}/ocean/insitu" for writing output IODA files.
  • marine_bufr_prepobs.py: OBSPROC_COMROOTCOMIN_OBSPROC in the obs_cycle_dict (passed to the Jinja template); all output usages of COMIN_OBSPROCCOMOUT_OCEAN_OBS.
  • parm/bufr2ioda_template.yaml.j2: {{ OBSPROC_COMROOT }}{{ COMIN_OBSPROC }}.

Comment thread jobs/JOBSFORGE_GLOBAL_AOD_DUMP Outdated
Comment thread jobs/JOBSFORGE_GLOBAL_MARINE_BUFR_DUMP Outdated
Comment thread jobs/JOBSFORGE_GLOBAL_AOD_DUMP Outdated
Agent-Logs-Url: https://github.com/NOAA-EMC/obsForge/sessions/0932c2a7-a100-48f4-ab86-2d3d260a79cb

Co-authored-by: CoryMartin-NOAA <6354668+CoryMartin-NOAA@users.noreply.github.com>
… _STAGE_OBS

Agent-Logs-Url: https://github.com/NOAA-EMC/obsForge/sessions/077ab63f-0718-4e07-a84c-366610a5c4f3

Co-authored-by: CoryMartin-NOAA <6354668+CoryMartin-NOAA@users.noreply.github.com>
The `script_env` fixture in `test_exobsforge_global_dump.py` only set 4
variables (`cyc`, `current_cycle`, `PDY`, `RUN`), causing `KeyError:
'COMOUT_OBSFORGE_MARINE_OBS'` when `MarineObsPrep.finalize()` ran. In
production these variables are injected by the job scripts; the test had
no equivalent setup.

## Changes

- **`script_env` fixture** — adds the three missing runtime path
variables, each rooted under pytest's `tmp_path`, with directories
pre-created:
  ```python
  env["DCOMROOT"] = str(tmp_path / "dcom")
env["COMOUT_OBSFORGE_MARINE_OBS"] = str(tmp_path / "com" / "marine_obs")
  env["COMOUT_OBSFORGE_CHEM_OBS"] = str(tmp_path / "com" / "chem_obs")

  Path(env["DCOMROOT"]).mkdir(parents=True, exist_ok=True)
Path(env["COMOUT_OBSFORGE_MARINE_OBS"]).mkdir(parents=True,
exist_ok=True)
Path(env["COMOUT_OBSFORGE_CHEM_OBS"]).mkdir(parents=True, exist_ok=True)
  ```
`COMOUT_OBSFORGE_CHEM_OBS` covers the AOD script — on the target branch
`AerosolObsPrep.finalize()` reads that key (matching
`JOBSFORGE_GLOBAL_AOD_DUMP`).

- **`test_run_exobsforge_script`** — fixes `create_dcom` to use
`env["DCOMROOT"]` (fixture-controlled) instead of
`os.getenv("DCOMROOT")` (parent process, unset in CI).

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

The failing GitHub Actions job for PR #220 in `NOAA-EMC/obsForge` is
caused by a pytest environment setup gap in
`scripts/tests/test_exobsforge_global_dump.py`.

Failure details:
- Workflow run: `25503656413`
- Job: `74864479258`
- Failing test:
`scripts/tests/test_exobsforge_global_dump.py::test_run_exobsforge_script`
- Logs show `KeyError: 'COMOUT_OBSFORGE_MARINE_OBS'` raised when running
`scripts/exobsforge_global_marine_dump.py`.

Relevant context from the failing job:
- The workflow `.github/workflows/build.yaml` runs `pytest scripts/tests
--disable-warnings -v` inside Docker.
- The test fixture `script_env` in
`scripts/tests/test_exobsforge_global_dump.py` currently sets only a
small subset of required environment variables (`cyc`, `current_cycle`,
`PDY`, `RUN`).
- The script `scripts/exobsforge_global_marine_dump.py` builds runtime
config from `os.environ` and invokes `MarineObsPrep.finalize()`, which
expects output path environment variables such as
`COMOUT_OBSFORGE_MARINE_OBS` to be present.

Requested fix:
1. Update `scripts/tests/test_exobsforge_global_dump.py` so the
`script_env` fixture provides the missing output directory environment
variables needed by the scripts under test.
2. Use temporary directories rooted under `tmp_path` for these variables
rather than relying on external environment state.
3. Create any required directories in the fixture before running the
scripts.
4. Keep the change minimal and focused on fixing the failing test.
5. If the AOD script under test requires a similar output variable,
include it as part of the fixture setup as well.
6. After making the change, open a pull request targeting branch
`copilot/use-compath-instead-of-hard-coded-paths`.

Please keep the PR title concise and descriptive.

The following is the prior conversation context from the user's chat
exploration (may be truncated):

User: Please find a solution for this failing job. Use the logs, job
definition, and any referenced files where the failure occurred. Keep
your response focused on the solution and include code suggestions when
appropriate.

Assistant: The failure to fix is the pytest error in
[`scripts/tests/test_exobsforge_global_dump.py`](https://github.com/NOAA-EMC/obsForge/blob/e52c83bb5289edf54655c2e3743ddce912dce664/scripts/tests/test_exobsforge_global_dump.py#L55-L87),
not the repeated `NetCDF: Unknown file format` messages. Those happen
because the test intentionally creates empty `.nc`/`.h5` placeholder
files at lines 47–50, but the job only fails when
`exobsforge_global_marine_dump.py` crashes with:

- `KeyError: 'COMOUT_OBSFORGE_MARINE_OBS'` in
[`scripts/exobsforge_global_marine_dump.py`](https://github.com/NOAA-EMC/obsForge/blob/e52c83bb5289edf54655c2e3743ddce912dce664/scripts/exobsforge_global_marine_dump.py#L15-L35)

## Root cause

The test fixture sets only:

- `cyc`
- `current_cycle`
- `PDY`
- `RUN`

in
[`script_env`](https://github.com/NOAA-EMC/obsForge/blob/e52c83bb5289edf54655c2e3743ddce912dce664/scripts/tests/test_exobsforge_global_dump.py#L7-L15)

but `MarineObsPrep.finalize()` expects `COMOUT_OBSFORGE_MARINE_OBS` to
exist in the environment/config. Since the script builds its config from
`os.environ` first, that missing variable propagates into a `KeyError`.

## Solution

Set the required output directory variables in the test environment
before running the script.

### Recommended patch

Update
[`scripts/tests/test_exobsforge_global_dump.py`](https://github.com/NOAA-EMC/obsForge/blob/e52c83bb5289edf54655c2e3743ddce912dce664/scripts/tests/test_exobsforge_global_dump.py)
so the fixture provides the missing paths:

```python
import pytest
import os
import subprocess
from pathlib import Path


@pytest.fixture
def script_env(tmp_path):
    env = os.environ.copy()
    env["cyc"] = "0"
    env["current_cycle"] = "20250301600"
    env["PDY"] = "20250316"
    env["RUN"] = "gdas"

    # Required runtime directories
    env["DCOMROOT"] = str(tmp_path / "dcom")
    env["COMROOT"] = str(tmp_path / "com")
    env["COMOUT_OBSFORGE_MARINE_OBS"] = str(tmp_path / "com" / "marine_obs")
    env["COMOUT_OBSFORGE_AOD_OBS"] = str(tmp_path / "com" / "aod_obs")

    # Ensure directories exist
    Path(env["DCOMROOT"]).mkdir(parents=True, exist_ok=True)
    Path(env["COMOUT_OBSFORGE_MARINE_OBS"]).mkdir(parents=True, exist_ok=True)
    Path(env["COMOUT_OBSFORGE_AOD_OBS"]).mkdir(parents=True, exist_ok=True)

    return env
```

## Why this is the right fix

- The failing traceback points to missing runtime configuration, not bad
Python logic in the script.
- The workflow just runs `pytest scripts/tests` in the container, so the
test must fully mock the environment itself; nothing in
[`.github/workflows/build.yaml`](https://github.com/NOAA-EMC/obsForge/blob/e52c83bb5289edf54655c2e3743ddce912dce664/.github/workflows/build.yaml#L42-L65)
injects these variables.
- `exobsforge_global_marine_dump.py` depends on environment-driven
config assembly at lines 17–30, so the test must provide all required
k...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: CoryMartin-NOAA <6354668+CoryMartin-NOAA@users.noreply.github.com>
@AndrewEichmann-NOAA
Copy link
Copy Markdown
Contributor

Added @givelberg and @apchoiCMD as reviewers because I haven't touched this in ages

@CoryMartin-NOAA
Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request and ask me if you run into any issues

…nstead-of-hard-coded-paths

Co-authored-by: CoryMartin-NOAA <6354668+CoryMartin-NOAA@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 11, 2026

@copilot resolve the merge conflicts in this pull request and ask me if you run into any issues

Done in commit 02b6276. The merge went cleanly — no manual conflict resolution was needed. The key change in main was moving the J-job scripts from jobs/ to dev/jobs/ (with jobs becoming a symlink to dev/jobs/). Git correctly detected this as renames and carried all the compath.py changes over to the new dev/jobs/ locations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use compath instead of hard coded paths

3 participants