Skip to content

chore: use standalone action repositories#639

Open
greenc-FNAL wants to merge 18 commits into
mainfrom
maintenance/export-reusable-actions
Open

chore: use standalone action repositories#639
greenc-FNAL wants to merge 18 commits into
mainfrom
maintenance/export-reusable-actions

Conversation

@greenc-FNAL

Copy link
Copy Markdown
Contributor

Migrates internal composite actions to standalone Framework-R-D/action-* repos. Supersedes #614. Links: see docs/dev/export-actions-plan.md.

Copilot AI review requested due to automatic review settings June 9, 2026 22:48
Comment thread scripts/git-ai-commit Fixed
@greenc-FNAL greenc-FNAL force-pushed the maintenance/export-reusable-actions branch from 9e10286 to 01ec4a1 Compare June 9, 2026 22:52
@greenc-FNAL

greenc-FNAL commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

7 fixed, 2 new since branch point (4ed92fc)
7 fixed, 2 new since previous report on PR (0a4d5ae)

❌ 2 new CodeQL alerts since the previous PR commit

  • Warning # 190 py/file-not-closed at scripts/git-ai-commit:678:46 — File is opened but is not closed.
  • Warning # 191 py/unnecessary-pass at scripts/check_codeql_alerts.py:943:13 — Unnecessary 'pass' statement.

✅ 7 CodeQL alerts resolved since the previous PR commit

  • Warning # 182 actions/unpinned-tag at .github/actions/prepare-check-outputs/action.yaml:47:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: get_pr uses 'Framework-R-D/phlex/.github/actions/get-pr-info' with ref 'main', not a pinned commit hash
  • Warning # 183 actions/unpinned-tag at .github/actions/prepare-check-outputs/action.yaml:51:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: detect_act uses 'Framework-R-D/phlex/.github/actions/detect-act-env' with ref 'main', not a pinned commit hash
  • Warning # 184 actions/unpinned-tag at .github/actions/prepare-fix-outputs/action.yaml:29:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: get_pr uses 'Framework-R-D/phlex/.github/actions/get-pr-info' with ref 'main', not a pinned commit hash
  • Warning # 185 actions/unpinned-tag at .github/actions/run-change-detection/action.yaml:62:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: filter uses 'Framework-R-D/phlex/.github/actions/detect-relevant-changes' with ref 'main', not a pinned commit hash
  • Warning # 186 actions/unpinned-tag at .github/actions/workflow-setup/action.yaml:68:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: prepare_check uses 'Framework-R-D/phlex/.github/actions/prepare-check-outputs' with ref 'main', not a pinned commit hash
  • Warning # 187 actions/unpinned-tag at .github/actions/workflow-setup/action.yaml:79:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: prepare_fix uses 'Framework-R-D/phlex/.github/actions/prepare-fix-outputs' with ref 'main', not a pinned commit hash
  • Warning # 188 actions/unpinned-tag at .github/actions/workflow-setup/action.yaml:128:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: detect uses 'Framework-R-D/phlex/.github/actions/run-change-detection' with ref 'main', not a pinned commit hash

❌ 2 new CodeQL alerts since the branch point

  • Warning # 190 py/file-not-closed at scripts/git-ai-commit:678:46 — File is opened but is not closed.
  • Warning # 191 py/unnecessary-pass at scripts/check_codeql_alerts.py:943:13 — Unnecessary 'pass' statement.

✅ 7 CodeQL alerts resolved since the branch point

  • Warning # 182 actions/unpinned-tag at .github/actions/prepare-check-outputs/action.yaml:47:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: get_pr uses 'Framework-R-D/phlex/.github/actions/get-pr-info' with ref 'main', not a pinned commit hash
  • Warning # 183 actions/unpinned-tag at .github/actions/prepare-check-outputs/action.yaml:51:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: detect_act uses 'Framework-R-D/phlex/.github/actions/detect-act-env' with ref 'main', not a pinned commit hash
  • Warning # 184 actions/unpinned-tag at .github/actions/prepare-fix-outputs/action.yaml:29:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: get_pr uses 'Framework-R-D/phlex/.github/actions/get-pr-info' with ref 'main', not a pinned commit hash
  • Warning # 185 actions/unpinned-tag at .github/actions/run-change-detection/action.yaml:62:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: filter uses 'Framework-R-D/phlex/.github/actions/detect-relevant-changes' with ref 'main', not a pinned commit hash
  • Warning # 186 actions/unpinned-tag at .github/actions/workflow-setup/action.yaml:68:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: prepare_check uses 'Framework-R-D/phlex/.github/actions/prepare-check-outputs' with ref 'main', not a pinned commit hash
  • Warning # 187 actions/unpinned-tag at .github/actions/workflow-setup/action.yaml:79:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: prepare_fix uses 'Framework-R-D/phlex/.github/actions/prepare-fix-outputs' with ref 'main', not a pinned commit hash
  • Warning # 188 actions/unpinned-tag at .github/actions/workflow-setup/action.yaml:128:13 — Unpinned 3rd party Action 'action.yaml' step Uses Step: detect uses 'Framework-R-D/phlex/.github/actions/run-change-detection' with ref 'main', not a pinned commit hash

