Skip to content

Commit

Permalink
Mise à jour Elixir 1.15 -> 1.16 et Erlang 24 -> 25 (#3815)
Browse files Browse the repository at this point in the history
* Bump to Erlang 25 and Elixir 1.16

* Add a first version of upgrade documentation

* Bump also nodejs version

* Point to the right docker image

* improve readme

* remove compilation warnings

* remove warnings about match on 0.0

* Update credo

* Fix Dialyxir errors

* improve documentation

* Update to OTP 26 in .tool_versions

* Order of map operations changed in OTP26

* Temporary OTP26 dockerfile

* Revert "Update to OTP 26 in .tool_versions"

This reverts commit f583cd2.

* Revert "Order of map operations changed in OTP26"

This reverts commit b68c1c1.

* Revert "Temporary OTP26 dockerfile"

This reverts commit d771a9e.

* Update comment in credo config

Co-authored-by: Thibaut Barrère <[email protected]>

* Improve badges code in organizations

* Revert credo config

* Bump OS to latest

Ref: https://github.com/etalab/transport-ops/releases/tag/elixir-1.16.2-erlang-25.3.2.10-ubuntu-focal-20240216-transport-tools-1.0.7

---------

Co-authored-by: Thibaut Barrère <[email protected]>
  • Loading branch information
vdegove and thbar authored Apr 8, 2024
1 parent 835e198 commit 69f45d1
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ default_docker: &default_docker
defaults: &defaults
parameters:
base_image:
default: ghcr.io/etalab/transport-ops:elixir-1.15.5-erlang-24.3.4.13-ubuntu-focal-20230126-transport-tools-1.0.7
default: ghcr.io/etalab/transport-ops:elixir-1.16.2-erlang-25.3.2.10-ubuntu-focal-20240216-transport-tools-1.0.7
type: string
# useful to invalidate the build cache manually by bumping the version
build_cache_key:
Expand Down
10 changes: 7 additions & 3 deletions .tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@
# provides an easy way to ensure local development and test will rely on roughly
# the same versions as in production, if one uses the "asdf" version manager.

# Update ASDF and plugins: asdf update && asdf plugin update --all

# See:
# - https://hexdocs.pm/elixir/compatibility-and-deprecations.html
# - https://github.com/elixir-lang/elixir/releases
# - `asdf list all elixir`
elixir 1.15.5-otp-24
elixir 1.16.2-otp-25

# See:
# - https://github.com/erlang/otp/releases
# - Blog, e.g. https://www.erlang.org/blog/my-otp-25-highlights/
# - https://github.com/erlang/otp/blob/master/otp_versions.table
# - `asdf list all erlang`
erlang 24.3.4.13
erlang 25.3.2.10

nodejs 18.17.1
# Take an LTS version on https://nodejs.org/
nodejs 20.11.1
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/etalab/transport-ops:elixir-1.15.5-erlang-24.3.4.13-ubuntu-focal-20230126-transport-tools-1.0.7
FROM ghcr.io/etalab/transport-ops:elixir-1.16.2-erlang-25.3.2.10-ubuntu-focal-20240216-transport-tools-1.0.7

RUN mkdir phoenixapp
WORKDIR /phoenixapp
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/etalab/transport-ops:elixir-1.15.5-erlang-24.3.4.13-ubuntu-focal-20230126-transport-tools-1.0.7
FROM ghcr.io/etalab/transport-ops:elixir-1.16.2-erlang-25.3.2.10-ubuntu-focal-20240216-transport-tools-1.0.7

RUN apt-get install -y git inotify-tools postgresql-client>=11

Expand Down
2 changes: 1 addition & 1 deletion apps/shared/lib/hasher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ defmodule Hasher do

def get_file_hash(file_path) do
file_path
|> File.stream!([], 2048)
|> File.stream!(2048)
|> compute_checksum(:sha256)
end

Expand Down
3 changes: 1 addition & 2 deletions apps/transport/lib/db/contact.ex
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ defmodule DB.Contact do

def organization_name(orgs) do
certified_orgs =
orgs
|> Enum.filter(fn %DB.Organization{badges: badges} -> Enum.any?(badges, &match?(&1, %{"kind" => "certified"})) end)
Enum.filter(orgs, fn %DB.Organization{badges: badges} -> %{"kind" => "certified"} in badges end)

case certified_orgs do
[] -> orgs |> List.first() |> Map.fetch!(:name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ defmodule TransportWeb.Backoffice.PageView do
def unaccent(nil), do: ""

def unaccent(value) when is_binary(value) do
~R<\p{Mn}>u
~r/\p{Mn}/u
|> Regex.replace(value |> :unicode.characters_to_nfd_binary(), "")
|> :unicode.characters_to_nfc_binary()
end
Expand Down
22 changes: 12 additions & 10 deletions apps/transport/test/transport/jobs/dataset_quality_score_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do

assert %{
format: "GTFS",
freshness: 0.0,
freshness: +0.0,
raw_measure: %{end_date: _, start_date: _},
resource_id: _
} = resource_freshness(resource)
Expand Down Expand Up @@ -127,7 +127,7 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do
metadata: %{"feed_timestamp_delay" => 1000}
)

assert %{format: "gbfs", freshness: 0.0, raw_measure: 1000, resource_id: _} = resource_freshness(resource)
assert %{format: "gbfs", freshness: +0.0, raw_measure: 1000, resource_id: _} = resource_freshness(resource)
end

test "GBFS resource without metadata for today" do
Expand Down Expand Up @@ -178,7 +178,7 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do
insert(:resource_unavailability, start: hours_ago(2), resource: resource)

assert %{
availability: 0.0,
availability: +0.0,
raw_measure: (22 / 24 * 100) |> Float.floor(1),
resource_id: resource.id
} == resource_availability(resource)
Expand Down Expand Up @@ -240,7 +240,7 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do
details: %{
resources: [
%{availability: 1.0, raw_measure: nil, resource_id: r1.id},
%{availability: 0.0, raw_measure: 0, resource_id: r2.id}
%{availability: +0.0, raw_measure: 0, resource_id: r2.id}
]
},
score: 0.5
Expand Down Expand Up @@ -269,7 +269,7 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do

assert [] == dataset |> DB.Repo.preload(:resources) |> Map.fetch!(:resources)

assert %{score: 0.0, details: %{resources: []}} == current_dataset_availability(dataset.id)
assert %{score: +0.0, details: %{resources: []}} == current_dataset_availability(dataset.id)
end
end

Expand Down Expand Up @@ -298,7 +298,7 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do
},
%{
format: "gtfs-rt",
freshness: 0.0,
freshness: +0.0,
raw_measure: 1000,
resource_id: ^resource_id_2
}
Expand All @@ -319,12 +319,12 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do

