Déploiement du projet
=====================

.. _PyPI: https://pypi.org/project/squirrel-battle/
.. _AUR: https://aur.archlinux.org/packages/python-squirrel-battle/
.. _Debian: https://gitlab.crans.org/ynerant/squirrel-battle/-/jobs/artifacts/master/raw/build/python3-squirrelbattle_3.14.1_all.deb?job=build-deb
.. _installation: install.html

À chaque nouvelle version du projet, il est compilé et déployé dans PyPI_, dans
l'AUR_ et un paquet Debian_ est créé, voir la page d'installation_.


PyPI
----

Définition du paquet
~~~~~~~~~~~~~~~~~~~~

.. _setup.py: https://gitlab.crans.org/ynerant/squirrel-battle/-/blob/master/setup.py

La documentation sur le packaging dans PyPI_ est disponible `ici
<https://packaging.python.org/tutorials/packaging-projects/>`_.

Le fichier `setup.py`_ contient l'ensemble des instructions d'installation du
paquet ainsi que des détails à fournir à PyPI :

.. code:: python

    #!/usr/bin/env python3
    import os

    from setuptools import find_packages, setup

    with open("README.md", "r") as f:
        long_description = f.read()

    # Compile messages
    for language in ["de", "es", "fr"]:
        args = ["msgfmt", "--check-format",
                "-o", f"squirrelbattle/locale/{language}/LC_MESSAGES"
                      "/squirrelbattle.mo",
                f"squirrelbattle/locale/{language}/LC_MESSAGES"
                "/squirrelbattle.po"]
        print(f"Compiling {language} messages...")
        subprocess.Popen(args)

    setup(
        name="squirrel-battle",
        version="3.14.1",
        author="ÿnérant, eichhornchen, nicomarg, charlse",
        author_email="squirrel-battle@crans.org",
        description="Watch out for squirrel's knives!",
        long_description=long_description,
        long_description_content_type="text/markdown",
        url="https://gitlab.crans.org/ynerant/squirrel-battle",
        packages=find_packages(),
        license='GPLv3',
        classifiers=[
            "Development Status :: 4 - Beta",
            "Environment :: Console :: Curses",
            "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
            "Natural Language :: French",
            "Operating System :: OS Independent",
            "Programming Language :: Python :: 3",
            "Programming Language :: Python :: 3.6",
            "Programming Language :: Python :: 3.7",
            "Programming Language :: Python :: 3.8",
            "Programming Language :: Python :: 3.9",
            "Topic :: Games/Entertainment",
        ],
        python_requires='>=3.6',
        include_package_data=True,
        package_data={"squirrelbattle": ["assets/*", "locale/*/*/*.mo"]},
        entry_points={
            "console_scripts": [
                "squirrel-battle = squirrelbattle.bootstrap:Bootstrap.run_game",
            ]
        }
    )

Ce fichier contient le nom du paquet, sa version, l'auteur et son contact,
sa description en une ligne et sa description longue, le lien d'accueil du projet,
sa licence, ses classificateurs et son exécutable.

Il commence tout d'abord par compiler les fichiers de `traduction <translation.html>`_.

Le paramètre ``entry_points`` définit un exécutable nommé ``squirrel-battle``,
qui permet de lancer le jeu.


Installation locale du paquet
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

L'installation du paquet localement dans son environnement Python (virtuel ou non)
peut se faire en exécutant ``pip install -e .``.


Génération des binaires
~~~~~~~~~~~~~~~~~~~~~~~

Les paquets ``setuptools`` (``python3-setuptools`` pour APT, ``python-setuptools``
pour pacman) et ``wheel`` (``python3-wheel`` pour APT, ``python-wheel`` pour pacman)
sont nécessaires. Une fois installés, il faut appeler la commande :

.. code:: bash

  python3 setup.py sdist bdist_wheel

Une fois cela fait, le dossier ``dist/`` contiendra les archives à transmettre à PyPI.


Publier sur PyPI
~~~~~~~~~~~~~~~~

Il faut avant tout avoir un compte sur PyPI. Dans `votre compte PyPI
<https://pypi.org/manage/account/>`_, il faut générer un jeton d'accès API.

Dans le fichier ``.pypirc`` dans le répertoire principal de l'utilisateur,
il faut ajouter le jeton d'accès :

.. code::

  [pypi]
    username = __token__
    password = pypi-my-pypi-api-access-token

Cela permet de s'authentifier directement par ce jeton.

Ensuite, il faut installer ``twine``, qui permet de publier sur PyPI.

Il suffit ensuite d'appeler :

