I expected sending this request to the GraphQL endpoint along with an appropriate Authorization header to return a non-null viewer:
query {
viewer {
id
githubUserName
}
}
It returns this:
{"data":{"viewer":null}}
Testcase (python3)
#!/usr/bin/env python3
# NOTE: Before running this, put a Cirrus CI API token in ./token.txt
import json
from urllib.request import urlopen, Request
from pathlib import Path
token = Path('token.txt').read_text().strip()
query = """
query {
viewer {
id
githubUserName
}
}
"""
data = json.dumps({'query': query}).encode('ascii')
headers = {
'Authorization': 'Bearer ' + token,
}
request = Request('https://api.cirrus-ci.com/graphql', data=data, headers=headers)
# Uncommenting the line below will send the request to httpbin, which just
# echoes the data back. Note that it gets the Authorization header.
#request = Request('https://httpbin.org/post', data=data, headers=headers)
result = urlopen(request)
text = result.read().decode()
print(text)
As mentioned in the testcase, if you uncomment the second Request(...) call and run it, httpbin.org can get the Authorization header without issue.
Try calling urllib.request.urlcleanup() first. This should remove any malformed data (including auth) iirc
Yeah, this is a API token which is not associated with a user. Such tokens are also used for organizations. What is your use case for this query?
As a workaround you can copy cirrusUserId and cirrusAuthToken cookies from your browser and auth with them to make viewer work.
This was supposed to be a testcase, but it looks like I actually got mixed up at some point and went down the wrong rabbit hole. Sorry about that. :sweat_smile:
The original problem was that I was getting Internal Server Error(s) while executing query for a query to trigger this manual task: https://cirrus-ci.com/task/5136260581031936 .
Here's a testcase for that
#!/usr/bin/env python3
# NOTE: Before running this, put a Cirrus CI API token in ./token.txt
import json
from urllib.request import urlopen, Request
from pathlib import Path
token = Path('token.txt').read_text().strip()
query = """
mutation TaskDetailsTriggerMutation($input: TaskTriggerInput!) {
trigger(input: $input) {
task {
id
}
}
}
"""
variables = {
'input': {
# https://cirrus-ci.com/task/5136260581031936
'taskId': '5136260581031936',
}
}
req_data = json.dumps({
'query': query,
'variables': variables,
}).encode('ascii')
headers = {
'Authorization': 'Bearer ' + token,
}
request = Request('https://api.cirrus-ci.com/graphql', data=req_data, headers=headers)
result = urlopen(request)
text = result.read().decode()
print(result.status)
print(text)
And the output of running it:
$ ./testcase.py
200
{"errors":[{"message":"Internal Server Error(s) while executing query","extensions":null,"path":null}],"data":{"trigger":null}}
$
Interesting... this should've been error with No user authorized! since not all mutations support working with the API authorization. This will need to be fixed.
This should work now for triggering.
@fkorotkov I'm still getting Internal Server Error for some reason, with the same testcase as before.
@duckinator there was a problem in an underlying microservide. Just added an integration test for your query and fixed the root cause. You can try again. 馃檶 Sorry for the delay.
@fkorotkov it's still giving an Internal Server Error for my testcase. :sweat_smile: Is there something I can do to get more debug information for y'all?
And no worries about the delay, ya'll are doing great. :+1:
I put my release.py script on GitHub, and updated it to print more request+response details, in case it's helpful.
The output under each === REQUEST === section is the exact string that is being sent. The output under each === RESPONSE === section is the exact response string returned from Cirrus CI. The only thing I've done to them is call .decode() so they're treated as strings instead of an ascii byte strings.
Output with debug information
=== REQUEST ===
{
"query": "query GitHubRepositoryQuery(\n $owner: String!\n $name: String!\n $branch: String\n) {\n githubRepository(owner: $owner, name: $name) {\n ...RepositoryBuildList_repository\n id\n }\n}\n\nfragment RepositoryBuildList_repository on Repository {\n id\n owner\n name\n masterBranch\n builds(last: 1, branch: $branch) {\n edges {\n node {\n id\n status\n tasks {\n id\n name\n status\n }\n }\n }\n }\n}\n\n",
"variables": {
"owner": "duckinator",
"name": "keress",
"branch": "test"
}
}
=== RESPONSE ===
{"data":{"githubRepository":{"id":"5762221211648000","owner":"duckinator","name":"keress","masterBranch":"master","builds":{"edges":[{"node":{"id":"5647376050552832","status":"COMPLETED","tasks":[{"id":"5699210534453248","name":"test","status":"COMPLETED"},{"id":"5136260581031936","name":"nightly","status":"PAUSED"}]}}]}}}}
=== REQUEST ===
{
"query": "mutation TaskDetailsTriggerMutation($input: TaskTriggerInput!) {\n trigger(input: $input) {\n task {\n id\n }\n }\n}\n\n",
"variables": {
"input": {
"taskId": "5136260581031936"
}
}
}
=== RESPONSE ===
{"errors":[{"message":"Internal Server Error(s) while executing query","extensions":null,"path":null}],"data":{"trigger":null}}
Thank you for the scripts. I've fixed the error reporting so now it will properly report errors instead of vague Internal Server Error(s).
You don't pass clientMutationId variable which is required for all mutations for deduplication purposes.
That did the trick! Thanks for all the help, @fkorotkov! :slightly_smiling_face: