Skip to content

Commit ee9405c

Browse files
Copilotlstein
andcommitted
Add linting tools configuration for backend (Ruff) and frontend (ESLint/Prettier)
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
1 parent 2a3dc8e commit ee9405c

84 files changed

Lines changed: 5109 additions & 4059 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/copilot-instructions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ PhotoMapAI/
4242
- Prefer f-strings for string formatting
4343
- Use pathlib.Path for file path operations instead of os.path
4444
- Import organization: standard library → third-party → local imports
45+
- Python files must pass ruff check
4546

4647
#### JavaScript
4748
- Use ES6 modules with explicit imports/exports
4849
- Use const/let instead of var
4950
- Use descriptive function and variable names
5051
- Add comments for complex logic, especially in event handlers
5152
- Follow existing file structure: one module per file with clear responsibilities
53+
- JavaScript files must pass `npm lint` and `npm run format:check`
5254

5355
### Testing
5456

.github/workflows/deploy.yml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,61 @@ name: Deploy Release
22

33
on:
44
workflow_dispatch:
5-
release:
5+
release:
66
types: [published]
7+
78
jobs:
8-
tag-release:
9+
tag-release:
910
runs-on: ubuntu-latest
11+
outputs:
12+
version: ${{ steps.get_version.outputs.version }}
13+
tag: ${{ steps.get_version.outputs.tag }}
1014
steps:
1115
- name: Checkout code
1216
uses: actions/checkout@v4
1317

1418
- name: Set up Python
1519
uses: actions/setup-python@v5
16-
with:
20+
with:
1721
python-version: '3.12'
1822

1923
- name: Extract version from pyproject.toml
2024
id: get_version
2125
run: |
2226
VERSION=$(python -c "
23-
try:
27+
try:
2428
import tomllib
2529
with open('pyproject.toml', 'rb') as f:
2630
data = tomllib.load(f)
2731
print(data['project']['version'])
2832
except Exception as e:
33+
import sys
2934
print(f'Error reading version: {e}', file=sys.stderr)
3035
exit(1)
3136
")
3237
echo "version=$VERSION" >> $GITHUB_OUTPUT
38+
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
39+
40+
- name: Check if tag exists
41+
id: check_tag
42+
run: |
43+
if git ls-remote --tags origin | grep -q "refs/tags/v${{ steps.get_version.outputs.version }}"; then
44+
echo "Tag already exists"
45+
echo "exists=true" >> $GITHUB_OUTPUT
46+
else
47+
echo "Tag does not exist"
48+
echo "exists=false" >> $GITHUB_OUTPUT
49+
fi
3350
3451
- name: Tag the release
52+
if: steps.check_tag.outputs.exists == 'false'
3553
run: |
3654
git config user.name "github-actions"
3755
git config user.email "github-actions@github.com"
3856
git tag v${{ steps.get_version.outputs.version }}
3957
git push origin v${{ steps.get_version.outputs.version }}
4058
41-
deploy-pypi:
59+
deploy-pypi:
4260
needs: tag-release
4361
uses: ./.github/workflows/deploy-pypi.yml
4462
secrets:
@@ -56,5 +74,7 @@ jobs:
5674
uses: ./.github/workflows/deploy-pyinstaller.yml
5775

5876
upload-release:
59-
needs: [deploy-pypi, deploy-dockerhub, deploy-pyinstaller]
77+
needs: [tag-release, deploy-pypi, deploy-dockerhub, deploy-pyinstaller]
6078
uses: ./.github/workflows/upload-artifacts.yml
79+
with:
80+
tag_name: ${{ needs.tag-release.outputs.tag }}

.github/workflows/lint.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Lint Code
2+
3+
on:
4+
push:
5+
branches: [ master, main ]
6+
pull_request:
7+
branches: [ master, main ]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
backend-lint:
14+
name: Backend Linting (Ruff)
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: '3.10'
25+
26+
- name: Install dependencies
27+
run: |
28+
python -m pip install --upgrade pip
29+
pip install .[development]
30+
31+
- name: Run Ruff
32+
run: |
33+
ruff check photomap tests
34+
35+
frontend-lint:
36+
name: Frontend Linting (ESLint & Prettier)
37+
runs-on: ubuntu-latest
38+
39+
steps:
40+
- name: Checkout code
41+
uses: actions/checkout@v4
42+
43+
- name: Set up Node.js
44+
uses: actions/setup-node@v4
45+
with:
46+
node-version: '20'
47+
cache: 'npm'
48+
49+
- name: Install dependencies
50+
run: npm ci
51+
52+
- name: Run ESLint
53+
run: npm run lint
54+
55+
- name: Run Prettier check
56+
run: npm run format:check
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
name: Upload Release Artifacts
22

33
on:
4-
workflow_call:
4+
workflow_call:
5+
inputs:
6+
tag_name:
7+
required: true
8+
type: string
9+
510
jobs:
6-
upload-release:
11+
upload-release:
712
runs-on: ubuntu-latest
813
steps:
914
- name: Download CPU installer package artifacts
1015
uses: actions/download-artifact@v4
11-
with:
16+
with:
1217
pattern: "*-cpu-*"
1318
path: artifacts
1419

@@ -18,6 +23,7 @@ jobs:
1823
- name: Upload artifacts to GitHub Release
1924
uses: softprops/action-gh-release@v2
2025
with:
26+
tag_name: ${{ inputs.tag_name }}
2127
files: artifacts/*-cpu-*/*
2228
env:
2329
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.prettierignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
node_modules
2+
dist
3+
build
4+
coverage
5+
.pytest_cache
6+
__pycache__
7+
*.min.js
8+
package-lock.json
9+
*.pyc

.prettierrc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "es5",
4+
"singleQuote": false,
5+
"printWidth": 120,
6+
"tabWidth": 2,
7+
"useTabs": false,
8+
"arrowParens": "always",
9+
"endOfLine": "lf"
10+
}

Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ help:
1111
@echo "docker-demo Build the Docker demo site image."
1212
@echo "docs Serve the mkdocs site with live reload."
1313
@echo "deploy-docs Deploy the mkdocs site to GitHub pages."
14+
@echo "backend-lint Run Python backend linting with Ruff."
15+
@echo "frontend-lint Run JavaScript frontend linting with ESLint and Prettier."
16+
@echo "lint Run both backend and frontend linting."
1417

