Skip to content

Commit 12d2cac

Browse files
JeromeBuclaude
authored andcommitted
ci: add SILL deployment workflows and sync-upstream
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 961b4f2 commit 12d2cac

8 files changed

Lines changed: 390 additions & 170 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 67 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ jobs:
2121
curl -o iocs.csv https://raw.githubusercontent.com/DataDog/indicators-of-compromise/refs/heads/main/shai-hulud-2.0/consolidated_iocs.csv
2222
- name: Scan dependencies against IOCs
2323
run: node scripts/scan-dependencies.js
24-
2524
validations:
26-
runs-on: ubuntu-latest
2725
needs: security-scan
26+
runs-on: ubuntu-latest
2827
env:
2928
DATABASE_URL: postgresql://catalogi:pg_password@localhost:5432/db
3029
services:
@@ -91,169 +90,76 @@ jobs:
9190
runs-on: ubuntu-latest
9291
needs: [validations, e2e]
9392
outputs:
94-
from_version: ${{ steps.step1.outputs.from_version }}
95-
to_version: ${{ steps.step1.outputs.to_version }}
96-
is_upgraded_version: ${{ steps.step1.outputs.is_upgraded_version }}
93+
is_upgraded_in_preprod: ${{ steps.check_version.outputs.is_upgraded_in_preprod }}
94+
is_upgraded_version: ${{ steps.check_version.outputs.is_upgraded_version }}
95+
to_version: ${{ steps.check_version.outputs.to_version }}
96+
from_version: ${{ steps.check_version.outputs.from_version }}
9797
steps:
98-
- uses: garronej/ts-ci@v2.1.5
99-
id: step1
100-
with:
101-
action_name: is_package_json_version_upgraded
102-
- run: |
103-
echo "from_version=${{ steps.step1.outputs.from_version }}"
104-
echo "to_version=${{ steps.step1.outputs.to_version }}"
105-
echo "is_upgraded_version=${{ steps.step1.outputs.is_upgraded_version }}"
106-
107-
create_tag:
108-
name: Create version tag
109-
runs-on: ubuntu-latest
110-
needs:
111-
- check_if_version_upgraded
112-
if: needs.check_if_version_upgraded.outputs.is_upgraded_version == 'true'
113-
env:
114-
TO_VERSION: ${{ needs.check_if_version_upgraded.outputs.to_version }}
115-
steps:
116-
- name: Checkout repository
117-
uses: actions/checkout@v6
118-
- name: Create tag
119-
run: |
120-
git config --local user.email "actions@github.com"
121-
git config --local user.name "GitHub Actions"
122-
git tag -a v${{ env.TO_VERSION }} -m "Deployment tag for v${{ env.TO_VERSION }}"
123-
git push --tags
124-
125-
create_github_release:
126-
name: "Create release notes"
127-
runs-on: ubuntu-latest
128-
needs:
129-
- check_if_version_upgraded
130-
- create_tag
131-
if: |
132-
needs.check_if_version_upgraded.outputs.is_upgraded_version == 'true' && github.event_name == 'push'
133-
env:
134-
RELEASE_TAG: v${{ needs.check_if_version_upgraded.outputs.to_version }}
135-
steps:
136-
- name: Checkout repository
137-
uses: actions/checkout@v6
138-
- name: Install Helm
139-
uses: azure/setup-helm@v4
140-
- name: Build Helm chart dependencies
141-
run: |
142-
helm dependency build helm-charts/catalogi
143-
- name: Package Helm chart
144-
run: |
145-
helm package helm-charts/catalogi
146-
- name: "Generate release on github"
147-
uses: softprops/action-gh-release@v2
148-
with:
149-
name: Release ${{ env.RELEASE_TAG }}
150-
prerelease: false
151-
tag_name: ${{ env.RELEASE_TAG }}
152-
generate_release_notes: true
153-
files: catalogi-*.tgz
154-
token: ${{ secrets.GITHUB_TOKEN }}
155-
156-
publish_helm_index:
157-
name: Publish Helm chart index
158-
runs-on: ubuntu-latest
159-
permissions:
160-
contents: write
161-
needs:
162-
- check_if_version_upgraded
163-
- create_github_release
164-
if: needs.check_if_version_upgraded.outputs.is_upgraded_version == 'true'
165-
env:
166-
TO_VERSION: ${{ needs.check_if_version_upgraded.outputs.to_version }}
167-
steps:
168-
- name: Generate GitHub App token
169-
id: generate_token
170-
uses: tibdex/github-app-token@v2
171-
with:
172-
app_id: ${{ secrets.RELEASE_APP_ID }}
173-
private_key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
174-
175-
- name: Checkout repository
176-
uses: actions/checkout@v6
177-
with:
178-
token: ${{ steps.generate_token.outputs.token }}
179-
fetch-depth: 0
180-
181-
- name: Configure git
182-
run: |
183-
git config --local user.email "actions@github.com"
184-
git config --local user.name "GitHub Actions"
185-
186-
- name: Setup gh-pages branch
98+
- uses: actions/checkout@v6
99+
- name: Check version upgrade
100+
id: check_version
187101
run: |
188-
git fetch origin
189-
190-
if git ls-remote --heads origin gh-pages | grep gh-pages; then
191-
git checkout gh-pages
102+
# Get current version from package.json
103+
CURRENT_VERSION=$(jq -r '.version' package.json)
104+
echo "Version in package.json: $CURRENT_VERSION"
105+
106+
# Get deployed version from preprod API
107+
PRE_PROD_DEPLOYED_VERSION=$(curl -s "https://code.gouv.fr/sill-preprod/api/getApiVersion" | jq -r '.result.data.json')
108+
PROD_DEPLOYED_VERSION=$(curl -s "https://code.gouv.fr/sill/api/getApiVersion" | jq -r '.result.data.json')
109+
echo "Deployed version in preprod: $PRE_PROD_DEPLOYED_VERSION"
110+
echo "Deployed version in prod: $PROD_DEPLOYED_VERSION"
111+
112+
# Simple comparison: check if versions are different
113+
if [ "$CURRENT_VERSION" != "$PRE_PROD_DEPLOYED_VERSION" ]; then
114+
IS_UPGRADED_IN_PRE_PROD="true"
115+
IS_UPGRADED="true"
116+
echo "✅ Version different from preprod ($PRE_PROD_DEPLOYED_VERSION), should deploy: $CURRENT_VERSION"
117+
elif [ "$CURRENT_VERSION" != "$PROD_DEPLOYED_VERSION" ]; then
118+
IS_UPGRADED="true"
119+
echo "✅ Version different from prod ($PROD_DEPLOYED_VERSION), should deploy: $CURRENT_VERSION"
192120
else
193-
git checkout -b gh-pages
121+
IS_UPGRADED="false"
122+
echo "ℹ️ Version unchanged: $CURRENT_VERSION"
194123
fi
195-
196-
git reset --hard origin/main
197-
198-
- name: Install Helm
199-
uses: azure/setup-helm@v4
200-
201-
- name: Create charts directory
202-
run: mkdir -p docs/charts
203-
204-
- name: Download chart from release
205-
run: |
206-
gh release download v${TO_VERSION} --pattern "catalogi-*.tgz" --dir docs/charts/
207-
env:
208-
GH_TOKEN: ${{ github.token }}
209-
210-
- name: Generate Helm repository index with merge
211-
run: |
212-
helm repo index docs/charts/ --url https://github.com/codegouvfr/catalogi/releases/download/v${TO_VERSION}/ --merge docs/charts/index.yaml
213-
214-
- name: Commit and push to gh-pages
215-
run: |
216-
git add docs/charts/index.yaml
217-
git commit -m "chore: update Helm chart index for v${TO_VERSION}"
218-
git push origin gh-pages --force
219-
220-
docker:
221-
name: Build and push Docker images
222-
runs-on: ubuntu-latest
124+
125+
echo "Is version upgraded: $IS_UPGRADED"
126+
127+
# Set outputs
128+
echo "is_upgraded_version=$IS_UPGRADED" >> $GITHUB_OUTPUT
129+
echo "is_upgraded_in_preprod=$IS_UPGRADED_IN_PRE_PROD" >> $GITHUB_OUTPUT
130+
echo "to_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
131+
echo "from_version=$PRE_PROD_DEPLOYED_VERSION" >> $GITHUB_OUTPUT
132+
133+
trigger_pre_production_deploy:
223134
needs:
224135
- check_if_version_upgraded
225-
if: needs.check_if_version_upgraded.outputs.is_upgraded_version == 'true'
226-
steps:
227-
- uses: actions/checkout@v6
228-
- uses: docker/setup-qemu-action@v3
229-
- uses: docker/setup-buildx-action@v3
230-
- uses: docker/login-action@v3
231-
with:
232-
username: ${{ secrets.DOCKERHUB_USERNAME }}
233-
password: ${{ secrets.DOCKERHUB_TOKEN }}
234-
- name: Computing Docker image tags
235-
id: step1
236-
env:
237-
TO_VERSION: ${{ needs.check_if_version_upgraded.outputs.to_version }}
238-
run: |
239-
OUT_API=$GITHUB_REPOSITORY-api:$TO_VERSION,$GITHUB_REPOSITORY-api:latest
240-
OUT_API=$(echo "$OUT_API" | awk '{print tolower($0)}')
241-
echo ::set-output name=docker_api_tags::$OUT_API
242-
243-
OUT_WEB=$GITHUB_REPOSITORY-web:$TO_VERSION,$GITHUB_REPOSITORY-web:latest
244-
OUT_WEB=$(echo "$OUT_WEB" | awk '{print tolower($0)}')
245-
echo ::set-output name=docker_web_tags::$OUT_WEB
246-
247-
- uses: docker/build-push-action@v5
248-
with:
249-
push: true
250-
context: .
251-
file: ./Dockerfile.api
252-
tags: ${{ steps.step1.outputs.docker_api_tags }}
253-
- uses: docker/build-push-action@v5
254-
with:
255-
push: true
256-
context: .
257-
file: ./Dockerfile.web
258-
tags: ${{ steps.step1.outputs.docker_web_tags }}
136+
if: needs.check_if_version_upgraded.outputs.is_upgraded_in_preprod == 'true'
137+
uses: ./.github/workflows/trigger-deploy.yaml
138+
with:
139+
server_host: code.gouv.fr
140+
server_user: web
141+
deploy_script_path: ./update-sill-preprod.sh
142+
server_ssh_key_path: ~/.ssh/sill-data
143+
environment_name: pre-production
144+
version: v${{ needs.check_if_version_upgraded.outputs.to_version }}
145+
secrets:
146+
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
147+
148+
149+
trigger_production_deploy:
150+
needs:
151+
- trigger_pre_production_deploy
152+
- check_if_version_upgraded
153+
if: needs.check_if_version_upgraded.outputs.is_upgraded_version == 'true' && (needs.trigger_pre_production_deploy.result == 'success' || needs.trigger_pre_production_deploy.result == 'skipped')
154+
uses: ./.github/workflows/trigger-deploy.yaml
155+
with:
156+
server_host: code.gouv.fr
157+
server_user: web
158+
deploy_script_path: ./update-sill-docker-compose.sh
159+
server_ssh_key_path: ~/.ssh/sill-data
160+
environment_name: production
161+
version: v${{ needs.check_if_version_upgraded.outputs.to_version }}
162+
github_environment: production
163+
secrets:
164+
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
259165

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Sync upstream
2+
3+
on:
4+
schedule:
5+
- cron: '0 7 * * *' # every day at 7 AM UTC
6+
workflow_dispatch:
7+
8+
jobs:
9+
sync:
10+
name: Sync repository with upstream repository
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout fork
14+
uses: actions/checkout@v4
15+
with:
16+
token: ${{ secrets.PAT_FOR_UPSTREAM_SYNC }}
17+
fetch-depth: 0
18+
19+
- name: Configure Git
20+
run: |
21+
git config user.name "github-actions[bot]"
22+
git config user.email "github-actions[bot]@users.noreply.github.com"
23+
24+
- name: Add upstream remote
25+
run: |
26+
git remote add upstream https://github.com/codegouvfr/catalogi.git
27+
git fetch upstream
28+
29+
- name: Sync with upstream/main
30+
run: |
31+
git checkout main
32+
git rebase upstream/main
33+
34+
- name: Push to origin
35+
run: git push origin main --force-with-lease --no-verify
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Deploy to Server
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
server_host:
7+
description: 'Server hostname or IP address'
8+
required: true
9+
type: string
10+
server_user:
11+
description: 'SSH user'
12+
required: true
13+
type: string
14+
deploy_script_path:
15+
description: 'Deployment script path on remote server (e.g., ./update-sill-preprod.sh)'
16+
required: true
17+
type: string
18+
server_ssh_key_path:
19+
description: 'Path to SSH key on remote server for GitHub access (e.g., ~/.ssh/sill-data)'
20+
required: false
21+
type: string
22+
default: '~/.ssh/sill-data'
23+
environment_name:
24+
description: 'Environment name for display purposes'
25+
required: true
26+
type: string
27+
version:
28+
description: 'Version to deploy (with v prefix)'
29+
required: true
30+
type: string
31+
github_environment:
32+
description: 'GitHub environment for approvals (optional)'
33+
required: false
34+
type: string
35+
secrets:
36+
SSH_PRIVATE_KEY:
37+
required: true
38+
39+
jobs:
40+
deploy:
41+
name: "Deploy to ${{ inputs.environment_name }}"
42+
runs-on: ubuntu-latest
43+
environment: ${{ inputs.github_environment }}
44+
concurrency:
45+
group: deploy-to-${{ inputs.environment_name }}
46+
cancel-in-progress: true
47+
steps:
48+
- run: echo "${{ inputs.version }} - Triggering ${{ inputs.environment_name }} deploy"
49+
- name: Set up SSH, trigger deployment script
50+
timeout-minutes: 10
51+
run: |
52+
set -e
53+
set -o pipefail
54+
mkdir -p ~/.ssh
55+
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
56+
chmod 600 ~/.ssh/id_ed25519
57+
ssh-keyscan ${{ inputs.server_host }} >> ~/.ssh/known_hosts
58+
59+
echo "Connecting to ${{ inputs.server_host }} and running deployment script..."
60+
ssh ${{ inputs.server_user }}@${{ inputs.server_host }} "bash -c 'set -e && eval \"\$(ssh-agent -s)\" && ssh-add ${{ inputs.server_ssh_key_path }} && ${{ inputs.deploy_script_path }} ${{ inputs.version }}'" 2>&1 | tee deploy.log
61+
62+
echo "✅ ${{ inputs.environment_name }} deployment completed successfully"
63+
env:
64+
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}

README.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Documentation is available [here](https://codegouvfr.github.io/catalogi/)
1919

2020
## Code organization
2121

22-
This monorepo is made of several directories:
22+
Mais quels logiciels libres utiliser et pourquoi ? Quand plusieurs logiciels libres remplissent la même fonction, lequel privilégier ? Quelle version minimale est acceptable ?
2323

2424
- api: Application API (also includes jobs, that can be run periodically)
2525
- web: Web frontend
@@ -28,18 +28,14 @@ This monorepo is made of several directories:
2828

2929
## Governance and contributions
3030

31-
[![img](https://img.shields.io/badge/code.gouv.fr-contributif-blue.svg)](https://code.gouv.fr/documentation/#quels-degres-douverture-pour-les-codes-sources)
31+
# Historique
3232

33-
See [GOVERNANCE](GOVERNANCE.md) and [CONTRIBUTING](CONTRIBUTING.md).
34-
35-
## Discuss with us
36-
37-
You are welcome to join the [Catalogi Matrix channel](https://matrix.to/#/#catalogi:matrix.org).
33+
Le SILL était à l'origine une liste sous format PDF qui était mise à jour tous les ans par les groupes MIM (Mutualisation InterMinistérielle).
3834

3935
## License
4036

41-
2021-2025 Direction interministérielle du numérique, mission logiciels libres.
37+
Cette liste servaient aux DSI des ministères à faire les mises à jour nécessaires et à découvrir des logiciels libres utilisés par d'autres ministères.
4238

43-
The code in this repository is published under [licence MIT](LICENSES/MIT.txt).
39+
En 2019, le SILL a été publié sous forme d'une application web à l'adresse https://sill.etalab.gouv.fr, qui redirigeait vers https://sill.code.gouv.fr depuis février 2023 jusqu'à présent, et désormais sur https://code.gouv.fr/sill. La page de visualisation était générée à partir de fichiers `csv` maintenus manuellement sur un dépôt public.
4440

4541
The documentation is published under [licence Ouverte 2.0](LICENSES/Etalab-2.0.md) and [CC-BY-4.0](LICENSES/CC-BY-4.0.txt).

0 commit comments

Comments
 (0)