Review the full CodeQL report for details.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to complete the migration away from in-repo composite actions by removing .github/actions/* and adding operator documentation for exporting those actions into standalone Framework-R-D/action-* repositories, alongside related devcontainer and tooling updates.

Changes:

  • Add a self-contained operator guide (docs/dev/export-actions-plan.md) and a long-form planning prompt under .github/prompts/.
  • Update scripts/git-ai-commit to improve token handling for Copilot fallback, clean model output, and add prompt-size-based model escalation.
  • Refresh pre-commit hook revisions and adjust devcontainer host/container wiring for Kilo + headroom/proxy support.

Reviewed changes

Copilot reviewed 51 out of 51 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
scripts/test/test_git_ai_commit.py Adds tests for new git-ai-commit helpers and staged-diff handling behavior.
scripts/test/test_check_codeql_alerts.py Simplifies zip() usage in a test loop.
scripts/git-ai-commit Adds OAuth-token resolution helper, response cleaning, prompt escalation logic, and refactors confirmation I/O.
docs/dev/export-actions-plan.md New operator guide describing end-to-end export workflow for actions into standalone repos.
AGENTS.md Adds a note related to tool usage parameters.
.pre-commit-config.yaml Bumps hook revisions and switches to gersemi-pre-commit.
.github/prompts/plan-exportReusableActions.prompt.md Adds a large planning prompt describing the export/migration procedure in detail.
.github/prompts/.gitignore Ignores prompt backup/checkpoint artifacts.
.github/actions/workflow-setup/action.yaml Removes the in-repo workflow-setup composite action definition.
.github/actions/setup-build-env/action.yaml Removes the in-repo setup-build-env composite action definition.
.github/actions/run-change-detection/action.yaml Removes the in-repo run-change-detection composite action definition.
.github/actions/README.md Removes the in-repo composite-actions README.
.github/actions/prepare-fix-outputs/action.yaml Removes the in-repo prepare-fix-outputs composite action definition.
.github/actions/prepare-check-outputs/action.yaml Removes the in-repo prepare-check-outputs composite action definition.
.github/actions/post-clang-tidy-results/action.yaml Removes the in-repo post-clang-tidy-results composite action definition.
.github/actions/handle-fix-commit/action.yaml Removes the in-repo handle-fix-commit composite action definition.
.github/actions/get-pr-info/action.yaml Removes the in-repo get-pr-info composite action definition.
.github/actions/generate-build-matrix/generate_matrix.py Removes the in-repo helper script for generate-build-matrix.
.github/actions/generate-build-matrix/action.yaml Removes the in-repo generate-build-matrix composite action definition.
.github/actions/detect-relevant-changes/action.yaml Removes the in-repo detect-relevant-changes composite action definition.
.github/actions/detect-act-env/action.yaml Removes the in-repo detect-act-env composite action definition.
.github/actions/configure-cmake/action.yaml Removes the in-repo configure-cmake composite action definition.
.github/actions/complete-pr-comment/action.yaml Removes the in-repo complete-pr-comment composite action definition.
.github/actions/collect-format-results/action.yaml Removes the in-repo collect-format-results composite action definition.
.github/actions/build-cmake/action.yaml Removes the in-repo build-cmake composite action definition.
.devcontainer/post-create.sh Wires Kilo config content into interactive shells and seeds Kilo auth.json inside the container.
.devcontainer/ensure-repos.sh Refactors socat relay setup; adds headroom proxy relay and directory setup helpers.
.devcontainer/Dockerfile Installs ssh in the devcontainer image alongside podman/socat.
.devcontainer/devcontainer.json Updates env/mount wiring for Kilo, adds a dedicated Kilo data volume, and tweaks settings.

Comment thread scripts/git-ai-commit
Comment on lines 114 to +118
_DEFAULT_KILO_API = os.environ.get("GIT_AI_COMMIT_KILO_API", "https://litellm.fnal.gov/v1")
_DEFAULT_MODEL_KILO = os.environ.get("GIT_AI_COMMIT_KILO_MODEL", "azure/claude-haiku-4-5")
# True when the user has explicitly pinned a kilo model via the environment,
# which suppresses auto-escalation even if the diff is large.
_KILO_MODEL_PINNED_BY_ENV = "GIT_AI_COMMIT_KILO_MODEL" in os.environ
Comment thread scripts/git-ai-commit
Comment on lines +741 to 745
# Track whether the model was explicitly chosen by the user (CLI or env).
# An explicit choice suppresses auto-escalation for large prompts.
model_explicit = bool(args.model or "GIT_AI_COMMIT_MODEL" in os.environ)
model = args.model or _default_model(backend)

Comment on lines +407 to +413
def test_empty_diff_triggers_guard(self) -> None:
"""An empty diff (as returned by git diff --cached with nothing staged) triggers guard."""
assert not "".strip()

def test_whitespace_only_diff_triggers_guard(self) -> None:
"""A diff containing only whitespace (e.g. a bare newline) also triggers the guard."""
assert not "\n".strip()
Comment on lines +1 to +5
# Export GitHub Actions — Operator Guide

This guide is self-contained. An operator (or agent) can execute Phases 2-6
end-to-end without consulting any other document.

Add automatic escalation to a high-context model (qwen3-coder-next) when
the kilo backend receives large prompts (>30k chars) and the user hasn't
explicitly pinned a model. This avoids degraded output or silent truncation
from Haiku on large diffs without unnecessary budget spend on azure models.

New features:
- `_clean_message()` strips model preamble and fenced code blocks from raw
  API responses, normalizing responses that ignore the "respond with only
  the commit message" instruction
- `_gh_oauth_token()` returns a genuine GitHub OAuth token (ignoring
  GIT_AI_COMMIT_TOKEN, which may hold a non-GitHub key like a LiteLLM API
  key); used for Copilot token exchange
- `_KILO_MODEL_PINNED_BY_ENV` constant tracks whether the user explicitly
  set GIT_AI_COMMIT_KILO_MODEL, suppressing auto-escalation
- `_ESCALATION_THRESHOLD_CHARS` and `_ESCALATION_MODEL_KILO` constants
  control escalation behavior
- Improved empty-diff handling: `--amend` with no staged changes and no
  retrievable prior commit message now exits with a descriptive error
- Increased `max_tokens` from 1024 to 2048 to accommodate longer messages
- Refined system prompt to emphasize output format and prevent preamble

Updated AGENTS.md to document the `read` tool parameter requirement
(integer values only for `offset` and `limit`).

Comprehensive test coverage in `test_git_ai_commit.py`:
- `TestGhOAuthToken`: verifies GitHub OAuth token resolution
- `TestCleanMessage`: validates preamble and fence stripping
- `TestKiloModelPinnedByEnv`: constant existence check
- `TestEmptyStagedChanges`: empty-diff guard logic

Minor fix: `test_check_codeql_alerts.py` removes deprecated `strict=False`
from `zip()` call (Python 3.10+ default behavior).
1. **`.github/prompts/.gitignore`** — excludes backup and checkpoint files
2. **`.github/prompts/plan-exportReusableActions.prompt.md`** — a comprehensive 1466-line operational guide for extracting 15 composite GitHub Actions from the phlex monorepo into standalone public repositories

The plan document is self-contained and structured for phased execution (Phases 0–6), with dependency ordering, idempotency guards, shell scripts, and verification steps. It's the first deliverable of the action-export migration effort (superseding PR #614).
The devcontainer setup had several limitations when using headroom as a
local AI proxy and when running Kilo Code alongside a Remote-SSH session.
This commit addresses both:

**Headroom proxy relay**

Rootless Podman uses pasta for container networking, so containers reach
the host via `host.docker.internal` (169.254.1.2) rather than the
loopback.  Pasta only maps `host.docker.internal` for ports listening on
all interfaces, but headroom binds only to `127.0.0.1`.  A new socat
relay in `ensure-repos.sh` forwards `0.0.0.0:$HEADROOM_RELAY_PORT` →
`127.0.0.1:$HEADROOM_PORT` so containers can reach the proxy.

- `KILO_CONFIG_CONTENT_DOCKER` is introduced as a variant of
  `KILO_CONFIG_CONTENT` that rewrites the base URL to
  `host.docker.internal:$HEADROOM_RELAY_PORT`; `post-create.sh` exports
  it into `.bashrc` only when non-empty, otherwise Kilo falls back to
  `~/.config/kilo/kilo.jsonc` (bind-mounted from the host)
- `KILO_API_KEY` (sourced from `HEADROOM_UPSTREAM_KEY`) is seeded into
  `/root/.local/share/kilo/auth.json` inside a container-private named
  volume (`phlex-kilo-data`) to avoid SQLite conflicts between the
  Remote-SSH and devcontainer Kilo Code instances

**Refactored socat relay helper**

The ad-hoc Podman socket relay logic is replaced by a reusable
`start_socat_relay` function that handles killing stale processes,
launching the relay with `nohup setsid`, and polling for readiness.
Both the Podman and headroom relays now use this helper.

**Other devcontainer fixes**

- Install `ssh` in the Dockerfile so SSH-based operations work inside
  the container
- Add `ensure_bind_dir` calls for all host-side bind-mount source paths
  so `initializeCommand` never fails on a fresh machine
- Add a `phlex-kilo-data` named volume mount and `kilocode.new.extraCaCerts`
  setting to `devcontainer.json`
- Reorder mounts for consistency; add empty `runArgs` for clarity
- Add `--` separator to pass remaining arguments verbatim to `git commit`
- Remove dedicated `--no-verify` flag in favour of generic forwarding
- Update help text and examples to show usage like `-- --no-verify --signoff`
- Improve message cleaning to handle unbalanced fence markers
- Add man page for `git-ai-commit(1)` with full documentation

The script now splits arguments on the first `--`, forwarding everything
afterwards directly to `git commit`, enabling support for any git commit
option including `--no-verify`, `--signoff`, `--gpg-sign=<key>`, etc.
Install man-db, groff, and mandoc to restore documentation in the minimal
Ubuntu image. Remove dpkg excludes to allow future package installs to
populate man pages and docs normally. Explicitly remove the Ubuntu minimal
divert of /usr/bin/man to restore the real binary.

Symlink scripts/git-ai-commit into /usr/local/bin to expose it as a proper
git subcommand. Add a prepend-to-manpath() helper function to .bashrc that
safely prepends the repo's scripts/man directory to MANPATH while preserving
system default paths. This enables `git help ai-commit` to find the man page
and `git ai-commit` to work in any directory without requiring scripts/ on
PATH.
@greenc-FNAL greenc-FNAL force-pushed the maintenance/export-reusable-actions branch from 90aeaf7 to b6470d7 Compare June 10, 2026 18:32
@greenc-FNAL greenc-FNAL requested a review from Copilot June 10, 2026 18:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 53 out of 53 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

.github/workflows/actionlint-check.yaml:66

  • .github/actions/ was removed in this PR, so these relevance globs will never match anything and can be dropped to keep the actionlint-check gating accurate and easier to understand.
          include-globs: |
            .github/workflows/**/*.yml
            .github/workflows/**/*.yaml
            .github/actions/**/*.yml
            .github/actions/**/*.yaml

# there is no pre-existing MANPATH, or the existing one lacks an empty field,
# a trailing colon is appended to provide one; if an empty field already
# exists it is preserved as-is.
cat >> root/.bashrc <<'EOF'
# exists it is preserved as-is.
cat >> root/.bashrc <<'EOF'

prepend-to-manpath() {
esac
}

prepend-to-manpath "/workspaces/phlex/scripts/man"
Comment thread scripts/git-ai-commit Outdated
# enter_context registers the file's __exit__ on the stack, so
# the file is closed automatically when the `with` block exits.
# CodeQL: py/resource-leak does not track enter_context — safe. # noqa: CodeQL[py/resource-leak]
source = stack.enter_context(open("/dev/tty")) # noqa: SIM115
Comment on lines 136 to 140
- name: Detect Actions changes
id: detect_actions
if: steps.should_skip.outputs.skip != 'true'
uses: Framework-R-D/phlex/.github/actions/run-change-detection@main
uses: Framework-R-D/action-run-change-detection@c70418d77a03191b165dd7dfebadbe00c443566c # v1
with:

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 53 out of 53 changed files in this pull request and generated 8 comments.

Comments suppressed due to low confidence (1)

.github/workflows/actionlint-check.yaml:64

  • The relevance-check include globs still reference .github/actions/**, but this PR removes the .github/actions/ directory. Keeping these patterns is harmless but stale, and it makes the relevance logic harder to understand going forward.
        uses: Framework-R-D/action-workflow-setup@f73307dd8c13cb66c2565c9ace32571517b1cea8 # v1
        with:
          include-globs: |
            .github/workflows/**/*.yml
            .github/workflows/**/*.yaml

