feat: add GitHub Actions CI workflow#4240
Conversation
📝 WalkthroughWalkthroughAdds a GitHub Actions Python CI workflow and applies defensive/refactor edits across frontend composables and utils: async/await migration, stricter type checks, parsing normalization, small cleanup for downloads, and minor formatting/hash tweaks. ChangesPython CI Workflow
JS defensive refactors and small API changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR introduces an additional GitHub Actions workflow intended to run CI checks. However, the added workflow targets Python tooling (pip/flake8/mypy/pytest) while this repository appears to be a Vue/TypeScript project with an existing Node/pnpm CI workflow already in place.
Changes:
- Added a new GitHub Actions workflow:
Python CI - Configured a Python version matrix and steps for dependency install, linting, type checking, and tests
Comments suppressed due to low confidence (2)
.github/workflows/python-ci.yml:33
- The test command chain masks real failures: if
pytestexits non-zero due to failing tests, the workflow will fall back to unittest (or just echo a message) and still exit 0. CI should fail when tests fail; if you need to support different test runners, detect which one is configured and run exactly that (or explicitly fail if none is configured).
- name: Run tests
run: |
pytest --tb=short --cov=. --cov-report=term-missing 2>/dev/null || python -m unittest discover 2>/dev/null || echo "No test framework found"
.github/workflows/python-ci.yml:30
mypy ... || echo "mypy not configured"will also hide genuine type-checking failures (non-zero exit) and let CI pass. If mypy is optional, gate the step on the presence of a config file (e.g., mypy.ini/pyproject.toml) rather than swallowing all failures.
- name: Type check with mypy
run: |
mypy . --ignore-missing-imports 2>/dev/null || echo "mypy not configured"
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| name: Python CI | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main, master ] | ||
| pull_request: | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ['3.9', '3.10', '3.11', '3.12'] |
| pip install -e . 2>/dev/null || pip install -r requirements.txt 2>/dev/null || true | ||
| pip install pytest pytest-cov flake8 mypy | ||
| - name: Lint with flake8 | ||
| run: | | ||
| flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics | ||
| - name: Type check with mypy | ||
| run: | | ||
| mypy . --ignore-missing-imports 2>/dev/null || echo "mypy not configured" | ||
| - name: Run tests | ||
| run: | | ||
| pytest --tb=short --cov=. --cov-report=term-missing 2>/dev/null || python -m unittest discover 2>/dev/null || echo "No test framework found" |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/python-ci.yml:
- Around line 1-33: The workflow currently runs a Python "test" job using steps
named "Lint with flake8", "Type check with mypy", and "Run tests" which doesn't
match the PR's Vue/TypeScript target; replace the Python-specific steps and
tools with Node/TypeScript equivalents: change the job to install Node using
actions/setup-node, run npm/yarn install, run ESLint for linting (replace "Lint
with flake8"), run the TypeScript compiler or tsc/tsserver for type checks
(replace "Type check with mypy"), and run the project's test runner
(jest/vitest) in lieu of "Run tests"; update the matrix to use Node versions
instead of python-version and adapt the step names (e.g., "Set up Node",
"Install dependencies", "Lint with ESLint", "Type check with tsc", "Run tests
with jest") so the CI actually validates the Vue/TypeScript stack.
- Around line 28-33: The CI is masking failures in the "Type check with mypy"
and "Run tests" steps by redirecting stderr and using "|| echo ..." to force
success; remove the stderr redirections (2>/dev/null) and the fallback "|| echo
..." from the "Type check with mypy" and "Run tests" steps so mypy and
pytest/unittest return non-zero on failure and their output is preserved,
allowing the workflow steps to fail the job properly (look for the step names
"Type check with mypy" and "Run tests" in the diff).
- Around line 21-24: The CI step named "Install dependencies" currently uses
"pip install -e . 2>/dev/null || pip install -r requirements.txt 2>/dev/null ||
true", which masks failures; remove the "|| true" and stop redirecting stderr so
the job fails on install errors (e.g. change to a fallback like "pip install -e
. || pip install -r requirements.txt" and drop "2>/dev/null"), ensuring the step
fails when neither install succeeds and surfaces error output for debugging.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d46fb3af-e99e-48d7-b383-7e31900ee41c
📒 Files selected for processing (1)
.github/workflows/python-ci.yml
| name: Python CI | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main, master ] | ||
| pull_request: | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ['3.9', '3.10', '3.11', '3.12'] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Set up Python ${{ matrix.python-version }} | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
| cache: 'pip' | ||
| - name: Install dependencies | ||
| run: | | ||
| pip install -e . 2>/dev/null || pip install -r requirements.txt 2>/dev/null || true | ||
| pip install pytest pytest-cov flake8 mypy | ||
| - name: Lint with flake8 | ||
| run: | | ||
| flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics | ||
| - name: Type check with mypy | ||
| run: | | ||
| mypy . --ignore-missing-imports 2>/dev/null || echo "mypy not configured" | ||
| - name: Run tests | ||
| run: | | ||
| pytest --tb=short --cov=. --cov-report=term-missing 2>/dev/null || python -m unittest discover 2>/dev/null || echo "No test framework found" |
There was a problem hiding this comment.
Workflow does not match the stated project CI target.
This workflow validates Python (flake8, mypy, pytest) while the PR objective says CI should target a Vue/TypeScript project. As written, it won’t gate the intended stack.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/python-ci.yml around lines 1 - 33, The workflow currently
runs a Python "test" job using steps named "Lint with flake8", "Type check with
mypy", and "Run tests" which doesn't match the PR's Vue/TypeScript target;
replace the Python-specific steps and tools with Node/TypeScript equivalents:
change the job to install Node using actions/setup-node, run npm/yarn install,
run ESLint for linting (replace "Lint with flake8"), run the TypeScript compiler
or tsc/tsserver for type checks (replace "Type check with mypy"), and run the
project's test runner (jest/vitest) in lieu of "Run tests"; update the matrix to
use Node versions instead of python-version and adapt the step names (e.g., "Set
up Node", "Install dependencies", "Lint with ESLint", "Type check with tsc",
"Run tests with jest") so the CI actually validates the Vue/TypeScript stack.
| - name: Install dependencies | ||
| run: | | ||
| pip install -e . 2>/dev/null || pip install -r requirements.txt 2>/dev/null || true | ||
| pip install pytest pytest-cov flake8 mypy |
There was a problem hiding this comment.
Dependency install step can silently succeed after total failure.
|| true makes this step pass even if both install paths fail, so later steps run in an invalid environment and CI can still appear green.
Suggested fix
- name: Install dependencies
run: |
- pip install -e . 2>/dev/null || pip install -r requirements.txt 2>/dev/null || true
- pip install pytest pytest-cov flake8 mypy
+ set -euo pipefail
+ python -m pip install --upgrade pip
+ if [ -f pyproject.toml ] || [ -f setup.py ]; then
+ python -m pip install -e .
+ elif [ -f requirements.txt ]; then
+ python -m pip install -r requirements.txt
+ else
+ echo "No Python dependency manifest found" >&2
+ exit 1
+ fi
+ python -m pip install pytest pytest-cov flake8 mypy📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Install dependencies | |
| run: | | |
| pip install -e . 2>/dev/null || pip install -r requirements.txt 2>/dev/null || true | |
| pip install pytest pytest-cov flake8 mypy | |
| - name: Install dependencies | |
| run: | | |
| set -euo pipefail | |
| python -m pip install --upgrade pip | |
| if [ -f pyproject.toml ] || [ -f setup.py ]; then | |
| python -m pip install -e . | |
| elif [ -f requirements.txt ]; then | |
| python -m pip install -r requirements.txt | |
| else | |
| echo "No Python dependency manifest found" >&2 | |
| exit 1 | |
| fi | |
| python -m pip install pytest pytest-cov flake8 mypy |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/python-ci.yml around lines 21 - 24, The CI step named
"Install dependencies" currently uses "pip install -e . 2>/dev/null || pip
install -r requirements.txt 2>/dev/null || true", which masks failures; remove
the "|| true" and stop redirecting stderr so the job fails on install errors
(e.g. change to a fallback like "pip install -e . || pip install -r
requirements.txt" and drop "2>/dev/null"), ensuring the step fails when neither
install succeeds and surfaces error output for debugging.
| - name: Type check with mypy | ||
| run: | | ||
| mypy . --ignore-missing-imports 2>/dev/null || echo "mypy not configured" | ||
| - name: Run tests | ||
| run: | | ||
| pytest --tb=short --cov=. --cov-report=term-missing 2>/dev/null || python -m unittest discover 2>/dev/null || echo "No test framework found" |
There was a problem hiding this comment.
Type-check and test failures are currently masked.
Both steps convert failures into success (|| echo ...), which defeats CI quality gates.
Suggested fix
- name: Type check with mypy
run: |
- mypy . --ignore-missing-imports 2>/dev/null || echo "mypy not configured"
+ set -euo pipefail
+ if find . -name "*.py" -o -name "*.pyi" | grep -q .; then
+ mypy . --ignore-missing-imports
+ else
+ echo "No Python files; skipping mypy"
+ fi
- name: Run tests
run: |
- pytest --tb=short --cov=. --cov-report=term-missing 2>/dev/null || python -m unittest discover 2>/dev/null || echo "No test framework found"
+ set -euo pipefail
+ if [ -d tests ] || find . -name "test_*.py" | grep -q .; then
+ pytest --tb=short --cov=. --cov-report=term-missing
+ else
+ echo "No Python tests discovered; skipping"
+ fi🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/python-ci.yml around lines 28 - 33, The CI is masking
failures in the "Type check with mypy" and "Run tests" steps by redirecting
stderr and using "|| echo ..." to force success; remove the stderr redirections
(2>/dev/null) and the fallback "|| echo ..." from the "Type check with mypy" and
"Run tests" steps so mypy and pytest/unittest return non-zero on failure and
their output is preserved, allowing the workflow steps to fail the job properly
(look for the step names "Type check with mypy" and "Run tests" in the diff).
…ation - useApi.js: Convert to async/await, add HTTP error checking, fix hashCode bitwise operation - useFormatting.js: Replace var with const/let, fix seconds calculation bug, improve addCommas - useMisc.js: Replace var with const/let, add URL.revokeObjectURL to prevent memory leak - usePreferences.js: Fix testLocalStorage validation, simplify boolean checks - HtmlUtils.js: Add input validation, pre-compile regex patterns for performance - Misc.js: Add input validation, fix parseInt radix, return proper boolean from isEmail
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/composables/useFormatting.js (1)
18-18: ⚡ Quick winConsider removing
.toFixed(3)to avoid implicit type coercion.
parseFloat(duration).toFixed(3)returns a string (e.g.,"123.456"), which is then implicitly coerced back to a number in the subsequent math operations (lines 19-21). This works but is confusing and non-idiomatic.Unless rounding to 3 decimal places before calculation is specifically required, simplify to:
const time = parseFloat(duration);♻️ Proposed refactor
- const time = parseFloat(duration).toFixed(3); + const time = parseFloat(duration);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/composables/useFormatting.js` at line 18, The code uses parseFloat(duration).toFixed(3) which produces a string and causes implicit coercion later; in useFormatting.js update the assignment that creates time (the variable created from parseFloat(duration)) to use parseFloat(duration) (a number) instead of .toFixed(3), and if desired add a NaN guard (e.g., check isNaN(time) and default to 0) so subsequent math in the formatting functions operates on a numeric value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/composables/useApi.js`:
- Line 6: The iteration over params using "for (const param in params)" in
useApi.js can include inherited properties; change it to iterate only own keys
(e.g., use Object.keys(params) or Object.entries(params)) or check
hasOwnProperty before calling url.searchParams.set so only own properties are
added; update the loop that sets URL search params in the useApi (or the
function that constructs the URL) to use Object.keys/entries or an explicit
ownership check.
---
Nitpick comments:
In `@src/composables/useFormatting.js`:
- Line 18: The code uses parseFloat(duration).toFixed(3) which produces a string
and causes implicit coercion later; in useFormatting.js update the assignment
that creates time (the variable created from parseFloat(duration)) to use
parseFloat(duration) (a number) instead of .toFixed(3), and if desired add a NaN
guard (e.g., check isNaN(time) and default to 0) so subsequent math in the
formatting functions operates on a numeric value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 541f1d38-42c2-4f50-9dbe-40226e1bd231
📒 Files selected for processing (6)
src/composables/useApi.jssrc/composables/useFormatting.jssrc/composables/useMisc.jssrc/composables/usePreferences.jssrc/utils/HtmlUtils.jssrc/utils/Misc.js
| if (params) { | ||
| url = new URL(url); | ||
| for (var param in params) url.searchParams.set(param, params[param]); | ||
| for (const param in params) url.searchParams.set(param, params[param]); |
There was a problem hiding this comment.
Guard against prototype pollution in parameter iteration.
The for...in loop iterates over all enumerable properties including inherited ones from the prototype chain. This could inadvertently add unexpected properties to the URL search parameters if params has inherited properties.
🛡️ Proposed fix using Object.entries()
- for (const param in params) url.searchParams.set(param, params[param]);
+ for (const [param, value] of Object.entries(params)) url.searchParams.set(param, value);Alternatively, use Object.keys():
- for (const param in params) url.searchParams.set(param, params[param]);
+ for (const param of Object.keys(params)) url.searchParams.set(param, params[param]);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (const param in params) url.searchParams.set(param, params[param]); | |
| for (const [param, value] of Object.entries(params)) url.searchParams.set(param, value); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/composables/useApi.js` at line 6, The iteration over params using "for
(const param in params)" in useApi.js can include inherited properties; change
it to iterate only own keys (e.g., use Object.keys(params) or
Object.entries(params)) or check hasOwnProperty before calling
url.searchParams.set so only own properties are added; update the loop that sets
URL search params in the useApi (or the function that constructs the URL) to use
Object.keys/entries or an explicit ownership check.
|
UNSUBSCRIBE
…On Tue, May 19, 2026 at 8:21 PM coderabbitai[bot] ***@***.***> wrote:
***@***.***[bot]* commented on this pull request.
*Actionable comments posted: 1*
🧹 Nitpick comments (1)
src/composables/useFormatting.js (1)
18-18: *⚡ Quick win*
*Consider removing .toFixed(3) to avoid implicit type coercion.*
parseFloat(duration).toFixed(3) returns a string (e.g., "123.456"), which
is then implicitly coerced back to a number in the subsequent math
operations (lines 19-21). This works but is confusing and non-idiomatic.
Unless rounding to 3 decimal places before calculation is specifically
required, simplify to:
const time = parseFloat(duration);
♻️ Proposed refactor
- const time = parseFloat(duration).toFixed(3);+ const time = parseFloat(duration);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In ***@***.***/composables/useFormatting.js` at line 18, The code uses
parseFloat(duration).toFixed(3) which produces a string and causes implicit
coercion later; in useFormatting.js update the assignment that creates time (the
variable created from parseFloat(duration)) to use parseFloat(duration) (a
number) instead of .toFixed(3), and if desired add a NaN guard (e.g., check
isNaN(time) and default to 0) so subsequent math in the formatting functions
operates on a numeric value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In ***@***.***/composables/useApi.js`:
- Line 6: The iteration over params using "for (const param in params)" in
useApi.js can include inherited properties; change it to iterate only own keys
(e.g., use Object.keys(params) or Object.entries(params)) or check
hasOwnProperty before calling url.searchParams.set so only own properties are
added; update the loop that sets URL search params in the useApi (or the
function that constructs the URL) to use Object.keys/entries or an explicit
ownership check.
---
Nitpick comments:
In ***@***.***/composables/useFormatting.js`:
- Line 18: The code uses parseFloat(duration).toFixed(3) which produces a string
and causes implicit coercion later; in useFormatting.js update the assignment
that creates time (the variable created from parseFloat(duration)) to use
parseFloat(duration) (a number) instead of .toFixed(3), and if desired add a NaN
guard (e.g., check isNaN(time) and default to 0) so subsequent math in the
formatting functions operates on a numeric value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
------------------------------
ℹ️ Review info ⚙️ Run configuration
*Configuration used*: Path: .coderabbit.yaml
*Review profile*: CHILL
*Plan*: Pro
*Run ID*: 541f1d38-42c2-4f50-9dbe-40226e1bd231
📥 Commits
Reviewing files that changed from the base of the PR and between eaca29a
and d72a307.
📒 Files selected for processing (6)
- src/composables/useApi.js
- src/composables/useFormatting.js
- src/composables/useMisc.js
- src/composables/usePreferences.js
- src/utils/HtmlUtils.js
- src/utils/Misc.js
------------------------------
In src/composables/useApi.js:
> if (params) {
url = new URL(url);
- for (var param in params) url.searchParams.set(param, params[param]);
+ for (const param in params) url.searchParams.set(param, params[param]);
*
|
Summary
This PR adds GitHub Actions CI workflow for automated testing and linting.
Changes Made
Checklist
Submitted via OSS PR Campaign by Kral
Summary by CodeRabbit
Chores
Bug Fixes / Improvements