Skip to content

ci: make the CI workflow portable across hosts - #12

Open
justyns wants to merge 1 commit into
masterfrom
ci/portable-workflow
Open

ci: make the CI workflow portable across hosts#12
justyns wants to merge 1 commit into
masterfrom
ci/portable-workflow

Conversation

@justyns

@justyns justyns commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Makes the CI workflow portable across CI hosts, and fixes the test failure that exposed.

ci:

  • Install uv from its own installer rather than the astral-sh/setup-uv action, and let uv fetch the interpreter (--python X.Y). That also removes the setup-python dependency, leaving checkout, setup-node and upload-artifact as the only actions.
  • Keep uses: refs bare so the file is not pinned to one host.
  • Gate the publish jobs (PyPI trusted publishing, GitHub Releases, GHCR) and the coverage-artifact upload on github.server_url, so they run only where those services exist. Tag-triggered publishing on GitHub is unchanged.
  • Add workflow_dispatch, and stop restricting pull_request to master so branch PRs get CI.

test:

test_write_file_error_handling and test_create_directory_error asserted that writing to /invalid/path/... and /root/cannot_create_here raises. That only holds for an unprivileged user: run the suite as root, as CI containers commonly do, and both calls succeed, so the tests fail with DID NOT RAISE.

Both now nest the target under a regular file, which fails with ENOTDIR for every uid. The error path stays covered instead of being skipped under root, and the suite becomes safe to run in a root container.

Copilot AI review requested due to automatic review settings August 2, 2026 01:16

Copilot AI left a comment

Copy link
Copy Markdown

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 make the GitHub Actions CI workflow behave consistently across different CI hosts/runners (including root-run containers) and to prevent GitHub-hosted publishing/artifact steps from running on non-GitHub hosts.

Changes:

  • Updated CI workflow to install uv via its upstream installer and to let uv fetch the requested Python version via --python, plus added workflow_dispatch and broadened PR triggering.
  • Gated GitHub-hosted publishing workflows (PyPI trusted publishing / GHCR) and the CI coverage artifact upload to run only on https://github.com.
  • Updated file tool tests to exercise error paths reliably even when the test suite runs as root by using an ENOTDIR-style failure setup.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
tests/test_file_tools.py Makes error-handling tests root-safe by forcing ENOTDIR via “parent is a file” setup.
.github/workflows/ci.yml Reworks CI to install uv via script + --python, adds workflow_dispatch, broadens PR coverage, gates artifact upload on GitHub.
.github/workflows/pypi-publish.yml Gates PyPI publish job to GitHub-hosted environment via github.server_url.
.github/workflows/docker-publish.yml Gates GHCR publish job to GitHub-hosted environment via github.server_url.
Suppressed comments (1)

.github/workflows/ci.yml:53

  • Same silent-failure risk here: without pipefail, a failed curl in the installer pipeline may not fail the step. Enable set -euo pipefail (and bash) so the installation step fails immediately on download errors.
      - name: Install uv
        run: |
          curl -LsSf https://astral.sh/uv/install.sh | sh
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"

Comment thread .github/workflows/ci.yml
Comment on lines 25 to +28
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
Copilot AI review requested due to automatic review settings August 2, 2026 01:31

Copilot AI left a comment

Copy link
Copy Markdown

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 6 out of 6 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

.github/workflows/ci.yml:53

  • Same supply-chain concern as the lint job: curl ... | sh executes a remote installer script without version pinning or verification, which reduces reproducibility and increases risk across CI hosts.
      - name: Install uv
        run: |
          curl -LsSf https://astral.sh/uv/install.sh | sh
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"

plugins/tsugite-daemon/tsugite_daemon/auth.py:158

  • TokenStore.validate() only holds the lock while reading the in-memory ephemeral token, then releases it before consulting SQLite and before returning. That allows a revoked persistent token to be accepted if revoke() interleaves between the DB read and the return, and it also weakens the concurrency guarantee this change is trying to enforce. Consider holding the lock for the entire validation path (including the SQLite read) so validate() and revoke() are mutually exclusive.
    def validate(self, token: str) -> tuple[bool, str]:
        """Validate a token. Returns (valid, identity)."""
        h = self._hash(token)
        with self._lock:
            t = self._tokens.get(h)
        t = t or self._persistent_token(h)

Comment thread .github/workflows/ci.yml
Comment on lines 25 to +28
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
@justyns
justyns force-pushed the ci/portable-workflow branch from 256785a to 9721025 Compare August 2, 2026 02:39
Copilot AI review requested due to automatic review settings August 2, 2026 02:39
@justyns
justyns force-pushed the ci/portable-workflow branch from 9721025 to f68da69 Compare August 2, 2026 02:59
Copilot stopped reviewing on behalf of justyns due to an error August 2, 2026 03:04

Copilot AI left a comment

Copy link
Copy Markdown

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 8 out of 8 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

plugins/tsugite-daemon/tsugite_daemon/auth.py:165

  • Locking in validate() is currently split across multiple sections, which allows a concrete race with revoke(): a thread can read an ephemeral token under the lock (line 156–157), release the lock, then another thread revokes the token, and the first thread still returns True based on the stale t reference. To make validation linearizable for the in-memory token map, hold self._lock for the whole validation path that depends on _tokens (lookup + expiry check + potential removal), and (since this is an RLock) you can also perform the persistent lookup within the same critical section if desired.
    def validate(self, token: str) -> tuple[bool, str]:
        """Validate a token. Returns (valid, identity)."""
        h = self._hash(token)
        with self._lock:
            t = self._tokens.get(h)
        t = t or self._persistent_token(h)
        if not t:
            return False, ""
        if t.expires_at and t.expires_at < datetime.now(timezone.utc).isoformat():
            with self._lock:
                self._tokens.pop(h, None)
            return False, ""
        return True, t.identity

Comment thread .github/workflows/ci.yml
Comment on lines +26 to +28
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
Copilot AI review requested due to automatic review settings August 2, 2026 03:05

Copilot AI left a comment

Copy link
Copy Markdown

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 8 out of 8 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

.github/workflows/ci.yml:28

  • The curl | sh pipeline can mask installer failures because the default bash -e doesn’t enable pipefail. If curl fails, sh may still exit 0 and the step can proceed with uv missing, producing confusing downstream errors. Add set -o pipefail (or set -euo pipefail) before the pipeline so the step fails reliably on download errors.
        run: |
          curl -LsSf https://astral.sh/uv/install.sh | sh
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"

.github/workflows/ci.yml:53

  • Same curl | sh pipeline issue here: without pipefail, a failed download can still result in a successful step status, making later failures harder to diagnose. Add set -o pipefail (or set -euo pipefail) before the pipeline.
        run: |
          curl -LsSf https://astral.sh/uv/install.sh | sh
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"

Comment on lines 153 to +157
def validate(self, token: str) -> tuple[bool, str]:
"""Validate a token. Returns (valid, identity)."""
h = self._hash(token)
t = self._tokens.get(h) or self._persistent_token(h)
with self._lock:
t = self._tokens.get(h)
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.

2 participants