Build des releases duniter dans Docker

$ python3 .gitlab/releaser.py
/bin/bash: line 60: python3: command not found
ERROR: Job failed: exit code 1

Bon apparemment il manque python 3 dans l’image docker/duniter-ci:v0.0.1 :confused:

bon je suis coincé, il faut renseigner un RELEASER_TOKEN mais après recherches dans la doc de gitlab ci je n’est pas trouvé de quoi il s’agit ! @florck on a besoin de tes lumières :sweat_smile:

$ python3 .gitlab/releaser.py
Traceback (most recent call last):
  File ".gitlab/releaser.py", line 154, in <module>
    main()
  File ".gitlab/releaser.py", line 150, in main
    exists_release, current_message = get_current_message()
  File ".gitlab/releaser.py", line 33, in get_current_message
    releaser_token = os.environ['RELEASER_TOKEN']
  File "/usr/lib/python3.5/os.py", line 725, in __getitem__
    raise KeyError(key) from None
KeyError: 'RELEASER_TOKEN'
ERROR: Job failed: exit code 1

EDIT : bon je doit vous laisser pour aujourd’hui, j’ai restaurer la CI, si quelqu’un peut trouver a quoi correspond ce RELEASER_TOKEN n’hésitez pas :wink:

Bon j’ai finalement trouvé a quoi correspondait le RELEASER_TOKEN, c’est un personnal access token d’un des utilisateur ayant des droits suffisants sur le dépot, j’ai donc créer un token et relancer le job… et j’ai encore un nouveau problème, avec python cette fois @Inso @florck je ne connait rien a python !

le script est ici : https://git.duniter.org/nodes/typescript/duniter/blob/DockerBuild/.gitlab/releaser.py

Ligne 43 il attend une réponse en JSON de la part de l’api gitlab et apparemment il reçoit une répondre d’un autre type :confused:

$ python3 .gitlab/releaser.py
Traceback (most recent call last):
  File ".gitlab/releaser.py", line 154, in <module>
    main()
  File ".gitlab/releaser.py", line 150, in main
    exists_release, current_message = get_current_message()
  File ".gitlab/releaser.py", line 43, in get_current_message
    data = json.load(response)
  File "/usr/lib/python3.5/json/__init__.py", line 268, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "/usr/lib/python3.5/json/__init__.py", line 312, in loads
    s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'

Je précise que j’ai fait la meme requete en cli, a savoir :

$ curl --header "Private-Token: RELEASER_TOKEN" https://git.duniter.org/api/v4/projects/47/repository/tags/0.99.5

Et j’ai bien une réponse JSON dans la console :

{"name":"0.99.5","message":"","commit":{"id":"61fa2161d36faffba21b9b6b7fe5d5d7ee34eb4a","short_id":"61fa2161","title":"use py3 image for release-message job","created_at":"2018-01-11T14:28:34.000+00:00","parent_ids":["aeb004c3d381912094f21954eaac4bac9fd6cfa7"],"message":"use py3 image for release-message job","author_name":"Éloïs","author_email":"***","authored_date":"2018-01-11T14:28:34.000+00:00","committer_name":"Éloïs","committer_email":"elois@ifee.fr","committed_date":"2018-01-11T14:28:34.000+00:00"},"release":null}

Bizarre… La seule raison à laquelle je pense serait que le résultat n’arrive pas en UTF-8, mais cela ne semble pas être le cas. :frowning:

En fait, après une bonne nuit, je pense avoir trouvé ce qui ne va pas : tu dois certainement recevoir une erreur 401. Vérifie s’il n’y a pas une faute de frappe dans le token que tu as utilisé ou dans le nom de la variable. Si cela peut se faire en toute sécurité, affiche la variable utilisée par la commande et tente d’exécuter la commande à la main depuis l’image Docker utilisée.

Tu peux afficher la réponse en ajoutant un print() et voir ce qui est retourné comme réponse…

ligne 42 dans la fonction get_current_message() :

response = urllib.request.urlopen(request) 

