fix: address Qodo review findings on CI/release hardening

- setup-semantica action: pass extras/version through env vars instead
  of interpolating ${{ inputs.* }} directly into the bash script, which
  was a script-injection vector for any caller deriving these from
  event/matrix data
- install-matrix: trigger on the Release workflow's completion
  (workflow_run) instead of `release: published`, since the GitHub
  release is created before the PyPI upload runs - the old trigger
  could race the publish and silently verify the prior version; also
  assert the installed version matches the triggering release tag
- examples/ci/github-actions.yml: pin actions/checkout and
  actions/setup-python to the same verified commit SHAs used elsewhere
  in this repo instead of mutable v5/v6 tags, and document how to pin
  the setup-semantica@main reference for production use
- examples/ci templates + README: make the requirements.txt install
  step conditional (guard with `-f requirements.txt`) and call out
  pyproject.toml/Poetry/Pipenv as alternatives, since the templates
  previously assumed every project has a requirements.txt; CircleCI's
  cache key also no longer hashes a file that may not exist
This commit is contained in:
KaifAhmad1
2026-08-30 16:41:46 +05:30
parent 5d63b2faeb
commit 302d0a2d75
6 changed files with 70 additions and 14 deletions
+7 -3
View File
@@ -31,13 +31,17 @@ runs:
- name: Install semantica
shell: bash
env:
SEMANTICA_EXTRAS: ${{ inputs.extras }}
SEMANTICA_VERSION: ${{ inputs.version }}
run: |
python -m pip install --upgrade pip
if [ -n "${{ inputs.extras }}" ]; then
pip install "semantica[${{ inputs.extras }}]${{ inputs.version }}"
if [ -n "$SEMANTICA_EXTRAS" ]; then
spec="semantica[$SEMANTICA_EXTRAS]$SEMANTICA_VERSION"
else
pip install "semantica${{ inputs.version }}"
spec="semantica$SEMANTICA_VERSION"
fi
python -m pip install -- "$spec"
- name: Verify install
id: verify
+24 -3
View File
@@ -6,12 +6,19 @@ permissions:
on:
schedule:
- cron: '0 6 * * 1' # weekly, catches upstream dependency breakage between releases
release:
types: [published]
workflow_run:
# The Release workflow publishes the GitHub release *before* it uploads to
# PyPI (see release.yml), so triggering on `release: published` would race
# the PyPI upload and could pass by silently installing the prior version.
# workflow_run fires only after the whole Release workflow - including the
# PyPI publish step - has finished.
workflows: ['Release']
types: [completed]
workflow_dispatch:
jobs:
verify-install:
if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success'
name: pip install semantica (${{ matrix.os }}, py${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
strategy:
@@ -21,7 +28,8 @@ jobs:
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: ./.github/actions/setup-semantica
- id: setup-semantica
uses: ./.github/actions/setup-semantica
with:
python-version: ${{ matrix.python-version }}
@@ -32,3 +40,16 @@ jobs:
import semantica
print('semantica', semantica.__version__, 'installed and importable')
"
- name: Verify version matches the release that triggered this run
if: github.event_name == 'workflow_run'
shell: bash
env:
EXPECTED_TAG: ${{ github.event.workflow_run.head_branch }}
INSTALLED_VERSION: ${{ steps.setup-semantica.outputs.version }}
run: |
expected="${EXPECTED_TAG#v}"
if [ -n "$expected" ] && [ "$expected" != "$INSTALLED_VERSION" ]; then
echo "::error::pip installed semantica $INSTALLED_VERSION but the release that triggered this run was $EXPECTED_TAG - PyPI may still be propagating, or the publish failed."
exit 1
fi
+10 -1
View File
@@ -3,7 +3,9 @@
Copy-paste starting points for wiring `semantica` into your own project's CI. Each file is a
complete, working config — rename it into your project (see the comment at the top of each file
for the target path) and swap the smoke-test / test step for whatever your project does with
Semantica.
Semantica. Each template installs `semantica` unconditionally and your own project's dependencies
only if a `requirements.txt` is present; if your project uses `pyproject.toml`, Poetry, or Pipenv
instead, adjust the marked install line (each file calls it out inline).
| File | Target path in your repo |
| ---- | ------------------------- |
@@ -22,5 +24,12 @@ Semantica's reusable composite action instead:
# version: '==0.6.7' # optional, pin an exact release
```
`@main` always tracks this repo's default branch, which is convenient but — like any mutable
ref — can change out from under you between runs. For production CI, pin it to a commit SHA
instead (find one via `git rev-parse` against a tagged release, or the commit history for
[`.github/actions/setup-semantica/`](../../.github/actions/setup-semantica/)) and update the pin
deliberately when you want to pick up changes, the same way this repo's own workflows are pinned
(see [`verify-action-pins.yml`](../../.github/workflows/verify-action-pins.yml)).
It installs Python, caches pip, installs `semantica`, and verifies the import — see
[`.github/actions/setup-semantica/action.yml`](../../.github/actions/setup-semantica/action.yml).
+10 -3
View File
@@ -7,17 +7,24 @@ jobs:
- image: cimg/python:3.11
steps:
- checkout
# A content-hashed cache key (e.g. `{{ checksum "requirements.txt" }}`)
# is more precise but breaks if that exact file doesn't exist in your
# project - swap in one matched to however you declare dependencies
# once you've adjusted the install step below.
- restore_cache:
keys:
- pip-cache-{{ checksum "requirements.txt" }}
- pip-cache-v1
- run:
name: Install dependencies
command: |
pip install --upgrade pip
pip install semantica
pip install -r requirements.txt # your project's own dependencies
# Install your own project's dependencies however your project
# declares them - adjust this to match, e.g. `pip install -e .`
# for pyproject.toml / setup.cfg, or `poetry install`.
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- save_cache:
key: pip-cache-{{ checksum "requirements.txt" }}
key: pip-cache-v1
paths:
- ~/.cache/pip
- run:
+15 -3
View File
@@ -3,6 +3,12 @@
# Installs Semantica and runs a smoke import + your test suite. Swap the
# smoke-test step for whatever your project actually does with Semantica
# (build a context graph, run an ingest pipeline, etc.).
#
# Third-party actions below are pinned to a commit SHA rather than a mutable
# tag - a moved tag can silently swap in different code. Update the pin (and
# the trailing "# vX" comment) deliberately when you want a newer version;
# see semantica-agi/semantica's own .github/workflows/verify-action-pins.yml
# for one way to keep pins honest automatically.
name: Semantica
on:
@@ -15,9 +21,9 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-python@v6
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: '3.11'
cache: 'pip'
@@ -26,7 +32,13 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install semantica
pip install -r requirements.txt # your project's own dependencies
# Install your own project's dependencies however your project
# declares them - adjust this to match. Examples:
# pip install -r requirements.txt
# pip install -e . # pyproject.toml / setup.cfg
# pip install -e ".[dev]"
# poetry install
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Run tests
run: pytest
+4 -1
View File
@@ -9,7 +9,10 @@ semantica-test:
script:
- pip install --upgrade pip
- pip install semantica
- pip install -r requirements.txt # your project's own dependencies
# Install your own project's dependencies however your project declares
# them - adjust this to match, e.g. `pip install -e .` for pyproject.toml
# / setup.cfg, or `poetry install`.
- if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- python -c "import semantica; print('semantica', semantica.__version__)"
- pytest
rules: