Maintainer guide¶
Maintainer-only runbook: releasing CodeCarbon, deploying the API and the dashboard, and operating the production database. Contributors want the contributing guide and the development guide instead.
Release process¶
- Merge all PRs.
- Open a terminal and make sure you are not in a venv with
deactivate. - Create a PR bumping the version with
uv run bumpver update --patch. For a release candidate, useuv run bumpver update --set-version 3.0.0_rc1. - Run
uv run python .github/pyproject_versions.py -cto check version consistancy. - No manual step is needed for the citation:
bumpveralso updates theversion:line inCITATION.cffand theversionfield in the README.md BibTeX entry.date-released:inCITATION.cffis not tracked bybumpverand needs a manual touch. - Update the dependencies with
uv sync --upgrade - Build the documentation with
uv run --only-group doc task docs. - Push the changes.
- Merge the PR.
- Wait for the Github Action
ReleaseDrafterto finish running on the merge commit. - Edit the Draft release on Github and give it a tag,
v1.0.0for the version 1.0.0. Github will automatically create a Git tag for it. Complete help here. - A Github Action Upload Python Package will be run automaticaly to upload the package.
Test the release¶
After the release on PyPi, please test it in a fresh environment:
cd /tmp
rm -rf cc_rel_test
python -m venv cc_rel_test
source cc_rel_test/bin/activate
pip install codecarbon
# Check you have the last version
codecarbon --version
codecarbon monitor --offline --country-iso-code FRA
# Stop it with Ctrl+C if it works
# Then clean up
rm -rf cc_rel_test
And check if the doc looks good on docs.codecarbon.io.
Test the build in Docker¶
If you want to check the build is working, you could run:
rm dist/*
uv build
docker run -it --rm -v $PWD:/data python:3.13 /bin/bash
pip install pytest pytest-mock requests-mock responses pandas
pip install --no-cache-dir /data/dist/codecarbon-*.whl -U --force-reinstall
cp /data/tests/test_package_integrity.py .
pytest test_package_integrity.py
Conda-forge packaging¶
CodeCarbon is distributed on conda-forge in addition to PyPI, so that conda users can install it with:
conda install -c conda-forge codecarbon
Nothing in this repository builds that package. Conda-forge builds every package from
a dedicated repository called a feedstock, ours being
conda-forge/codecarbon-feedstock.
The build instructions live there in recipe/meta.yaml, and the people allowed to
approve changes are listed at the bottom of that file under extra: recipe-maintainers.
How a release reaches conda-forge¶
- We publish to PyPI, as described in Release process.
- A few hours later
regro-cf-autotick-botnotices the new version, and opens a PR on the feedstock bumping the version and the sourcesha256. It also re-reads the dependencies from the published package and updates the recipe accordingly. - Conda-forge CI builds the package and runs the tests declared in the recipe, which
for us are
pip checkpluscodecarbon --help. conda-forge.ymlsetsbot: automerge: true, so the PR merges itself once CI is green and the package is uploaded to theconda-forgechannel.
A normal release therefore needs no action from us. pip check is the safety net:
if a dependency is missing or is named differently on conda-forge, CI fails, the PR
stays open, and a maintainer has to step in.
Updating the recipe by hand¶
Needed when the bot PR fails, or when the recipe has drifted from pyproject.toml
(a new dependency, a dropped Python version, a renamed entry point).
Two conda-forge rules make this different from a normal PR:
- Always work from a personal fork. Conda-forge refuses PRs opened from a branch of
the feedstock itself, and its bot cannot push to a fork owned by an organisation. Fork
to your own account, not to
mlco2. - Never edit the generated files by hand.
README.md,.ci_support/, and the CI workflows are produced byconda-smithy. To refresh them, comment on the PR:
@conda-forge-admin, please rerender
The bot pushes the regenerated files to your branch. A feedstock that has not been rerendered for a long time will fail to build at all, because its pinned CI container eventually becomes too old for conda-forge tooling.
To update the recipe itself:
- Set
version, and take the matchingsha256from the sdist on PyPI. - Mirror the
dependenciesof ourpyproject.tomlintorequirements: run. Conda package names occasionally differ from PyPI ones, and environment markers such aspython_version >= "3.14"cannot be expressed in anoarch: pythonrecipe. - Do not hardcode a Python version: use
{{ python_min }}, which comes from conda-forge's global pinning. - The optional
carbonboardextra is shipped as a separatecodecarbon-vizmetapackage, so its dependencies must be updated there too.
Adding someone to extra: recipe-maintainers requires that person to comment on the PR
to confirm.
Restore database from a production Backup¶
docker cp postgresql_*.dump postgres_codecarbon:/tmp
docker exec -it postgres_codecarbon bash
export BACKUP_USER=upwnpbdktjvnoks0foxq
export BACKUP_DB=bnrwiktgr4hzukt1xseg
psql -U $POSTGRES_USER -d $POSTGRES_DB -c "CREATE USER $BACKUP_USER WITH PASSWORD '$POSTGRES_PASSWORD';"
psql -U $POSTGRES_USER -d $POSTGRES_DB -c "ALTER USER $BACKUP_USER CREATEDB;"
createdb -U $BACKUP_USER $BACKUP_DB
psql -U $BACKUP_USER -d $POSTGRES_DB -c "CREATE DATABASE $BACKUP_DB;"
pg_restore -d $BACKUP_DB -U $BACKUP_USER --jobs=8 --clean --create /tmp/postgresql_*.dump
psql -U $BACKUP_USER -d $BACKUP_DB -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO \"$POSTGRES_USER\";"
psql -U $POSTGRES_USER -d $BACKUP_DB -c "ALTER DATABASE $POSTGRES_DB RENAME TO \"$POSTGRES_DB-backup\";"
psql -U $BACKUP_USER -d $POSTGRES_DB-backup -c "ALTER DATABASE $BACKUP_DB RENAME TO $POSTGRES_DB;"
Clean the database¶
To remove orphans (elements without run) from the database, run:
CALL public.spcc_purgeduplicatedata();
Deployment¶
API¶
The API is available to everyone from https://api.codecarbon.io, but if you want to deploy it for yourself, here are the instructions.
To deploy the API we use Clever Cloud, an IT Automation platform. They manage all the hard ops work while we focus on the Code Carbon value.
Here is the Clever Cloud configuration if you want to reproduce it:
APP_FOLDER="carbonserver"
CC_PIP_REQUIREMENTS_FILE="requirements.txt"
CC_POST_BUILD_HOOK="cd $APP_HOME/carbonserver && python3 -m alembic -c carbonserver/database/alembic.ini upgrade head"
CC_PYTHON_BACKEND="uvicorn"
CC_PYTHON_MODULE="main:app"
CC_PYTHON_VERSION="3.13"
DATABASE_URL="postgresql://secret_do_not_publish_this"
PORT="8080"
The CC_ prefix is Clever Cloud's, not CodeCarbon's.
To deploy,
git remote add deploy git+ssh://git@push-n2-par-clevercloud-customers.services.clever-cloud.com/app_<secret_do_not_share>.git
git push deploy master:master
See the doc for more informations.
Please note that Clever Cloud host Code Carbon for free because they like our project.
Dashboard¶
Same as for the API, for example to deploy the branch fix-unit to CleverCloud:
git push clever-dashboard fix-unit:master
Config on CleverCloud:
APP_FOLDER="dashboard"
CC_PIP_REQUIREMENTS_FILE="requirements-dashboard.txt"
CC_PYTHON_MODULE="carbon_board_API:server"
CC_PYTHON_VERSION="3.13"
CODECARBON_API_URL="https://api.codecarbon.io"
PORT="8000"
Webapp¶
The React webapp is deployed by .github/workflows/deploy.yml, as a Node.js
application built from the webapp/ folder with pnpm. The pnpm version comes
from the packageManager field of webapp/package.json.
Config on CleverCloud:
APP_FOLDER="webapp"
CC_NODE_VERSION="24"
CC_NODE_BUILD_TOOL="pnpm"
CC_BUILD_COMMAND="corepack pnpm install --frozen-lockfile && corepack pnpm run build"