print(response)

data = json.load(response)
1 Like

JSON object must be str, not ‘bytes’

signifie que la réponse reçue est du bytes, ce qui signifie qu’il faudrait essayer de convertir en string. Cependant essaie d’afficher pour voir que c’est bien ça.

Car à ma connaissance le script marchait asis !

1 Like

merci @vit je viens d’ajouter un print de la réponse et de pusher un nouveau tag on vas bien voir si l’hypothèse de @sveyret est la bonne :slight_smile:

@florck @sveyret @vit , voilà le print de la réponse de l’api :

<http.client.HTTPResponse object at 0x7f4aff1f7c18>

@florck peut tu retry ton job qui avait marché debut décembre pour voir si c’est une mise a jours de l’api gitlab qui est en cause ?

On ne peut pas afficher response directement car il s’agit d’un flux. D’ailleurs, si c’était une chaine, on aurait utilisé json.loads (avec un s à la fin) et non json.load. As-tu vérifié si ton token était bien renseigné et si tu n’avais pas une erreur 401 depuis l’image Docker ?

J’ai revérifier et copier coller le contenu de la variable dans ma console la requête curl passe, et si je change 1 seul caractère j’ai effectivement une erreur 401. Bref, je suis certain à 100% que le token est bon et la variable aussi, je pense que le problème viens de l’environnement d’exécution, je ne sais pas dans quel image docker @florck a exécuté son script avec succès, car c’est un runner qui tournais sur son pc perso.

J’ai utiliser l’image tensorflow/tensorflow:latest-py3 pour éviter d’avoir a créer une image spécifique juste pour exécuter un script… mais peut être que le problème viens de là.

On vas être obligé de créer une image spécifique juste pour le job de publication des releases dans la tag page ? Je trouve ça franchement très lourd !

@florck peut tu nous partager ton dockerfile de ton runner flork-demo que l’on voit si le problème viens de là !

1 Like

en fait, cette démo se joue pas dans docker, donc non, c’est pas ça. Ce que tu affiches est un objet httpresponse, il faudrait réussir à lire ce qu’il à a dedans…

À priori, il faudrait exécuter response.read().decode('utf-8').

1 Like

Tu peux créer un petit script de test, comme test_request.py, avec dedans :

#!/usr/bin/env python3

import urllib.request

url = "https://g1-test.duniter.org/network/peers"

request = urllib.request.Request(url)
response = urllib.request.urlopen(request)

print('status: %s' % response.status)
print('headers:', response.headers)
print('body:' + response.read().decode('utf-8'))

Remplace l’url par celle qui pose problème et analyse la réponse… Hope it helps…

2 Likes

merci pour ton aide @vit, ton script s’éxécute avec succès donc le problème ne viens pas de l’image docker que j’ai choisi, j’ai ajouté ton code de print au script de @florck et voila ce que j’obtiens :

 $ python3 .gitlab/releaser.py
status: 200
headers: Server: nginx/1.12.1
Date: Mon, 15 Jan 2018 14:47:45 GMT
Content-Type: application/json
Content-Length: 501
Connection: close
Cache-Control: max-age=0, private, must-revalidate
Etag: W/"1c9722cad0d3c3072036eab7359b8fbe"
Vary: Origin
X-Frame-Options: SAMEORIGIN
X-Request-Id: ab86d658-b1aa-4d2f-b03c-47daa40c6a9c
X-Runtime: 0.255735
Strict-Transport-Security: max-age=31536000


Traceback (most recent call last):
  File ".gitlab/releaser.py", line 161, in <module>
    main()
  File ".gitlab/releaser.py", line 157, in main
    exists_release, current_message = get_current_message()
  File ".gitlab/releaser.py", line 44, in get_current_message
    print('body:' + response.read().decode('utf-8'))
UnicodeEncodeError: 'ascii' codec can't encode character '\xc9' in position 292: ordinal not in range(128)
ERROR: Job failed: exit code 1

