Skip to content

Commit 92119f4

Browse files
m4dm4rtig4nClément VALENTINclaudesemantic-release-bot
authored
Develop (#85)
* fix(api): resolve all ruff linting errors - Add TYPE_CHECKING imports for SQLAlchemy forward references - Fix SQLAlchemy boolean comparisons (use .is_(True) instead of == True) - Fix SQLAlchemy None comparisons (use .is_(None) instead of == None) - Remove unused imports and variables - Remove f-strings without placeholders 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): resolve all 204 mypy type errors - Add TYPE_CHECKING imports for forward references - Fix implicit Optional (str = None → str | None = None) - Add missing return type annotations - Use cast() for Any returns - Fix SQLAlchemy ORM assignments with type ignore - Fix variable reuse confusion (renamed result variables) - Add assertions for None checks before returns - Fix AsyncGenerator return type for database session All 62 source files now pass mypy --ignore-missing-imports 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): remove unused imports 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ci): add pre-commit hooks for linting Add pre-commit configuration with hooks for: - ruff (lint + format) for backend Python code - mypy type checking for backend - eslint for frontend TypeScript/React - tsc type checking for frontend 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ci): add mypy to dependency-groups for CI type checking The CI workflow uses `uv sync` which relies on [dependency-groups], not [project.optional-dependencies]. Added mypy and cleaned up duplicate dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(release): 1.1.0-dev.1 [skip ci] * fix(ci): use semantic-release action for proper GitHub outputs The previous npx semantic-release command did not set GitHub Actions outputs, causing Docker builds to be skipped. Using the official action ensures new_release_published and new_release_version are properly exposed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ci): add extra_plugins for semantic-release action The cycjimmy action uses its own semantic-release installation, so additional plugins must be specified via extra_plugins input. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(release): 1.1.0-dev.2 [skip ci] * fix(helm): correct postgres/valkey condition and configmap references - Fix Chart.yaml: change postgresql.enabled to postgres.enabled condition - Fix configmap.yaml: update redis references to valkey 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(release): 1.1.0-dev.3 [skip ci] * feat(helm): migrate from Redis to Valkey - Replace CloudPirates Redis subchart with Valkey 0.13.0 - Update _helpers.tpl with valkey.* helpers - Fix secret key to use 'password' (CloudPirates default) - Update values.yaml for Valkey configuration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(release): 1.1.0-dev.4 [skip ci] * feat(ci): separate CI/CD pipelines for apps and Helm chart - Add paths-ignore to release.yml to exclude helm/ changes - Create helm-ci.yml for chart validation (lint + template) on PRs - Refactor helm-release.yml with independent semantic-release - Add .releaserc-helm.yaml for chart-specific versioning (helm-* tags) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(release): 1.1.0-dev.5 [skip ci] * fix(ci): trigger release only on apps changes Change from paths-ignore to paths for explicit control: - apps/** (backend + frontend code) - package.json, package-lock.json - .releaserc.yaml 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ci): use helm/vX.X.X tags without GitHub releases - Change tag format from helm-X.X.X to helm/vX.X.X - Remove @semantic-release/github plugin (tags only, no releases) - Update workflow summaries to show new tag format 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ci): use config swap instead of extends for helm release The extends option tries to npm install the file path. Instead, temporarily swap .releaserc.yaml with helm config. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(helm): release 1.0.0-dev.1 [skip ci] * fix(valkey): update existingSecretKey to existingSecretPasswordKey in values.yaml and helpers.tpl * chore(helm): release 1.0.0-dev.2 [skip ci] * fix(ci): remove 'v' prefix from helm tags Tags will now be helm/X.X.X instead of helm/vX.X.X 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Clément VALENTIN <clement.valentin@blacktiger.tech> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
1 parent c91e383 commit 92119f4

Some content is hidden

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

66 files changed

+1077
-450
lines changed

.claude/rules/encryption.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ MyElectricalData implémente un système de chiffrement **GDPR-compliant** pour
2828
│ │ │
2929
│ ▼ │
3030
│ ┌─────────────────────────────────────┐ │
31-
│ │ Redis (données chiffrées) │ │
31+
│ │ Valkey (données chiffrées) │ │
3232
│ │ │ │
3333
│ │ consumption:daily:{pdl}:{date} │ │
3434
│ │ production:daily:{pdl}:{date} │ │
@@ -115,7 +115,7 @@ async def set(
115115
encryption_key: str,
116116
ttl: int | None = None
117117
) -> bool:
118-
"""Store encrypted data in Redis"""
118+
"""Store encrypted data in Valkey"""
119119
try:
120120
# 1. Sérialise en JSON
121121
json_data = json.dumps(value)
@@ -124,7 +124,7 @@ async def set(
124124
cipher = self._get_cipher(encryption_key)
125125
encrypted_data = cipher.encrypt(json_data.encode())
126126

127-
# 3. Stocke dans Redis avec TTL
127+
# 3. Stocke dans Valkey avec TTL
128128
await self.redis.setex(
129129
key,
130130
ttl or self.default_ttl,
@@ -140,7 +140,7 @@ async def set(
140140

141141
```python
142142
async def get(self, key: str, encryption_key: str) -> Any | None:
143-
"""Retrieve and decrypt data from Redis"""
143+
"""Retrieve and decrypt data from Valkey"""
144144
try:
145145
# 1. Récupère les bytes chiffrés
146146
encrypted_data = await self.redis.get(key)
@@ -282,9 +282,9 @@ Le `client_secret` est stocké en clair dans la base de données car :
282282

283283
## Scénarios de sécurité
284284

285-
### Redis compromis
285+
### Valkey compromis
286286

287-
Si un attaquant accède à Redis :
287+
Si un attaquant accède à Valkey :
288288

289289
- ✅ Il ne voit que des bytes chiffrés
290290
- ✅ Sans le `client_secret`, déchiffrement impossible
@@ -295,7 +295,7 @@ Si un attaquant accède à Redis :
295295
Si un attaquant accède à PostgreSQL/SQLite :
296296

297297
- ⚠️ Il peut lire les `client_secret`
298-
- ⚠️ Il pourrait déchiffrer les caches Redis
298+
- ⚠️ Il pourrait déchiffrer les caches Valkey
299299
- 🔒 **Mitigation** : Chiffrer la base de données au niveau disque
300300

301301
### Rotation des clés
@@ -313,7 +313,7 @@ Actuellement, le `client_secret` ne change jamais après la création du compte.
313313
### Variables d'environnement
314314

315315
```bash
316-
# Redis connection
316+
# Valkey connection (protocole Redis compatible)
317317
REDIS_URL=redis://localhost:6379/0
318318

319319
# Cache TTL (default: 24 hours)
@@ -351,7 +351,7 @@ async def get(self, key: str, encryption_key: str) -> Any | None:
351351
| ------------------ | ------------------------------------------------- |
352352
| `get()` échoue | Retourne `None`, données récupérées depuis Enedis |
353353
| `set()` échoue | Retourne `False`, données non cachées |
354-
| Redis indisponible | Application continue, performances dégradées |
354+
| Valkey indisponible | Application continue, performances dégradées |
355355
| Clé invalide | Déchiffrement échoue silencieusement |
356356

357357
---

.claude/rules/enedis.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ Energie (Wh) = Puissance (W) / (60 / interval_minutes)
4343
| --------------------------------- | ------------------------------ |
4444
| `apps/api/src/adapters/enedis.py` | Wrapper API avec rate limiting |
4545
| `apps/api/src/routers/enedis.py` | Endpoints FastAPI |
46-
| `apps/api/src/services/cache.py` | Cache chiffre Redis |
46+
| `apps/api/src/services/cache.py` | Cache chiffre Valkey |

.env.local.example

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
# Copier ce fichier vers .env.local et ajuster selon votre environnement
33

44
# =============================================================================
5-
# Redis - Cache partagé entre les branches
5+
# Valkey - Cache partagé entre les branches (Redis-compatible)
66
# =============================================================================
7-
# Option 1: Redis local (Docker ou natif)
7+
# Option 1: Valkey local (Docker ou natif)
88
REDIS_URL=redis://localhost:6379/0
99

10-
# Option 2: Redis Docker sur le réseau host
10+
# Option 2: Valkey Docker sur le réseau host
1111
# REDIS_URL=redis://host.docker.internal:6379/0
1212

1313
# =============================================================================

.github/workflows/helm-ci.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Helm CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- develop
8+
- 'feature/**'
9+
paths:
10+
- 'helm/**'
11+
pull_request:
12+
paths:
13+
- 'helm/**'
14+
15+
concurrency:
16+
group: ${{ github.workflow }}-${{ github.ref }}
17+
cancel-in-progress: true
18+
19+
env:
20+
CHART_PATH: helm/myelectricaldata
21+
22+
jobs:
23+
validate:
24+
name: Validate Chart
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
30+
- name: Install Helm
31+
uses: azure/setup-helm@v4
32+
with:
33+
version: 'v3.14.0'
34+
35+
- name: Update dependencies
36+
run: helm dependency update ${{ env.CHART_PATH }}
37+
38+
- name: Lint chart
39+
run: helm lint ${{ env.CHART_PATH }}
40+
41+
- name: Template chart (default values)
42+
run: |
43+
helm template myelectricaldata ${{ env.CHART_PATH }} \
44+
--debug \
45+
> /dev/null
46+
echo "✅ Template with default values succeeded"
47+
48+
- name: Template chart (example values)
49+
if: hashFiles('helm/values-dev.yaml') != ''
50+
run: |
51+
helm template myelectricaldata ${{ env.CHART_PATH }} \
52+
-f helm/values-dev.yaml \
53+
--debug \
54+
> /dev/null
55+
echo "✅ Template with dev values succeeded"
56+
57+
- name: Validate Chart.yaml
58+
run: |
59+
# Check required fields
60+
if ! grep -q "^version:" ${{ env.CHART_PATH }}/Chart.yaml; then
61+
echo "❌ Missing version in Chart.yaml"
62+
exit 1
63+
fi
64+
if ! grep -q "^appVersion:" ${{ env.CHART_PATH }}/Chart.yaml; then
65+
echo "❌ Missing appVersion in Chart.yaml"
66+
exit 1
67+
fi
68+
echo "✅ Chart.yaml validation passed"
69+
70+
- name: Summary
71+
run: |
72+
VERSION=$(grep '^version:' ${{ env.CHART_PATH }}/Chart.yaml | awk '{print $2}')
73+
APP_VERSION=$(grep '^appVersion:' ${{ env.CHART_PATH }}/Chart.yaml | awk '{print $2}' | tr -d '"')
74+
75+
echo "## Helm Chart Validation ✅" >> $GITHUB_STEP_SUMMARY
76+
echo "" >> $GITHUB_STEP_SUMMARY
77+
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
78+
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
79+
echo "| Chart Version | \`$VERSION\` |" >> $GITHUB_STEP_SUMMARY
80+
echo "| App Version | \`$APP_VERSION\` |" >> $GITHUB_STEP_SUMMARY
81+
echo "" >> $GITHUB_STEP_SUMMARY
82+
echo "### Checks Passed" >> $GITHUB_STEP_SUMMARY
83+
echo "- ✅ Helm lint" >> $GITHUB_STEP_SUMMARY
84+
echo "- ✅ Helm template (default)" >> $GITHUB_STEP_SUMMARY
85+
echo "- ✅ Chart.yaml validation" >> $GITHUB_STEP_SUMMARY

.github/workflows/helm-release.yml

Lines changed: 131 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,136 @@ name: Release Helm Chart
22

33
on:
44
push:
5-
tags:
6-
- 'helm-v*' # Déclenché par les tags comme helm-v0.1.0
5+
branches:
6+
- main
7+
- develop
78
paths:
89
- 'helm/myelectricaldata/**'
9-
workflow_dispatch: # Permet le déclenchement manuel
10-
inputs:
11-
version:
12-
description: 'Version du chart (ex: 0.1.0)'
13-
required: false
14-
default: ''
15-
16-
# Annule les builds en cours sur la même branche
10+
workflow_dispatch:
11+
12+
# Prevent concurrent releases
1713
concurrency:
18-
group: ${{ github.workflow }}-${{ github.ref }}
19-
cancel-in-progress: true
14+
group: helm-release-${{ github.ref }}
15+
cancel-in-progress: false
2016

2117
env:
2218
REGISTRY: ghcr.io
2319
CHART_PATH: helm/myelectricaldata
2420

2521
jobs:
22+
# ===========================================
23+
# STEP 1: Validate Chart
24+
# ===========================================
25+
validate:
26+
name: Validate Chart
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
32+
- name: Install Helm
33+
uses: azure/setup-helm@v4
34+
with:
35+
version: 'v3.14.0'
36+
37+
- name: Update dependencies
38+
run: helm dependency update ${{ env.CHART_PATH }}
39+
40+
- name: Lint chart
41+
run: helm lint ${{ env.CHART_PATH }}
42+
43+
- name: Template chart
44+
run: helm template myelectricaldata ${{ env.CHART_PATH }} --debug > /dev/null
45+
46+
# ===========================================
47+
# STEP 2: Semantic Release for Helm Chart
48+
# ===========================================
2649
release:
50+
name: Semantic Release
51+
needs: validate
2752
runs-on: ubuntu-latest
2853
permissions:
29-
contents: read
54+
contents: write
55+
issues: write
56+
pull-requests: write
3057
packages: write
58+
outputs:
59+
new_release_published: ${{ steps.semantic.outputs.new_release_published }}
60+
new_release_version: ${{ steps.semantic.outputs.new_release_version }}
61+
steps:
62+
- name: Checkout
63+
uses: actions/checkout@v4
64+
with:
65+
fetch-depth: 0
66+
persist-credentials: false
67+
68+
- name: Setup Node.js
69+
uses: actions/setup-node@v4
70+
with:
71+
node-version: 20
72+
cache: 'npm'
73+
74+
- name: Use Helm release config
75+
run: |
76+
# Backup original releaserc if exists
77+
if [ -f .releaserc.yaml ]; then
78+
mv .releaserc.yaml .releaserc.yaml.bak
79+
fi
80+
# Use helm-specific config
81+
cp .releaserc-helm.yaml .releaserc.yaml
82+
83+
- name: Semantic Release
84+
id: semantic
85+
uses: cycjimmy/semantic-release-action@v4
86+
with:
87+
extra_plugins: |
88+
@semantic-release/changelog@6.0.3
89+
@semantic-release/git@10.0.1
90+
semantic-release-replace-plugin@1.2.7
91+
conventional-changelog-conventionalcommits@8.0.0
92+
env:
93+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
94+
95+
- name: Restore original config
96+
if: always()
97+
run: |
98+
# Restore original releaserc
99+
if [ -f .releaserc.yaml.bak ]; then
100+
mv .releaserc.yaml.bak .releaserc.yaml
101+
else
102+
rm -f .releaserc.yaml
103+
fi
31104
105+
- name: Release info
106+
if: steps.semantic.outputs.new_release_published == 'true'
107+
run: |
108+
echo "## Helm Chart Release 🎉" >> $GITHUB_STEP_SUMMARY
109+
echo "" >> $GITHUB_STEP_SUMMARY
110+
echo "**Version:** \`${{ steps.semantic.outputs.new_release_version }}\`" >> $GITHUB_STEP_SUMMARY
111+
echo "**Tag:** \`helm/${{ steps.semantic.outputs.new_release_version }}\`" >> $GITHUB_STEP_SUMMARY
112+
echo "**Branch:** \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
113+
114+
# ===========================================
115+
# STEP 3: Package and Push to GHCR
116+
# ===========================================
117+
publish:
118+
name: Publish to GHCR
119+
needs: release
120+
if: needs.release.outputs.new_release_published == 'true'
121+
runs-on: ubuntu-latest
122+
permissions:
123+
contents: read
124+
packages: write
32125
steps:
33-
- name: Checkout repository
126+
- name: Checkout
34127
uses: actions/checkout@v4
128+
with:
129+
ref: ${{ github.ref }}
130+
# Fetch latest to get the version bump commit
131+
fetch-depth: 1
132+
133+
- name: Pull latest changes
134+
run: git pull origin ${{ github.ref_name }}
35135

36136
- name: Set lowercase owner
37137
id: repo
@@ -47,34 +147,16 @@ jobs:
47147
run: |
48148
echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ${{ env.REGISTRY }} -u ${{ github.actor }} --password-stdin
49149
150+
- name: Update Helm dependencies
151+
run: helm dependency update ${{ env.CHART_PATH }}
152+
50153
- name: Get chart version
51154
id: chart_version
52155
run: |
53-
if [ -n "${{ github.event.inputs.version }}" ]; then
54-
VERSION="${{ github.event.inputs.version }}"
55-
elif [[ "${{ github.ref }}" == refs/tags/helm-v* ]]; then
56-
VERSION="${{ github.ref_name }}"
57-
VERSION="${VERSION#helm-v}"
58-
else
59-
VERSION=$(grep '^version:' ${{ env.CHART_PATH }}/Chart.yaml | awk '{print $2}')
60-
fi
156+
VERSION=$(grep '^version:' ${{ env.CHART_PATH }}/Chart.yaml | awk '{print $2}')
61157
echo "version=$VERSION" >> $GITHUB_OUTPUT
62158
echo "Chart version: $VERSION"
63159
64-
- name: Update chart version
65-
run: |
66-
sed -i "s/^version:.*/version: ${{ steps.chart_version.outputs.version }}/" ${{ env.CHART_PATH }}/Chart.yaml
67-
sed -i "s/^appVersion:.*/appVersion: \"${{ steps.chart_version.outputs.version }}\"/" ${{ env.CHART_PATH }}/Chart.yaml
68-
cat ${{ env.CHART_PATH }}/Chart.yaml
69-
70-
- name: Update Helm dependencies
71-
run: |
72-
helm dependency update ${{ env.CHART_PATH }}
73-
74-
- name: Lint Helm chart
75-
run: |
76-
helm lint ${{ env.CHART_PATH }}
77-
78160
- name: Package Helm chart
79161
run: |
80162
helm package ${{ env.CHART_PATH }} --destination ./packages
@@ -87,13 +169,23 @@ jobs:
87169
88170
- name: Summary
89171
run: |
90-
echo "## Helm Chart Published" >> $GITHUB_STEP_SUMMARY
172+
VERSION="${{ steps.chart_version.outputs.version }}"
173+
174+
if [[ "$VERSION" == *"-dev."* ]]; then
175+
RELEASE_TYPE="🧪 Development"
176+
else
177+
RELEASE_TYPE="🚀 Production"
178+
fi
179+
180+
echo "## Helm Chart Published 📦" >> $GITHUB_STEP_SUMMARY
91181
echo "" >> $GITHUB_STEP_SUMMARY
182+
echo "**Release Type:** $RELEASE_TYPE" >> $GITHUB_STEP_SUMMARY
92183
echo "**Chart:** myelectricaldata" >> $GITHUB_STEP_SUMMARY
93-
echo "**Version:** ${{ steps.chart_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
184+
echo "**Version:** \`$VERSION\`" >> $GITHUB_STEP_SUMMARY
185+
echo "**Tag:** \`helm/$VERSION\`" >> $GITHUB_STEP_SUMMARY
94186
echo "**Registry:** oci://${{ env.REGISTRY }}/${{ steps.repo.outputs.owner }}/charts" >> $GITHUB_STEP_SUMMARY
95187
echo "" >> $GITHUB_STEP_SUMMARY
96188
echo "### Installation" >> $GITHUB_STEP_SUMMARY
97189
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
98-
echo "helm install myelectricaldata oci://${{ env.REGISTRY }}/${{ steps.repo.outputs.owner }}/charts/myelectricaldata --version ${{ steps.chart_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
190+
echo "helm install myelectricaldata oci://${{ env.REGISTRY }}/${{ steps.repo.outputs.owner }}/charts/myelectricaldata --version $VERSION" >> $GITHUB_STEP_SUMMARY
99191
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)