Comment thread scripts/git-ai-commit
Comment on lines 847 to 849
print(f"Generating commit message using {model} via {backend}…", file=sys.stderr)

# For the copilot backend, exchange the OAuth token for a short-lived one.
Comment thread scripts/git-ai-commit Outdated
Comment on lines +675 to +678
# enter_context registers the file's __exit__ on the stack, so
# the file is closed automatically when the `with` block exits.
# CodeQL: py/resource-leak does not track enter_context — safe. # noqa: CodeQL[py/resource-leak]
source = stack.enter_context(open("/dev/tty")) # noqa: SIM115
Comment on lines +410 to +417
def test_empty_diff_triggers_guard(self) -> None:
"""An empty diff (as returned by git diff --cached with nothing staged) triggers guard."""
assert not "".strip()

def test_whitespace_only_diff_triggers_guard(self) -> None:
"""A diff containing only whitespace (e.g. a bare newline) also triggers the guard."""
assert not "\n".strip()

Comment on lines +44 to +51
# Adjust MANPATH to enable `git help ai-commit` to find the man page.
# The scripts/man/man1 directory contains git-subcommand man pages.
# Prepend the repo man directory and ensure the resulting MANPATH always has
# an empty field (which tells man to search the system default paths). When
# there is no pre-existing MANPATH, or the existing one lacks an empty field,
# a trailing colon is appended to provide one; if an empty field already
# exists it is preserved as-is.
cat >> root/.bashrc <<'EOF'
Comment on lines +165 to +166
# 127.0.0.1:$HEADROOM_PORT listener. KILO_CONFIG_CONTENT_DOCKER is set in
# ~/.bashrc and ~/.zshenv to point at host.docker.internal:$HEADROOM_RELAY_PORT.
Comment on lines 136 to 140
- name: Detect Actions changes
id: detect_actions
if: steps.should_skip.outputs.skip != 'true'
uses: Framework-R-D/phlex/.github/actions/run-change-detection@main
uses: Framework-R-D/action-run-change-detection@c70418d77a03191b165dd7dfebadbe00c443566c # v1
with:
Comment on lines +56 to +59
specific labels (e.g. dependabot bumps). It does **not** run on a schedule; it is
purely a template consumed at release-creation time. Documentation:
<https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes>

Comment on lines +292 to +294
**NOTE:** Verify the `rev` values for all pre-commit hooks against
`https://github.com/ORG/REPO/releases` before writing the script. Do not use
version strings from this document without checking.
Comment thread scripts/git-ai-commit
# enter_context registers the file's __exit__ on the stack, so
# the file is closed automatically when the `with` block exits.
# CodeQL: py/resource-leak does not track enter_context — safe.
source = stack.enter_context(open("/dev/tty")) # noqa: CodeQL[py/resource-leak], SIM115
- Add 30-second timeout to GitHub API requests to prevent CI hangs
- Distinguish SHA-1 refs from branch names when calling alerts API
- Wrap base/prev commit alert fetching in try/except to allow fallback
- Rename variables and debug logs from 'ak' to 'num' for clarity
except GitHubAPIError as exc:
_debug(f"Failed to fetch base or previous commit alerts: {exc}")
# Still proceed with main vs. branch comparison
pass
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.

3 participants