La réponse à le statut 200, le problème ne viens donc pas de la requête ni du token @sveyret , c’est bien un problème d’utilisation de la réponse par le script python, mais comme je ne connais pas du tout python ça irai bien plus vite si l’un d’entre vous s’en chargeai car là ça fait déjà presque 1semaine qu’un bloque juste sur le job de publication de la tagpage et ça commence franchement a me gaver …

Bon avec @vit nous avons avancer, on pense que le souci viens d’un accent dans le nom de mon profil, ce qui expliquerai que le script d"origine est marché dans le cas de florck (pas d’accent dans son profil).

De toute façon comme l’authentification se fait en personnal access token c’est plus propre de créer un user dédié pour ce job, j’ai donc créer un user releaser-duniter puis commiter et tagger avec ce user, il semble toujours y avoir un problème mais uniquement lié au code de print, donc si ça se trouve ça vas fonctionner en le supprimant, je vais tester ça (et c’est parti pour un ième tag de test :stuck_out_tongue: )

$ python3 .gitlab/releaser.py
status: 200
headers: Server: nginx/1.12.1
Date: Mon, 15 Jan 2018 15:31:18 GMT
Content-Type: application/json
Content-Length: 519
Connection: close
Cache-Control: max-age=0, private, must-revalidate
Etag: W/"c4724aae611103f9cf00abdce9785cf8"
Vary: Origin
X-Frame-Options: SAMEORIGIN
X-Request-Id: 513d8c00-0f5f-4a9f-95f6-df3efd4b2e16
X-Runtime: 0.243020
Strict-Transport-Security: max-age=31536000


Traceback (most recent call last):
  File ".gitlab/releaser.py", line 161, in <module>
    main()
  File ".gitlab/releaser.py", line 157, in main
    exists_release, current_message = get_current_message()
  File ".gitlab/releaser.py", line 44, in get_current_message
    print('body:' + response.read())
TypeError: Can't convert 'bytes' object to str implicitly
ERROR: Job failed: exit code 1
1 Like

En tous cas, il semble que c’est la réponse qui n’est pas vraiment en UTF-8. Étrange.

C’est peut-être le + qui ne fonctionne pas tel quel, il faudrait essayer :

print(u'body:' + response.read().decode('utf-8'))

Note le u devant ‘body’.

Bon je crois que python se fou de ma gueule, voici 3 variantes du code et l’erreur générée :

data = json.load(response)
TypeError: the JSON object must be str, not 'bytes'

data = json.load(response.read())
AttributeError: 'str' object has no attribute 'read'

data = json.load(response.decode())
AttributeError: 'HTTPResponse' object has no attribute 'decode'

Je précise qu’on est ici dans un test sans accent nul part et que la réponse JSON est correctement printée par le script, la preuve : https://git.duniter.org/nodes/typescript/duniter/-/jobs/1340

La première erreur est normale.
json.load analyse l’objet (ici de la classe HTTPResponse) comme une string, celui-ci réagit alors en renvoyant une representation en bytes. Donc la première erreur est “normale”.

La seconde erreur n’est pas normale. response contient un objet de la classe HTTPResponse dont le body est extrait comme un fichier avec la méthode read(). Pourquoi la variable response contient une string cette fois là… Mystère.

La dernière erreur est normale.
La variable réponse est un objet et ne peut pas être traité comme une chaine de bytes avec decode().

response doit être traitée comme suit si la variable contient bien un objet de la classe HTTPResponse :

response_body = response.read().decode()
data = json.load(response_body)

Normalement (l’informatique étant une activité hautement incantatoire).

[EDIT]
J’ai compris !
Faire un response.read() vide le buffer de la réponse, ou amène le pointeur à la fin. bref, on ne peut faire le response.read() deux fois. Ce qui explique le changement de type de la variable selon que l’on fait un read() avant ou pas…

Si response_body est une chaine, alors ce n’est pas load qu’il faut appeler mais :

json.loads(response_body) 

(avec un s à la fin du nom de fonction).

1 Like