1
0
Fork 0
mirror of https://github.com/YunoHost/apps.git synced 2024-09-03 20:06:07 +02:00

Merge pull request #1612 from YunoHost/toml-all-the-things

TOML all the things ?
This commit is contained in:
Alexandre Aubin 2023-01-20 17:34:59 +01:00 committed by GitHub
commit 0b67b0711c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 4398 additions and 5740 deletions

View file

@ -1,4 +1,4 @@
name: JSON validation
name: Catalog consistency checks
on: pull_request
@ -9,25 +9,16 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Check JSON validity for apps.json
- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install toml python lib
run: |
cat apps.json | jq >/dev/null
- name: Check all working apps have consistent app id / app url
pip3 install toml
- name: Check TOML validity for apps.toml
run: |
FAULTY_APPS="false";
for LINE in $(cat apps.json | jq -r 'to_entries[] | select ( .value.state=="working" ) | "\(.key)|\(.value.url)"')
do
APP=$(echo $LINE | awk -F'|' '{print $1}')
URL_END=$(echo $LINE | awk -F'/' '{print $NF}')
[ "$APP" == "$(echo $APP | tr [A-Z] [a-z])" ] || { FAULTY_APPS="true"; echo "$APP : app id should be lowercase" >&2; }
[ "$URL_END" == "${APP}_ynh" ] || { FAULTY_APPS="true"; echo "$APP : the url should end with ${APP}_ynh" >&2; }
done
[ $FAULTY_APPS = "false" ]
- name: Check all working apps have a category
python3 -c "import toml; toml.load(open('apps.toml'))"
- name: Check all working apps have consistent app id / app url and categories
run: |
APPS_WITH_NO_CATEGORY=$(jq -e -r '.[] | select ( .state=="working" ) | select ( has("category") | not )' apps.json || true)
[ "$APPS_WITH_NO_CATEGORY" == "" ] || { echo "Some working apps are missing a category: $APPS_WITH_NO_CATEGORY" >&2; false; }
python3 tools/catalog_linter.py

2
.gitignore vendored
View file

@ -9,3 +9,5 @@ tools/bot-repo-cleanup/.github_token
tools/autopatches/login
tools/autopatches/token
.github_token

View file