.. code:: bash

  twine upload dist/*

pour envoyer le paquet sur PyPI.


.. note::

  À des fins de tests, il est possible d'utiliser le dépôt `<https://test.pypi.org>`_.
  Les différences sont au niveau de l'authentification, où il faut l'en-tête
  ``[testpypi]`` dans le ``.pypirc``, et il faut envoyer le paquet avec
  ``twine upload --repository testpypi dist/``.


Publier dans l'AUR
------------------

Fonctionnement du packaging
~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. _python-squirrel-battle: https://aur.archlinux.org/packages/python-squirrel-battle/
.. _python-squirrel-battle-git: https://aur.archlinux.org/packages/python-squirrel-battle-git/

Deux paquets sont publiés dans l'AUR (Arch User Repository) :

- python-squirrel-battle_
- python-squirrel-battle-git_

Le packaging dans Arch Linux se fait en commitant un fichier ``PKGBUILD`` dans
le dépôt à l'adresse ``ssh://aur@aur.archlinux.org/packagename.git``,
en remplaçant ``packagename`` par le nom du paquet.

Le second paquet compile directement le jeu à partir de la branche ``master``
du dépôt Git. Le fichier ``PKGBUILD`` dispose de cette structure :

.. code::

    # Maintainer: Yohann D'ANELLO <squirrel-battle@crans.org>

    pkgbase=squirrel-battle
    pkgname=python-squirrel-battle-git
    pkgver=3.14.1
    pkgrel=1
    pkgdesc="Watch out for squirrel's knives!"
    arch=('any')
    url="https://gitlab.crans.org/ynerant/squirrel-battle"
    license=('GPLv3')
    depends=('python')
    makedepends=('gettext' 'python-setuptools')
    depends=('noto-fonts-emoji')
    checkdepends=('python-tox')
    ssource=("git+https://gitlab.crans.org/ynerant/squirrel-battle.git")
    sha256sums=("SKIP")

    pkgver() {
      cd pkgbase
      git describe --long --tags | sed -r 's/^v//;s/([^-]*-g)/r\1/;s/-/./g'
    }
    build() {
      cd $pkgbase
      python setup.py build
    }

    check() {
      cd $pkgbase
      tox -e py3
      tox -e linters
    }

    package() {
      cd $pkgbase
      python setup.py install --skip-build \
                              --optimize=1 \
                              --root="${pkgdir}"
      install -vDm 644 README.md \
        -t "${pkgdir}/usr/share/doc/${pkgname}"
      install -vDm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
    }

Ces instructions permettent de cloner le dépôt, l'installer et exécuter des tests,
en plus de définir les attributs du paquet.

Le fichier ``PKGBUILD`` du paquet ``python-squirrel-battle``, synchronisé avec
les releases, est plus ou moins similaire :

.. code::

    # Maintainer: Yohann D'ANELLO <squirrel-battle@crans.org>

    pkgbase=squirrel-battle
    pkgname=python-squirrel-battle
    pkgver=3.14.1
    pkgrel=1
    pkgdesc="Watch out for squirrel's knives!"
    arch=('any')
    url="https://gitlab.crans.org/ynerant/squirrel-battle"
    license=('GPLv3')
    depends=('python')
    makedepends=('gettext' 'python-setuptools')
    depends=('noto-fonts-emoji')
    checkdepends=('python-tox')
    source=("https://gitlab.crans.org/ynerant/squirrel-battle/-/archive/v3.14.1/$pkgbase-v$pkgver.tar.gz")
    sha256sums=("6090534d598c0b3a8f5acdb553c12908ba8107d62d08e17747d1dbb397bddef0")

    build() {
      cd $pkgbase-v$pkgver
      python setup.py build
    }

    check() {
      cd $pkgbase-v$pkgver
      tox -e py3
      tox -e linters
    }

    package() {
      cd $pkgbase-v$pkgver
      python setup.py install --skip-build \
                              --optimize=1 \
                              --root="${pkgdir}"
      install -vDm 644 README.md \
        -t "${pkgdir}/usr/share/doc/${pkgname}"
      install -vDm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
    }

Il se contente ici de télécharger l'archive de la dernière release, et de travailler
dessus.


Mettre à jour
~~~~~~~~~~~~~

Pour mettre à jour le dépôt, une fois les dépôts
``ssh://aur@aur.archlinux.org/python-squirrel-battle.git`` et
``ssh://aur@aur.archlinux.org/python-squirrel-battle-git.git`` clonés,
il suffit de mettre à jour le paramètre ``pkgver`` pour la bonne version,
de régénérer le fichier ``.SRCINFO`` en faisant
``makepkg --printsrcinfo > .SRCINFO``, puis de committer/pousser.


Construction du paquet Debian
-----------------------------

Structure du paquet
-------------------

L'ensemble des instructions pour construire le paquet Debian est situé dans le
dossier ``debian/``.

Le fichier ``changelog`` est à modifier à chaque nouvelle version, le fichier
``compat`` contient la version minimale de Debian requise (``10`` pour Debian
Buster), le fichier ``copyright`` contient la liste des fichiers distribués sous
quelle licence (ici GPLv3), le fichier ``control`` contient les informations du
paquet, le fichier ``install`` les fichiers de configuration à installer
(ici le fix de l'affichage de l'écurueil), et enfin le fichier ``rules`` l'ensemble
des instructions à exécuter pour installer.

Le paquet ``fonts-noto-color-emoji`` est en dépendance pour le bon affichage
des émojis.

Mettre à jour le paquet
-----------------------

Pour changer la version du paquet, il faut ajouter des lignes dans le fichier
``changelog``.


Construire le paquet
--------------------

Il faut partir d'une installation de Debian.

D'abord on installe les paquets nécessaires :

.. code::

  apt update
  apt --no-install-recommends install build-essential debmake dh-python debhelper gettext python3-all python3-setuptools

On peut ensuite construire le paquet :

.. code:: bash

  dpkg-buildpackage
  mkdir build && cp ../*.deb build/

Le paquet sera installé dans ``build/python3-squirrel-battle_3.14.1_all.deb``.

Le paquet Debian_ est construit par l'intégration continue Gitlab et ajouté
à chaque release.