1518
# Run the unit tests
1619
test:
@@ -48,3 +51,26 @@ docs:
4851

4952
deploy-docs:
5053
mkdocs gh-deploy
54+
55+
# Run backend linting with Ruff
56+
# fix with ruff check photomap tests photomap --fix
57+
.PHONY: backend-lint
58+
backend-lint:
59+
@echo "Running Ruff on Python backend..."
60+
ruff check photomap tests photomap
61+
62+
# Run frontend linting with ESLint and Prettier
63+
# Fix with npm run lint:fix
64+
# npm run format
65+
.PHONY: frontend-lint
66+
frontend-lint:
67+
@echo "Installing npm dependencies if needed..."
68+
npm install
69+
@echo "Running ESLint on JavaScript frontend..."
70+
npm run lint
71+
@echo "Running Prettier check on JavaScript frontend..."
72+
npm run format:check
73+
74+
# Run both backend and frontend linting
75+
.PHONY: lint
76+
lint: backend-lint frontend-lint

eslint.config.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
export default [
2+
{
3+
ignores: [
4+
'**/node_modules/**',
5+
'**/dist/**',
6+
'**/build/**',
7+
'**/.pytest_cache/**',
8+
'**/__pycache__/**',
9+
'**/coverage/**',
10+
],
11+
},
12+
{
13+
files: ['**/*.js'],
14+
languageOptions: {
15+
ecmaVersion: 2022,
16+
sourceType: 'module',
17+
globals: {
18+
// Browser globals
19+
window: 'readonly',
20+
document: 'readonly',
21+
console: 'readonly',
22+
localStorage: 'readonly',
23+
sessionStorage: 'readonly',
24+
fetch: 'readonly',
25+
FormData: 'readonly',
26+
URLSearchParams: 'readonly',
27+
URL: 'readonly',
28+
setTimeout: 'readonly',
29+
clearTimeout: 'readonly',
30+
setInterval: 'readonly',
31+
clearInterval: 'readonly',
32+
alert: 'readonly',
33+
confirm: 'readonly',
34+
prompt: 'readonly',
35+
CustomEvent: 'readonly',
36+
Event: 'readonly',
37+
MouseEvent: 'readonly',
38+
KeyboardEvent: 'readonly',
39+
TouchEvent: 'readonly',
40+
ResizeObserver: 'readonly',
41+
IntersectionObserver: 'readonly',
42+
MutationObserver: 'readonly',
43+
HTMLElement: 'readonly',
44+
Element: 'readonly',
45+
Node: 'readonly',
46+
NodeList: 'readonly',
47+
Blob: 'readonly',
48+
File: 'readonly',
49+
FileReader: 'readonly',
50+
Image: 'readonly',
51+
navigator: 'readonly',
52+
performance: 'readonly',
53+
requestAnimationFrame: 'readonly',
54+
getComputedStyle: 'readonly',
55+
// Plotly global (used in umap.js)
56+
Plotly: 'readonly',
57+
// Swiper global (used in swiper.js)
58+
Swiper: 'readonly',
59+
},
60+
},
61+
rules: {
62+
// Possible errors
63+
'no-console': 'off',
64+
'no-debugger': 'warn',
65+
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
66+
'no-undef': 'error',
67+
68+
// Best practices
69+
'eqeqeq': ['error', 'always'],
70+
'curly': ['error', 'all'],
71+
'no-eval': 'error',
72+
'no-implied-eval': 'error',
73+
'no-with': 'error',
74+
'no-new-func': 'error',
75+
76+
// ES6+
77+
'prefer-const': 'warn',
78+
'no-var': 'warn',
79+
'prefer-arrow-callback': 'warn',
80+
'arrow-spacing': 'error',
81+
82+
// Style (mostly handled by Prettier, but some logical style rules)
83+
// Note: quotes handled by Prettier, semi retained for logical consistency
84+
'semi': ['error', 'always'],
85+
},
86+
},
87+
{
88+
files: ['tests/**/*.js', '**/*.test.js'],
89+
languageOptions: {
90+
globals: {
91+
// Jest globals
92+
describe: 'readonly',
93+
it: 'readonly',
94+
test: 'readonly',
95+
expect: 'readonly',
96+
beforeEach: 'readonly',
97+
afterEach: 'readonly',
98+
beforeAll: 'readonly',
99+
afterAll: 'readonly',
100+
jest: 'readonly',
101+
global: 'readonly',
102+
},
103+
},
104+
},
105+
];

0 commit comments

Comments
 (0)