@ -6,7 +6,7 @@ Here you will find the repositories and versions of every apps available in Yuno
It is browsable here: https://yunohost.org/apps
The main file of the catalog is [**apps.json**](./apps.json) which contains
The main file of the catalog is [**apps.toml**](./apps.toml) which contains
references to the corresponding Git repositories for each application, along
with a few metadata about them such as its category or maintenance state. This
file regularly read by `list_builder.py` which publish the results on
@ -30,28 +30,23 @@ https://app.yunohost.org/default/.
> with keeping your app working and up to date with packaging evolutions on the long run.
To add your application to the catalog:
* Fork this repository and edit the [apps.json](https://github.com/YunoHost/apps/tree/master/apps.json) file
* Fork this repository and edit the [apps.toml](https://github.com/YunoHost/apps/tree/master/apps.toml) file
* Add your app's ID and git information at the right alphabetical place
* Indicate the app's functioning state: `notworking`, `inprogress`, or `working`
* Indicate the app category, which you can pick from `categories.yml`
* Indicate any anti-feature that your app may be subject to, see `antifeatures.yml` (or remove the `antifeatures` key if there's none)
* Indicate the app category, which you can pick from `categories.toml`
* Indicate any anti-feature that your app may be subject to, see `antifeatures.toml` (or remove the `antifeatures` key if there's none)
* Indicate if your app can be thought of as an alternative to popular proprietary services (or remove the `potential_alternative_to` key if there's none)
* *Do not* add the `level` entry by yourself. Our automatic test suite ("the CI") will handle it.
* Create a [Pull Request](https://github.com/YunoHost/apps/pulls/)
App example addition:
```json
"your_app": {
"antifeatures": [
"deprecated-software"
],
"potential_alternative_to": [
"YouTube"
],
"category": "pick_the_appropriate_category",
"state": "working",
"url": "https://github.com/YunoHost-Apps/your_app_ynh"
}
```toml
[your_app]
antifeatures = [ "deprecated-software" ] # Remove if no relevant antifeature applies
potential_alternative_to = [ "YouTube" ] # Indicate if your app can be thought of as an alternative to popular proprietary services (or remove if none applies)
category = "foobar" # Replace with the appropriate category id found in categories.toml
state = "working"
url = "https://github.com/YunoHost-Apps/your_app_ynh"
```
> **Warning**
@ -69,6 +64,6 @@ App packagers should *not* manually set their apps' level. The levels of all the
### Apps flagged as not-maintained
Applications with no recent activity and no active sign from maintainer may be flagged in `apps.json` with the `package-not-maintained` antifeature tag to signify that the app is inactive and may slowly become outdated with respect to the upstream, or with respect to good packaging practices. It does **not** mean that the app is not working anymore.
Applications with no recent activity and no active sign from maintainer may be flagged in `apps.toml` with the `package-not-maintained` antifeature tag to signify that the app is inactive and may slowly become outdated with respect to the upstream, or with respect to good packaging practices. It does **not** mean that the app is not working anymore.
Feel free to contact the app group if you feel like taking over the maintenance of a currently unmaintained app!

90
antifeatures.toml Normal file
View file

@ -0,0 +1,90 @@
[tracking]
icon = "user-secret"
title.en = "Tracking"
title.fr = "Pistage"
description.en = "Tracks you and/or reports your activity to upstream maintainer or third parties, either without your permission or by default."
decription.fr = "Vous piste et/ou rapporte vos activités au mainteneur source ou à des tiers, sans votre permission ou par défaut."
[non-free-network]
icon = "sitemap"
title.en = "Non-free Network Services"
title.fr = "Services réseau non libres"
description.en = "Promotes or depends entirely on a non-free network service."
description.fr = "Promeut ou utilise des services réseau non libres."
[non-free-addons]
icon = "puzzle-piece"
title.en = "Non-free Addons"
title.fr = "Extensions non libres"
description.en = "Promotes other non-free applications or plugins."
description.fr = "Promeut d'autres applications ou plugins non libres."
[non-free-dependencies]
icon = "book"
title.en = "Non-free dependencies"
title.fr = "Dépendances non libres"
description.en = "Relies on software dependencies that are not free in order to run."
description.fr = "Dépend pour fonctionner de dépendances logicielles non libres."
[non-free-assets]
icon = "file-image-o"
title.en = "Non-free assets"
title.fr = "Ressources non libres"
description.en = "Contains and makes use of non-free assets. The most common case is apps using artwork - images, sounds, music, etc. - under a commercial license."
description.fr = "Contient ou utilise des médias non libres. Le cas le plus fréquent concerne des applications utilisant des œuvres (images, sons, musiques, etc.) sous une licence commerciale."
[bad-security-reputation]
icon = "bug"
title.en = "Bad security reputation"
title.fr = "Mauvaise réputation en matière de sécurité"
description.en = "Has a bad security reputation, such as deprecated addons."
description.fr = "A une mauvaise réputation en matière de sécurité, en utilisant des plugins dépréciés par exemple."
[deprecated-software]
icon = "trash-o"
title.en = "Upstream not maintained"
title.fr = "Application non maintenue"
description.en = "This software is not maintained anymore. Expect it to break down over time, be exposed to unfixed security breaches, etc."
description.fr = "Ce logiciel n'est plus maintenu. Attendez-vous à ce qu'il ne fonctionne plus avec le temps, et que l'on découvre des failles de sécurité qui ne seront pas corrigées, etc."
[package-not-maintained]
icon = "user-times"
title.en = "Package not maintained"
title.fr = "Paquet non maintenu"
description.en = "This YunoHost package is not maintained and needs adoption."
description.fr = "Ce package YunoHost n'est plus maintenu et doit être adopté."
[paid-content]
icon = "money"
title.en = "Paid content"
title.fr = "Contenu payant"
description.en = "Promotes or depends, entirely or partially, on a paid service."
description.fr = "Promeut ou dépend, entièrement ou partiellement, d'un service payant."
[arbitrary-limitations]
icon = "star-half-empty"
title.en = "Arbitrary limitations"
title.fr = "Limitations arbitraires"
description.en = "Features arbitrary limitations. Please refer to the README."
description.fr = "Contient des limitations arbitraires. Se référer au fichier README."
[replaced-by-another-app]
icon = "repeat"
title.en = "Replaced by another app"
title.fr = "Remplacé par une autre application"
description.en = "Was replaced by another app. Please refer to the README."
description.fr = "A été remplacé par une autre application. Se référer au fichier README."
[alpha-software]
icon = "flask"
title.en = "Alpha software"
title.fr = "Logiciel en version alpha"
description.en = "Early development stage. May contain changing or unstable features, bugs, and security vulnerability."
description.fr = "Le logiciel est au tout début de son développement. Il pourrait contenir des fonctionnalités changeantes ou instables, des bugs, et des failles de sécurité."
[not-totally-free]
icon = "lock"
title.en = "Not totally free upstream"
title.fr = "Application sous licence libre restreinte"
description.en = "The packaged app is under an overall free licence, but with clauses that restrict its use."
description.fr = "L'application packagée est sous une licence globalement libre, mais avec des clauses qui pourraient restreindre son utilisation."

View file

@ -1,116 +0,0 @@
- id: tracking
icon: user-secret
title:
en: "Tracking"
fr: "Pistage"
description:
en: "Tracks you and/or reports your activity to upstream maintainer or third parties, either without your permission or by default."
fr: "Vous piste et/ou rapporte vos activités au mainteneur source ou à des tiers, sans votre permission ou par défaut."
- id: non-free-network
icon: sitemap
title:
en: "Non-free Network Services"
fr : "Services réseau non libres"
description:
en: "Promotes or depends entirely on a non-free network service."
fr: "Promeut ou utilise des services réseau non libres."
- id: non-free-addons
icon: puzzle-piece
title:
en: "Non-free Addons"
fr: "Extensions non libres"
description:
en: "Promotes other non-free applications or plugins."
fr: "Promeut d'autres applications ou plugins non libres."
- id: non-free-dependencies
icon: book
title:
en: "Non-free dependencies"
fr: "Dépendances non libres"
description:
en: "Relies on software dependencies that are not free in order to run."
fr: "Dépend pour fonctionner de dépendances logicielles non libres."
- id: non-free-assets
icon: file-image-o
title:
en: "Non-free assets"
fr: "Ressources non libres"
description:
en: "Contains and makes use of non-free assets. The most common case is apps using artwork - images, sounds, music, etc. - under a commercial license."
fr: "Contient ou utilise des médias non libres. Le cas le plus fréquent concerne des applications utilisant des œuvres (images, sons, musiques, etc.) sous une licence commerciale."
- id: bad-security-reputation
icon: bug
title:
en: "Bad security reputation"
fr: "Mauvaise réputation en matière de sécurité"
description:
en: "Has a bad security reputation, such as deprecated addons."
fr: "A une mauvaise réputation en matière de sécurité, en utilisant des plugins dépréciés par exemple."
- id: deprecated-software
icon: trash-o
title:
en: "Upstream not maintained"
fr: "Application non maintenue"
description:
en: "This software is not maintained anymore. Expect it to break down over time, be exposed to unfixed security breaches, etc."
fr: "Ce logiciel n'est plus maintenu. Attendez-vous à ce qu'il ne fonctionne plus avec le temps, et que l'on découvre des failles de sécurité qui ne seront pas corrigées, etc."
- id: package-not-maintained
icon: user-times
title:
en: "Package not maintained"
fr: "Paquet non maintenu"
description:
en: "This YunoHost package is not maintained and needs adoption."
fr: "Ce package YunoHost n'est plus maintenu et doit être adopté."
- id: paid-content
icon: money
title:
en: "Paid content"
fr: "Contenu payant"
description:
en: "Promotes or depends, entirely or partially, on a paid service."
fr: "Promeut ou dépend, entièrement ou partiellement, d'un service payant."
- id: arbitrary-limitations
icon: star-half-empty
title:
en: "Arbitrary limitations"
fr: "Limitations arbitraires"
description:
en: "Features arbitrary limitations. Please refer to the README."
fr: "Contient des limitations arbitraires. Se référer au fichier README."
- id: replaced-by-another-app
icon: repeat
title:
en: "Replaced by another app"
fr: "Remplacé par une autre application"
description:
en: "Was replaced by another app. Please refer to the README."
fr: "A été remplacé par une autre application. Se référer au fichier README."
- id: alpha-software
icon: flask
title:
en: "Alpha software"
fr: "Logiciel en version alpha"
description:
en: "Early development stage. May contain changing or unstable features, bugs, and security vulnerability."
fr: "Le logiciel est au tout début de son développement. Il pourrait contenir des fonctionnalités changeantes ou instables, des bugs, et des failles de sécurité."
- id: not-totally-free
icon: lock
title:
en: "Not totally free upstream"
fr: "Application sous licence libre restreinte"
description:
en: "The packaged app is under an overall free licence, but with clauses that restrict its use."
fr: "L'application packagée est sous une licence globalement libre, mais avec des clauses qui pourraient restreindre son utilisation."

5254
apps.json

File diff suppressed because it is too large Load diff

3835
apps.toml Normal file

File diff suppressed because it is too large Load diff

298
categories.toml Normal file
View file

@ -0,0 +1,298 @@
[synchronization]
icon = "cloud"
title.en = "Synchronization"
title.es = "Sincronización"
title.fr = "Synchronisation"
description.en = "Files sync, contact, calendar, password managers..."
description.es = "Sincronización, contactos, calendario, gestor de contraseñas..."
description.fr = "Fichiers, contacts, calendrier, mots de passe..."
[synchronization.subtags.files]
title.en = "Files"
title.es = "Archivos"
title.fr = "Fichiers"
[synchronization.subtags.calendar]
title.en = "Calendar"
title.es = "Calendario"
title.fr = "Calendrier"
[synchronization.subtags.contacts]
title.en = "Contacts"
title.es = "Contactos"
title.fr = "Contacts"
[synchronization.subtags.password]
title.en = "Passwords"
title.es = "Contraseñas"
title.fr = "Mots de passe"
[publishing]
icon = "globe"
title.en = "Publishing"
title.es = "Publicaciones"
title.fr = "Publication"
description.en = "Websites, blog, wiki, CMS..."
description.es = "Paginas Web, blog, wiki, CMS..."
description.fr = "Site web, blog, wiki, CMS..."
[publishing.subtags.websites]
title.en = "Websites"
title.es = "Paginas web"
title.fr = "Sites web"
[publishing.subtags.blog]
title.en = "Blog"
title.es = "blog"
title.fr = "Blog"
[publishing.subtags.wiki]
title.en = "Wiki"
title.es = "Wiki"
title.fr = "Wiki"
[publishing.subtags.ecommerce]
title.en = "E-commerce"
title.es = "Comercio eletronico"
title.fr = "Vente en ligne"
[publishing.subtags.analytics]
title.en = "Analytics"
title.es = "Estadisticas"
title.fr = "Statistiques"
[communication]
icon = "comments-o"
title.en = "Communication"
title.es = "Comunicacion"
title.fr = "Communication"
description.en = "Chat, email, forum, meetings..."
description.es = "Chat, email, foro, reuniones en grupo..."
description.fr = "Chat, email, forum, meetings..."
[communication.subtags.chat]
title.en = "Instant messaging"
title.es = "Mensajeria Instantanea"
title.fr = "Messagerie instantannée"
[communication.subtags.forum]
title.en = "Forum"
title.es = "Foro"
title.fr = "Forum"
[communication.subtags.email]
title.en = "Email"
title.es = "Email"
title.fr = "Email"
[communication.subtags.meeting]
title.en = "Meetings"
title.es = "Reuniones"
title.fr = "Meetings"
[office]
icon = "file-text-o"
title.en = "Office"
title.es = "Ofimatica"
title.fr = "Bureautique"
description.en = "Collaborative text edition, spreadsheets..."
description.es = "Edición de texto colaborativo, hojas de cálculo..."
description.fr = "Édition de texte collaborative, tableurs..."
[office.subtags.text]
title.en = "Text"
title.es = "Texto"
title.fr = "Texte"
[office.subtags.speadsheet]
title.en = "Speadsheet"
title.es = "Hoja de cálculo"
title.fr = "Tableur"
[office.subtags.impress]
title.en = "Slide show"
title.es = "Diapositivas"
title.fr = "Diaporama"
[office.subtags.draw]
title.en = "Graphism"
title.es = "Graficos"
title.fr = "Graphisme"
[office.subtags.mindmap]
title.en = "Mindmap"
title.fr = "Cartes mentale"
[productivity_and_management]
icon = "area-chart"
title.en = "Productivity & management"
title.fr = "Productivité & gestion"
description.en = "Tasks, polls, accounting, ERP..."
description.fr = "Tâches, sondages, comptabilité, ERP..."
[productivity_and_management.subtags.task]
title.en = "Task"
title.fr = "Tâches"
[productivity_and_management.subtags.poll]
title.en = "Poll"
title.fr = "Sondage"
[productivity_and_management.subtags.accounting]
title.en = "Accounting"
title.fr = "Comptabilité"
[productivity_and_management.subtags.business_and_ngos]
title.en = "Business and NGOs"
title.fr = "Entreprises et associations"
[small_utilities]
icon = "umbrella"
title.en = "Small utilities"
title.fr = "Petits utilitaires"
description.en = "Pastebins, URL shortener, proxies..."
description.fr = "Pastebins, raccourcisseurs d'URL, proxys..."
[small_utilities.subtags.pastebin]
title.en = "Pastebin"
title.fr = "Pastebin"
[small_utilities.subtags.url_shortener]
title.en = "URL shortener"
title.fr = "Raccourcisseurs d'URL"
[small_utilities.subtags.proxy]
title.en = "Proxy"
title.fr = "Proxy (Intermédiaire)"
[reading]
icon = "newspaper-o"
title.en = "Reading"
title.fr = "Lecture"
description.en = "Newsfeed readers, books library..."
description.fr = "Fils d'actualité, livres..."
[reading.subtags.rssreader]
title.en = "RSS readers"
title.fr = "Lecteurs RSS"
[reading.subtags.books]
title.en = "Books"
title.fr = "Livres"
[multimedia]
icon = "music"
title.en = "Multimedia"
title.fr = "Multimédia"
description.en = "Music library, pictures gallery, P2P, TV shows..."
description.fr = "Bibliothèque de musique, d'images, P2P, séries..."
[multimedia.subtags.mediacenter]
title.en = "Media center"
title.fr = "Centre multimédia"
[multimedia.subtags.download]
title.en = "Download"
title.fr = "Téléchargement"
[multimedia.subtags.music]
title.en = "Music"
title.fr = "Musique"
[multimedia.subtags.pictures]
title.en = "Pictures"
title.fr = "Images"
[social_media]
icon = "users"
title.en = "Social media"
title.fr = "Médias sociaux"
description.en = "Microblogging, federated media"
description.fr = "Microblogging, médias fédérés"
[social_media.subtags.microblogging]
title.en = "Microblogging"
title.fr = "Microblogging"
[social_media.subtags.blogging]
title.en = "Blogging"
title.fr = "Blogging"
[social_media.subtags.events]
title.en = "Events"
title.fr = "Événements"
[social_media.subtags.videos]
title.en = "Videos"
title.fr = "Vidéos"
[social_media.subtags.pictures]
title.en = "Pictures"
title.fr = "Images"
[social_media.subtags.music]
title.en = "Music"
title.fr = "Musique"
[games]
icon = "gamepad"
title.en = "Games"
title.fr = "Jeux"
description.en = "Wanna have some fun? ;)"
description.fr = "Envie de s'amuser ? ;)"
[dev]
icon = "flask"
title.en = "Development"
title.fr = "Développement"
description.en = "Git forges, apps skeleton, CI, translation..."
description.fr = "Forges Git, squelette d'apps, CI, traduction..."
[dev.subtags.forge]
title.en = "Forge"
title.fr = "Forge"
[dev.subtags.skeleton]
title.en = "Skeleton"
title.fr = "Squelettes"
[dev.subtags.programming]
title.en = "Programming"
title.fr = "Programmation"
[system_tools]
icon = "wrench"
title.en = "System tools"
title.fr = "Outils système"
description.en = "Monitoring, backup, network, DB tools..."
description.fr = "Monitoring, sauvegardes, outils réseau, bases de données..."
[system_tools.subtags.backup]
title.en = "Backup"
title.fr = "Sauvegardes"
[system_tools.subtags.monitoring]
title.en = "Monitoring"
title.fr = "Monitoring"
[system_tools.subtags.network]
title.en = "Network"
title.fr = "Réseau"
[system_tools.subtags.db]
title.en = "Databases"
title.fr = "Bases de données"
[iot]
icon = "home"
title.en = "Internet of Things (IoT)"
title.fr = "Internet des objets (IoT)"
description.en = "Home automation, energy dashboard..."
description.fr = "Domotique, énergie..."
[wat]
icon = "tree"
title.en = "Wat"
title.fr = "Wat"
description.en = "Weird experimental or very-custom stuff"
description.fr = "Trucs expérimentaux et autres projets spécifiques"

View file

@ -1,324 +0,0 @@
- id: "synchronization"
icon: "cloud"
title:
en: "Synchronization"
es: "Sincronización"
fr: "Synchronisation"
description:
en: "Files sync, contact, calendar, password managers..."
es: "Sincronización, contactos, calendario, gestor de contraseñas..."
fr: "Fichiers, contacts, calendrier, mots de passe..."
subtags:
- id: files
title:
en: Files
es: Archivos
fr: Fichiers
- id: calendar
title:
en: Calendar
es: Calendario
fr: Calendrier
- id: contacts
title:
en: Contacts
es: Contactos
fr: Contacts
- id: password
title:
en: Passwords
es: Contraseñas
fr: Mots de passe
- id: "publishing"
icon: "globe"
title:
en: "Publishing"
es: "Publicaciones"
fr: "Publication"
description:
en: "Websites, blog, wiki, CMS..."
es: "Paginas Web, blog, wiki, CMS..."
fr: "Site web, blog, wiki, CMS..."
subtags:
- id: websites
title:
en: Websites
es: Paginas web
fr: Sites web
- id: blog
title:
en: Blog
es: blog
fr: Blog
- id: wiki
title:
en: Wiki
es: Wiki
fr: Wiki
- id: ecommerce
title:
en: E-commerce
es: Comercio eletronico
fr: Vente en ligne
- id: analytics
title:
en: Analytics
es: Estadisticas
fr: Statistiques
- id: "communication"
icon: "comments-o"
title:
en: "Communication"
es: "Comunicacion"
fr: "Communication"
description:
en: "Chat, email, forum, meetings..."
es: "Chat, email, foro, reuniones en grupo..."
fr: "Chat, email, forum, meetings..."
subtags:
- id: chat
title:
en: Instant messaging
es: Mensajeria Instantanea
fr: Messagerie instantannée
- id: forum
title:
en: Forum
es: Foro
fr: Forum
- id: email
title:
en: Email
es: Email
fr: Email
- id: meeting
title:
en: Meetings
es: Reuniones
fr: Meetings
- id: "office"
icon: "file-text-o"
title:
en: "Office"
es: "Ofimatica"
fr: "Bureautique"
description:
en: "Collaborative text edition, spreadsheets..."
es: "Edición de texto colaborativo, hojas de cálculo..."
fr: "Édition de texte collaborative, tableurs..."
subtags:
- id: text
title:
en: Text
es: Texto
fr: Texte
- id: spreadsheet
title:
en: Speadsheet
es: Hoja de cálculo
fr: Tableur
- id: impress
title:
en: Slide show
es: Diapositivas
fr: Diaporama
- id: draw
title:
en: Graphism
es: Graficos
fr: Graphisme
- id: mindmap
title:
en: Mindmap
fr: Cartes mentale
- id: "productivity_and_management"
icon: "area-chart"
title:
en: "Productivity & management"
fr: "Productivité & gestion"
description:
en: "Tasks, polls, accounting, ERP..."
fr: "Tâches, sondages, comptabilité, ERP..."
subtags:
- id: task
title:
en: Task
fr: Tâches
- id: poll
title:
en: Poll
fr: Sondage
- id: accounting
title:
en: Accounting
fr: Comptabilité
- id: business_and_ngos
title:
en: Business and NGOs
fr: Entreprises et associations
- id: "small_utilities"
icon: "umbrella"
title:
en: "Small utilities"
fr: "Petits utilitaires"
description:
en: "Pastebins, URL shortener, proxies..."
fr: "Pastebins, raccourcisseurs d'URL, proxys..."
subtags:
- id: pastebin
title:
en: Pastebin
fr: Pastebin
- id: url_shortener
title:
en: "URL shortener"
fr: "Raccourcisseurs d'URL"
- id: proxy
title:
en: "Proxy"
fr: "Proxy (Intermédiaire)"
- id: "reading"
icon: "newspaper-o"
title:
en: "Reading"
fr: "Lecture"
description:
en: "Newsfeed readers, books library..."
fr: "Fils d'actualité, livres..."
subtags:
- id: rssreader
title:
en: RSS readers
fr: Lecteurs RSS
- id: books
title:
en: Books
fr: Livres
- id: "multimedia"
icon: "music"
title:
en: "Multimedia"
fr: "Multimédia"
description:
en: "Music library, pictures gallery, P2P, TV shows..."
fr: "Bibliothèque de musique, d'images, P2P, séries..."
subtags:
- id: mediacenter
title:
en: Media center
fr: Centre multimédia
- id: download
title:
en: Download
fr: Téléchargement
- id: music
title:
en: Music
fr: Musique
- id: pictures
title:
en: Pictures
fr: Images
- id: "social_media"
icon: "users"
title:
en: "Social media"
fr: "Médias sociaux"
description:
en: "Microblogging, federated media"
fr: "Microblogging, médias fédérés"
subtags:
- id: microblogging
title:
en: Microblogging
fr: Microblogging
- id: blogging
title:
en: Blogging
fr: Blogging
- id: events
title:
en: Events
fr: Événements
- id: videos
title:
en: Videos
fr: Vidéos
- id: pictures
title:
en: Pictures
fr: Images
- id: music
title:
en: Music
fr: Musique
- id: "games"
icon: "gamepad"
title:
en: "Games"
fr: "Jeux"
description:
en: "Wanna have some fun? ;)"
fr: "Envie de s'amuser ? ;)"
- id: "dev"
icon: "flask"
title:
en: "Development"
fr: "Développement"
description:
en: "Git forges, apps skeleton, CI, translation..."
fr: "Forges Git, squelette d'apps, CI, traduction..."
subtags:
- id: forge
title:
en: Forge
fr: Forge
- id: skeleton
title:
en: Skeleton
fr: Squelettes
- id: programming
title:
en: Programming
fr: Programmation
- id: "system_tools"
icon: "wrench"
title:
en: "System tools"
fr: "Outils système"
description:
en: "Monitoring, backup, network, DB tools..."
fr: "Monitoring, sauvegardes, outils réseau, bases de données..."
subtags:
- id: backup
title:
en: Backup
fr: Sauvegardes
- id: monitoring
title:
en: Monitoring
fr: Monitoring
- id: network
title:
en: Network
fr: Réseau
- id: db
title:
en: Databases
fr: Bases de données
- id: "iot"
icon: "home"
title:
en: "Internet of Things (IoT)"
fr: "Internet des objets (IoT)"
description:
en: "Home automation, energy dashboard..."
fr: "Domotique, énergie..."
- id: "wat"
icon: "tree"
title:
en: "Wat"
fr: "Wat"
description:
en: "Weird experimental or very-custom stuff"
fr: "Trucs expérimentaux et autres projets spécifiques"

View file

@ -7,7 +7,6 @@ import re
import json
import toml
import subprocess
import yaml
import time
from collections import OrderedDict
@ -15,7 +14,20 @@ from tools.packaging_v2.convert_v1_manifest_to_v2_for_catalog import convert_v1_
now = time.time()
catalog = json.load(open("apps.json"))
# Load categories and reformat the structure to have a list with an "id" key
categories = toml.load(open("categories.toml"))
for category_id, infos in categories.items():
infos["id"] = category_id
categories = list(categories.values())
# (Same for antifeatures)
antifeatures = toml.load(open("antifeatures.toml"))
for antifeature_id, infos in antifeatures.items():
infos["id"] = antifeature_id
antifeatures = list(antifeatures.values())
# Load the app catalog and filter out the non-working ones
catalog = toml.load(open("apps.toml"))
catalog = {
app: infos for app, infos in catalog.items() if infos.get("state") != "notworking"
}
@ -181,8 +193,6 @@ def build_catalog():
result_dict_with_manifest_v1 = copy.deepcopy(result_dict)
result_dict_with_manifest_v1 = {name: infos for name, infos in result_dict_with_manifest_v1.items() if float(str(infos["manifest"].get("packaging_format", "")).strip() or "0") < 2}
categories = yaml.load(open("categories.yml").read())
antifeatures = yaml.load(open("antifeatures.yml").read())
os.system("mkdir -p ./builds/default/v2/")
with open("builds/default/v2/apps.json", "w") as f:
f.write(
@ -239,7 +249,6 @@ def build_catalog():
##############################
# Version for catalog in doc #
##############################
categories = yaml.load(open("categories.yml").read())
os.system("mkdir -p ./builds/default/doc_catalog")
def infos_for_doc_catalog(infos):

View file

@ -4,7 +4,6 @@ import argparse
import json
import toml
import os
import yaml
from pathlib import Path
from jinja2 import Environment, FileSystemLoader
@ -33,11 +32,10 @@ def generate_READMEs(app_path: str):
upstream = manifest.get("upstream", {})
catalog = json.load(open(Path(os.path.abspath(__file__)).parent.parent.parent / "apps.json"))
catalog = toml.load(open(Path(os.path.abspath(__file__)).parent.parent.parent / "apps.toml"))
from_catalog = catalog.get(manifest['id'], {})
antifeatures_list = yaml.load(open(Path(os.path.abspath(__file__)).parent.parent.parent / "antifeatures.yml"), Loader=yaml.SafeLoader)
antifeatures_list = { e['id']: e for e in antifeatures_list }
antifeatures_list = toml.load(open(Path(os.path.abspath(__file__)).parent.parent.parent / "antifeatures.toml"))
if not upstream and not (app_path / "doc" / "DISCLAIMER.md").exists():
print(

28
tools/catalog_linter.py Normal file
View file

@ -0,0 +1,28 @@
import toml
import sys
catalog = toml.load(open('apps.toml'))
catalog = {app: infos for app, infos in catalog.items() if infos.get('state') == "working"}
categories = toml.load(open('categories.toml')).keys()
def check_apps():
for app, infos in catalog.items():
repo_name = infos.get("url", "").split("/")[-1]
if repo_name != app + "_ynh":
yield f"{app}: repo name should be {app}_ynh, not in {repo_name}"
category = infos.get("category")
if not category:
yield f"{app}: missing category"
if category not in categories:
yield f"{app}: category {category} is not defined in categories.toml"
errors = list(check_apps())
for error in errors:
print(error)
if errors:
sys.exit(1)

View file

@ -0,0 +1,106 @@
import time
import toml
import requests
import tempfile
import os
import sys
import json
from collections import OrderedDict
token = open(".github_token").read().strip()
tmpdir = tempfile.mkdtemp(prefix="update_app_levels_")
os.system(f"git clone 'https://oauth2:{token}@github.com/yunohost/apps' {tmpdir}")
os.system(f"git -C {tmpdir} checkout -b update_app_levels")
# Load the app catalog and filter out the non-working ones
catalog = toml.load(open(f"{tmpdir}/apps.toml"))
# Fetch results from the CI
CI_RESULTS_URL = "https://ci-apps.yunohost.org/ci/logs/list_level_stable_amd64.json"
ci_results = requests.get(CI_RESULTS_URL).json()
comment = {
"major_regressions": [],
"minor_regressions": [],
"improvements": [],
"outdated": [],
"missing": [],
}
for app, infos in catalog.items():
if infos.get("state") != "working":
continue
if app not in ci_results:
comment["missing"].append(app)
continue
# 3600 * 24 * 60 = ~2 months
if (int(time.time()) - ci_results[app].get("timestamp", 0)) > 3600 * 24 * 60:
comment["outdated"].append(app)
continue
ci_level = ci_results[app]["level"]
current_level = infos.get("level")
if ci_level == current_level:
continue
elif current_level is None or ci_level > current_level:
comment["improvements"].append((app, current_level, ci_level))
elif ci_level < current_level:
if ci_level < 4 and current_level >= 4:
comment["major_regressions"].append((app, current_level, ci_level))
else:
comment["minor_regressions"].append((app, current_level, ci_level))
infos["level"] = ci_level
# Also re-sort the catalog keys / subkeys
for app, infos in catalog.items():
catalog[app] = OrderedDict(sorted(infos.items()))
catalog = OrderedDict(sorted(catalog.items()))
updated_catalog = toml.dumps(catalog)
updated_catalog = updated_catalog.replace(",]", " ]")
open(f"{tmpdir}/apps.toml", "w").write(updated_catalog)
os.system(f"git -C {tmpdir} commit apps.toml -m 'Update app levels according to CI results'")
os.system(f"git -C {tmpdir} push origin update_app_levels --force")
os.system(f"rm -rf {tmpdir}")
PR_body = ""
if comment["major_regressions"]:
PR_body += "\n### Major regressions\n\n"
for app, current_level, new_level in comment['major_regressions']:
PR_body += f"- [ ] {app} | {current_level} -> {new_level} | https://ci-apps.yunohost.org/ci/apps/{app}/latestjob\n"
if comment["minor_regressions"]:
PR_body += "\n### Minor regressions\n\n"
for app, current_level, new_level in comment['minor_regressions']:
PR_body += f"- [ ] {app} | {current_level} -> {new_level} | https://ci-apps.yunohost.org/ci/apps/{app}/latestjob\n"
if comment["improvements"]:
PR_body += "\n### Improvements\n\n"
for app, current_level, new_level in comment['improvements']:
PR_body += f"- {app} | {current_level} -> {new_level} | https://ci-apps.yunohost.org/ci/apps/{app}/latestjob\n"
if comment["missing"]:
PR_body += "\n### Missing results\n\n"
for app in comment['missing']:
PR_body += f"- {app} | https://ci-apps.yunohost.org/ci/apps/{app}/latestjob\n"
if comment["outdated"]:
PR_body += "\n### Outdated results\n\n"
for app in comment['outdated']:
PR_body += f"- [ ] {app} | https://ci-apps.yunohost.org/ci/apps/{app}/latestjob\n"
PR = {"title": "Update app levels accoring to CI results",
"body": PR_body,
"head": "update_app_levels",
"base": "master"}
with requests.Session() as s:
s.headers.update({"Authorization": f"token {token}"})
r = s.post("https://api.github.com/repos/yunohost/apps/pulls", json.dumps(PR))
if r.status_code != 200:
print(r.text)
sys.exit(1)