# average freshness for only 1 resource with freshness information available
assert %{
score: 0.0,
score: +0.0,
details: %{
resources: [
%{
format: "GTFS",
freshness: 0.0,
freshness: +0.0,
raw_measure: %{end_date: _, start_date: _},
resource_id: ^resource_id
},
Expand Down Expand Up @@ -369,7 +369,9 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do
assert %{
score: 0,
details: %{
resources: [%{compliance: 0.0, raw_measure: %{"has_errors" => true}, resource_id: geojson_resource.id}]
resources: [
%{compliance: +0.0, raw_measure: %{"has_errors" => true}, resource_id: geojson_resource.id}
]
}
} == current_dataset_compliance(dataset.id)
end
Expand All @@ -395,7 +397,7 @@ defmodule Transport.Test.Transport.Jobs.DatasetQualityScoreTest do
score: 0.5,
details: %{
resources: [
%{compliance: 0.0, raw_measure: %{"max_error" => "Error"}, resource_id: gtfs_1.id},
%{compliance: +0.0, raw_measure: %{"max_error" => "Error"}, resource_id: gtfs_1.id},
%{compliance: 1.0, raw_measure: %{"max_error" => "Warning"}, resource_id: gtfs_2.id}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ defmodule Transport.Jobs.LowEmissionZonesToGeoDataTest do
coordinates: [
[[{102.0, 2.0}, {103.0, 2.0}, {103.0, 3.0}, {102.0, 3.0}, {102.0, 2.0}]],
[
[{100.0, 0.0}, {101.0, 0.0}, {101.0, 1.0}, {100.0, 1.0}, {100.0, 0.0}],
[{100.0, +0.0}, {101.0, +0.0}, {101.0, 1.0}, {100.0, 1.0}, {100.0, +0.0}],
[{100.2, 0.2}, {100.2, 0.8}, {100.8, 0.8}, {100.8, 0.2}, {100.2, 0.2}]
]
],
Expand Down
27 changes: 27 additions & 0 deletions docs/upgrade_versions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Gestion des versions et des images Docker

Le setup standard de développement s’appuie sur ASDF pour la gestion des versions. Cependant, la CI/CD (CircleCI) et la production s’appuient sur Docker.

Une première image Docker est mise à disposition par le dépôt tranport-ops : elle récupère une image Docker standard sur le hub Docker avec déjà la bonne version de Elixir et Erlang, rajoute Node et les outils annexes (transport-tools), et est publiée sur le dépôt d’images Docker de Github.

L’application transport-site récupère l’image Docker de transport-ops, et y rajoute uniquement son propre code, le compile, lance le serveur, les migrations, et expose le serveur à l’extérieur.

CircleCI pour les tests va donc faire ces étapes là de compilation du code Elixir, mais sans devoir reconstruire toute l’image (puisque s’appuyant sur l’image de transport-ops). Quand on pousse sur les serveurs de CleverCloud, un premier serveur va créer l’image Docker finale (mêmes étapes que sur CircleCI, donc un temps de compilation existe) puis déployer l’image résultante sur un autre serveur. Potentiellement, on pourrait réduire à l’avenir le temps de déploiement en fournissant directement l’image Docker avec l’application précompilée, et que la même image serve pour les tests et pour la production.

## Processus de mise à jour

Les versions de ASDF et de Docker doivent être mises à jour dans la même branche de transport-site (sinon des tests ratent). Il faut donc en préalable du merge de la branche qu’une image Docker avec les bonnes versions de Elixir, Erlang/OTP et Node et les outils transport existe, donc qu’une branche correspondante sur transport-ops ait été mergée et un package crée.

Dans les grandes lignes : on teste d’abord avec ASDF que tout va bien, puis on fait le nécessaire sur le repo transport-ops pour créer un package, et on finalise la branche sur transport-site avec la référence de l’image.

1. Créer une branche
2. Mettre à jour `.tool_versions`. Le fichier contient un peu de documentation sur les commandes ASDF, et où trouver les versions disponibles, la compatibilité Elixir/Erlang et les notes de versions.
3. Vérifier que :
1. Ça compile
2. Les tests passent (il y aura forcément une erreur liée à la différence de version avec Docker)
3. Credo et Dialyxir n’aient pas de warning.
4. Noter tous les warnings, qui serviront soit dans une issue pour un traitement postérieur, soit seront mis dans la pull request. Exemple : https://github.com/etalab/transport-site/issues/3307
5. Créer un package Docker correspondant dans le dépôt https://github.com/etalab/transport-ops On peut pousser sur une branche pour faire tourner la CI Github Workflow, pas besoin d’avoir Docker en local. Lire le README de transport-ops pour le détail.
6. Modifier transport-site avec la bonne image Docker. Il n’est pas nécessaire de tester en local transport-site avec l’image Docker : les tests sufiront + prochainement. Il n’y a pas de grosse diff entre passage asdf et docker.
7. Créer une pull request en draft pour faire tourner Circle CI.
8. Tester le plus possible : en local et sur le serveur de staging (`git push origin ma_branche:prochainement`)

0 comments on commit 69f45d1

Please sign in to comment.