Bug 1142779 - Enable testdroid devices to be used within test tasks r=lightsofapollo

This commit is contained in:
Gregory Arndt 2015-03-12 17:43:28 -05:00
parent ce12d9a8e2
commit 6f86baed1e
17 changed files with 453 additions and 7 deletions

View File

@ -0,0 +1,48 @@
FROM ubuntu:14.04
MAINTAINER Greg Arndt <garndt@mozilla.com>
RUN mkdir -p /home/worker/upload/logs
WORKDIR /home/worker
RUN apt-get install -y curl
# Add PPA for latest nodejs versions. Do not need to run apt-get update after this
# as the script already does it.
RUN curl -sL https://deb.nodesource.com/setup | sudo bash -
RUN apt-get upgrade -y && apt-get install -y \
build-essential \
ca-certificates \
nodejs \
python-dev \
mercurial \
git \
android-tools-adb \
android-tools-fastboot\
jq
# Get pip and virtualenv
RUN curl https://bootstrap.pypa.io/get-pip.py | python
RUN pip install virtualenv
RUN git config --global user.email "mozilla@example.com" && \
git config --global user.name "mozilla"
# Get node packages
RUN npm install -g taskcluster-vcs@2.3.0
WORKDIR /home/worker
ADD bin /home/worker/bin
ADD data /home/worker/data
ADD https://raw.githubusercontent.com/taskcluster/buildbot-step/master/buildbot_step /home/worker/bin/buildbot_step
RUN chmod u+x /home/worker/bin/*
ENV HOME /home/worker
ENV SHELL /bin/bash
ENV PATH $PATH:/home/worker/bin
ENV CLOUD_HOST testdroid
ENTRYPOINT ["entrypoint"]

View File

@ -0,0 +1 @@
0.0.2

View File

@ -0,0 +1,26 @@
#! /bin/bash -e
echo "Validating Task"
python /home/worker/bin/validate_task.py
echo "Retrieving device"
res=`curl --request POST -H "Content-Type: application/json" -d "$DEVICE_CAPABILITIES" http://$CLOUD_HOST/device`
status=`echo $res | jq .session`
if [[ $status == 'null' ]]; then
echo "Session could not be created with a device."
exit -1
fi
export SESSION_ID=`echo $res | jq .session.id`
export SERIAL_ID=`echo $res | jq -r .proxies.adb.serialId`
export ADB_HOST=`echo $res | jq .proxies.adb.forwardHost`
export ADB_PORT=`echo $res | jq .proxies.adb.port`
export MARIONETTE_HOST=`echo $res | jq .proxies.marionette.forwardHost`
export MARIONETTE_PORT=`echo $res | jq .proxies.marionette.port`
export PROXY_HOST=`echo $res | jq -r .proxyHost`
echo "Retrieved device. Session: $SESSION_ID"
curl -o /home/worker/data/device.json -s -H "Accept: application/json" http://$CLOUD_HOST/device/properties
eval $@

View File

@ -0,0 +1,75 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import os.path
import json
import urllib2
import sys
import re
import subprocess
repo_matcher = re.compile(r'[a-z]+://(hg|git)\.mozilla\.org')
image_matcher = re.compile(r'^https:\/\/queue\.taskcluster\.net\/v1\/task\/.+\/artifacts\/private\/build\/flame-kk\.zip$')
def get_task(taskid):
return json.load(urllib2.urlopen('https://queue.taskcluster.net/v1/task/' + taskid))
def check_task(task):
payload = task['payload']
if 'DEVICE_CAPABILITIES' not in payload['env']:
print('Device capalities are required.', file=sys.stderr)
return -1
capabilities = json.loads(payload['env']['DEVICE_CAPABILITIES'])
if 'build' not in capabilities:
print('Build image url is required', file=sys.stderr)
return -1
image = capabilities['build']
if not image_matcher.match(image):
print('Invalid image url', file=sys.stderr)
return -1
if 'GAIA_HEAD_REPOSITORY' not in payload['env']:
print('Task has no head gaia repository', file=sys.stderr)
return -1
repo = payload['env']['GAIA_HEAD_REPOSITORY']
# if it is not a mozilla repository, fail
if not repo_matcher.match(repo):
print('Invalid head repository', repo, file=sys.stderr)
return -1
if 'GAIA_BASE_REPOSITORY' not in payload['env']:
print('Task has no base gaia repository', file=sys.stderr)
return -1
repo = payload['env']['GAIA_BASE_REPOSITORY']
if not repo_matcher.match(repo):
print('Invalid base repository', repo, file=sys.stderr)
return -1
if 'artifacts' in payload:
artifacts = payload['artifacts']
# If any of the artifacts makes reference to 'public',
# abort the task
if any(map(lambda a: 'public' in a, artifacts)):
print('Cannot upload to public', file=sys.stderr)
return -1
return 0
def main():
taskid = os.getenv('TASK_ID')
# If the task id is None, we assume we are running docker locally
if taskid is not None:
task = get_task(taskid)
sys.exit(check_task(task))
if __name__ == '__main__':
main()

View File

@ -0,0 +1,22 @@
#! /bin/bash -ve
while getopts "t:g:" arg; do
case $arg in
t)
TAG=$OPTARG
;;
g)
GAIA_TESTVARS=$OPTARG
;;
esac
done
pushd $(dirname $0)
test $TAG
test -f "$GAIA_TESTVARS"
cp $GAIA_TESTVARS data/gaia_testvars.json
docker build -t $TAG .
rm -f data/gaia_testvars.json

View File

@ -0,0 +1,29 @@
taskId: 1
task:
metadata:
name: '[TC] Gaia Python Integration Tests - device'
description: Gaia Python Integration Tests
workerType: testdroid-device
retries: 0
payload:
env:
DEVICE_CAPABILITIES: '{"type":"flame","memory":"319","sims": "1","build":"https://queue.taskcluster.net/v1/task/H0FPqxakT06Eg4wo4zPwMw/runs/0/artifacts/private/build/flame-kk.zip"}'
GAIA_HEAD_REPOSITORY: 'http://hg.mozilla.org/integration/gaia-central'
GAIA_BASE_REPOSITORY: 'http://github.com/mozilla-b2g/gaia'
command:
- entrypoint
- >
tc-vcs checkout /home/worker/gaia/source $GAIA_BASE_REPOSITORY $GAIA_HEAD_REPOSITORY $GAIA_REV $GAIA_REF &&
cd gaia/source/tests/python/gaia-ui-tests/ &&
python setup.py develop &&
pip install py &&
cd /home/worker/ &&
gaiatest --testvars=/home/worker/data/testdroid.json --testvars=/home/worker/data/acknowledge_risks.json --testvars=/home/worker/data/common.json --testvars=/home/worker/data/device.json --adb-host=$PROXY_HOST --adb-port=$ADB_PORT --address=$PROXY_HOST:$MARIONETTE_PORT --device $SERIAL_ID --xml-output=/home/worker/upload/logs/xml_output.xml --timeout=10000 --log-html=/home/worker/upload/logs/index.html --restart --type=b2g+sanity-dsds --log-mach=- --log-raw=/home/worker/upload/logs/raw.log gaia/source/tests/python/gaia-ui-tests/gaiatest/tests/functional/manifest.ini
artifacts:
'private/device.json':
type: file
path: '/home/worker/data/device.json'
'private/logs':
type: directory
path: '/home/worker/upload/logs/'

View File

@ -0,0 +1,29 @@
taskId: 1
task:
metadata:
name: '[TC] Gaia Python Integration Tests - device'
description: Gaia Python Integration Tests
workerType: testdroid-device
retries: 0
payload:
env:
DEVICE_CAPABILITIES: "{\"type\":\"flame\",\"memory\":\"319\",\"sims\": \"1\",\"build\":\"https://queue.some_other_domain.net/v1/task/fLOiHaudRkepg9yEiaM1Mg/artifacts/private/build/flame-kk.zip\"}"
GAIA_HEAD_REPOSITORY: 'http://hg.mozilla.org/integration/gaia-central'
GAIA_BASE_REPOSITORY: 'http://hg.mozilla.org/integration/gaia-central'
command:
- entrypoint
- >
tc-vcs checkout /home/worker/gaia/source $GAIA_BASE_REPOSITORY $GAIA_HEAD_REPOSITORY $GAIA_REV $GAIA_REF &&
cd gaia/source/tests/python/gaia-ui-tests/ &&
python setup.py develop &&
pip install py &&
cd /home/worker/ &&
gaiatest --testvars=/home/worker/data/testdroid.json --testvars=/home/worker/data/acknowledge_risks.json --testvars=/home/worker/data/common.json --testvars=/home/worker/data/device.json --adb-host=$PROXY_HOST --adb-port=$ADB_PORT --address=$PROXY_HOST:$MARIONETTE_PORT --device $SERIAL_ID --xml-output=/home/worker/upload/logs/xml_output.xml --timeout=10000 --log-html=/home/worker/upload/logs/index.html --restart --type=b2g+sanity-dsds --log-mach=- --log-raw=/home/worker/upload/logs/raw.log gaia/source/tests/python/gaia-ui-tests/gaiatest/tests/functional/manifest.ini
artifacts:
'private/device.json':
type: file
path: '/home/worker/data/device.json'
'private/logs':
type: directory
path: '/home/worker/upload/logs/'

View File

@ -0,0 +1,29 @@
taskId: 1
task:
metadata:
name: '[TC] Gaia Python Integration Tests - device'
description: Gaia Python Integration Tests
workerType: testdroid-device
retries: 0
payload:
env:
DEVICE_CAPABILITIES: '{"type":"flame","memory":"319","sims": "1","build":"https://queue.taskcluster.net/v1/task/H0FPqxakT06Eg4wo4zPwMw/runs/0/artifacts/private/build/flame-kk.zip"}'
GAIA_BASE_REPOSITORY: 'http://hg.mozilla.org/integration/gaia-central'
GAIA_HEAD_REPOSITORY: 'http://github.com/mozilla-b2g/gaia'
command:
- entrypoint
- >
tc-vcs checkout /home/worker/gaia/source $GAIA_BASE_REPOSITORY $GAIA_HEAD_REPOSITORY $GAIA_REV $GAIA_REF &&
cd gaia/source/tests/python/gaia-ui-tests/ &&
python setup.py develop &&
pip install py &&
cd /home/worker/ &&
gaiatest --testvars=/home/worker/data/testdroid.json --testvars=/home/worker/data/acknowledge_risks.json --testvars=/home/worker/data/common.json --testvars=/home/worker/data/device.json --adb-host=$PROXY_HOST --adb-port=$ADB_PORT --address=$PROXY_HOST:$MARIONETTE_PORT --device $SERIAL_ID --xml-output=/home/worker/upload/logs/xml_output.xml --timeout=10000 --log-html=/home/worker/upload/logs/index.html --restart --type=b2g+sanity-dsds --log-mach=- --log-raw=/home/worker/upload/logs/raw.log gaia/source/tests/python/gaia-ui-tests/gaiatest/tests/functional/manifest.ini
artifacts:
'private/device.json':
type: file
path: '/home/worker/data/device.json'
'private/logs':
type: directory
path: '/home/worker/upload/logs/'

View File

@ -0,0 +1,29 @@
taskId: 1
task:
metadata:
name: '[TC] Gaia Python Integration Tests - device'
description: Gaia Python Integration Tests
workerType: testdroid-device
retries: 0
payload:
env:
DEVICE_CAPABILITIES: '{"type":"flame","memory":"319","sims": "1","build":"https://queue.taskcluster.net/v1/task/H0FPqxakT06Eg4wo4zPwMw/runs/0/artifacts/private/build/flame-kk.zip"}'
GAIA_BASE_REPOSITORY: 'http://hg.mozilla.org/integration/gaia-central'
GAIA_HEAD_REPOSITORY: 'http://github.com/mozilla-b2g/gaia'
command:
- entrypoint
- >
tc-vcs checkout /home/worker/gaia/source $GAIA_BASE_REPOSITORY $GAIA_HEAD_REPOSITORY $GAIA_REV $GAIA_REF &&
cd gaia/source/tests/python/gaia-ui-tests/ &&
python setup.py develop &&
pip install py &&
cd /home/worker/ &&
gaiatest --testvars=/home/worker/data/testdroid.json --testvars=/home/worker/data/acknowledge_risks.json --testvars=/home/worker/data/common.json --testvars=/home/worker/data/device.json --adb-host=$PROXY_HOST --adb-port=$ADB_PORT --address=$PROXY_HOST:$MARIONETTE_PORT --device $SERIAL_ID --xml-output=/home/worker/upload/logs/xml_output.xml --timeout=10000 --log-html=/home/worker/upload/logs/index.html --restart --type=b2g+sanity-dsds --log-mach=- --log-raw=/home/worker/upload/logs/raw.log gaia/source/tests/python/gaia-ui-tests/gaiatest/tests/functional/manifest.ini
artifacts:
'public/device.json':
type: file
path: '/home/worker/data/device.json'
'private/logs':
type: directory
path: '/home/worker/upload/logs/'

View File

@ -0,0 +1,35 @@
#!/usr/bin/env python
import unittest
import sys
import yaml
sys.path.append('../bin')
from validate_task import check_task
def load_task(task_file):
content = open(task_file, 'r')
return yaml.load(content)['task']
class TaskValidationTest(unittest.TestCase):
def test_valid_task(self):
task = load_task('valid.yml')
self.assertEquals(check_task(task), 0)
def test_invalid_base_repo(self):
task = load_task('invalid_base_repo.yml')
self.assertEquals(check_task(task), -1)
def test_invalid_head_repo(self):
task = load_task('invalid_head_repo.yml')
self.assertEquals(check_task(task), -1)
def test_public_artifact(self):
task = load_task('public.yml')
self.assertEquals(check_task(task), -1)
def test_invalid_build(self):
task = load_task('invalid_build.yml')
self.assertEquals(check_task(task), -1)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,29 @@
taskId: 1
task:
metadata:
name: '[TC] Gaia Python Integration Tests - device'
description: Gaia Python Integration Tests
workerType: testdroid-device
retries: 0
payload:
env:
DEVICE_CAPABILITIES: "{\"type\":\"flame\",\"memory\":\"319\",\"sims\": \"1\",\"build\":\"https://queue.taskcluster.net/v1/task/fLOiHaudRkepg9yEiaM1Mg/artifacts/private/build/flame-kk.zip\"}"
GAIA_HEAD_REPOSITORY: 'http://hg.mozilla.org/integration/gaia-central'
GAIA_BASE_REPOSITORY: 'http://hg.mozilla.org/integration/gaia-central'
command:
- entrypoint
- >
tc-vcs checkout /home/worker/gaia/source $GAIA_BASE_REPOSITORY $GAIA_HEAD_REPOSITORY $GAIA_REV $GAIA_REF &&
cd gaia/source/tests/python/gaia-ui-tests/ &&
python setup.py develop &&
pip install py &&
cd /home/worker/ &&
gaiatest --testvars=/home/worker/data/testdroid.json --testvars=/home/worker/data/acknowledge_risks.json --testvars=/home/worker/data/common.json --testvars=/home/worker/data/device.json --adb-host=$PROXY_HOST --adb-port=$ADB_PORT --address=$PROXY_HOST:$MARIONETTE_PORT --device $SERIAL_ID --xml-output=/home/worker/upload/logs/xml_output.xml --timeout=10000 --log-html=/home/worker/upload/logs/index.html --restart --type=b2g+sanity-dsds --log-mach=- --log-raw=/home/worker/upload/logs/raw.log gaia/source/tests/python/gaia-ui-tests/gaiatest/tests/functional/manifest.ini
artifacts:
'private/device.json':
type: file
path: '/home/worker/data/device.json'
'private/logs':
type: directory
path: '/home/worker/upload/logs/'

View File

@ -311,6 +311,12 @@ class Graph(object):
build_task['task']['extra']['locations']['build']
)
# img_url is only necessary for device builds
img_url = ARTIFACT_URL.format(
build_parameters['build_slugid'],
build_task['task']['extra']['locations'].get('img', '')
)
define_task = DEFINE_TASK.format(build_task['task']['workerType'])
graph['scopes'].append(define_task)
@ -339,6 +345,7 @@ class Graph(object):
test = test['allowed_build_tasks'][build['task']]
test_parameters = copy.copy(build_parameters)
test_parameters['build_url'] = build_url
test_parameters['img_url'] = img_url
test_parameters['tests_url'] = tests_url
test_definition = templates.load(test['task'], {})['task']
@ -449,7 +456,7 @@ class CIBuild(object):
head_ref = params['head_ref'] or head_rev
build_parameters = {
build_parameters = dict(gaia_info().items() + {
'docker_image': docker_image,
'owner': params['owner'],
'from_now': json_time_from_now,
@ -461,7 +468,7 @@ class CIBuild(object):
'mozharness_repository': params['mozharness_repository'],
'mozharness_ref': params['mozharness_ref'],
'mozharness_rev': params['mozharness_rev']
}
}.items())
try:
build_task = templates.load(params['build_task'], build_parameters)
@ -501,21 +508,23 @@ class CITest(object):
raise ValueError(
'"chunk" must be a value between 1 and "total_chunks (default 1)"')
build_url, tests_url = self._get_build_and_tests_url(task_id)
build_url, img_url, tests_url = self._get_build_and_tests_url(task_id)
test_parameters = {
test_parameters = dict(gaia_info().items() + {
'docker_image': docker_image,
'build_url': ARTIFACT_URL.format(task_id, build_url),
'img_url': ARTIFACT_URL.format(task_id, img_url),
'tests_url': ARTIFACT_URL.format(task_id, tests_url),
'total_chunks': total_chunks,
'chunk': chunk,
'owner': owner,
'from_now': json_time_from_now,
'now': current_json_time()
}
}.items())
try:
test_task = import_yaml(test_task, test_parameters)
templates = Templates(ROOT)
test_task = templates.load(test_task, test_parameters)
except IOError:
sys.stderr.write(
"Could not load test task file. Ensure path is a relative " \
@ -528,7 +537,7 @@ class CITest(object):
def _get_build_and_tests_url(self, task_id):
task = get_task(task_id)
locations = task['extra']['locations']
return locations['build'], locations['tests']
return locations['build'], locations.get('img', ''), locations['tests']
@CommandProvider
class CIDockerRun(object):

View File

@ -18,3 +18,6 @@ builds:
types:
opt:
task: tasks/builds/b2g_flame_kk_eng.yml
gaia-ui-test-sanity:
task: tasks/tests/flame_kk_gaia_ui_test_sanity.yml

View File

@ -28,6 +28,7 @@ flags:
- gaia-linter
- gaia-unit
- gaia-unit-oop
- gaia-ui-test-sanity
- gaia-ui-test-oop
- gaia-ui-test-accessibility
- gaia-ui-test-functional

View File

@ -29,4 +29,7 @@ task:
locations:
img: 'private/build/flame-kk.zip'
GAIA_OPTIMIZE: '1'
B2G_SYSTEM_APPS: '1'
B2G_UPDATER: '1'

View File

@ -0,0 +1,42 @@
# This task is the base for most tests in gecko.
task:
created: '{{now}}'
deadline: '{{#from_now}}24 hours{{/from_now}}'
metadata:
source: http://todo.com/soon
owner: mozilla-taskcluster-maintenance@mozilla.com
tags:
createdForUser: {{owner}}
workerType: b2gtest
provisionerId: aws-provisioner
schedulerId: task-graph-scheduler
scopes:
- 'docker-worker:image:{{#docker_image}}tester-device{{/docker_image}}'
- 'queue:create-task:aws-provisioner/testdroid-device'
- 'docker-worker:cache:tc-vcs'
payload:
image: '{{#docker_image}}tester-device{{/docker_image}}'
maxRunTime: 3600
cache:
tc-vcs: '/home/worker/.tc-vcs'
env:
GAIA_HEAD_REPOSITORY: '{{{gaia_head_repository}}}'
GAIA_BASE_REPOSITORY: '{{{gaia_base_repository}}}'
GAIA_REF: '{{{gaia_ref}}}'
GAIA_REV: '{{{gaia_rev}}}'
MOZHARNESS_REPOSITORY: '{{mozharness_repository}}'
MOZHARNESS_REV: '{{mozharness_rev}}'
# All builds share a common artifact directory for ease of uploading.
artifacts:
'private/logs':
type: directory
path: '/home/worker/upload/logs/'
expires: '{{#from_now}}1 year{{/from_now}}'
extra:
treeherder:
groupSymbol: tc
groupName: Submitted by taskcluster

View File

@ -0,0 +1,36 @@
---
$inherits:
from: 'tasks/phone_test.yml'
task:
metadata:
name: '[TC] Gaia Python Sanity Integration Tests'
description: Gaia Python Integration Tests
workerType: testdroid-device
retries: 0
payload:
env:
DEVICE_CAPABILITIES: '{"type":"flame","memory":"319","sims": "1","build":"{{{img_url}}}"}'
features:
testdroidProxy: true
maxRunTime: 7200
command:
- >
tc-vcs checkout /home/worker/gaia/source $GAIA_BASE_REPOSITORY $GAIA_HEAD_REPOSITORY $GAIA_REV $GAIA_REF &&
cd gaia/source/tests/python/gaia-ui-tests/ &&
python setup.py develop &&
pip install py &&
cd /home/worker/ &&
gaiatest --testvars=/home/worker/data/gaia_testvars.json --testvars=/home/worker/data/device.json --adb-host=$PROXY_HOST --adb-port=$ADB_PORT --address=$PROXY_HOST:$MARIONETTE_PORT --device $SERIAL_ID --xml-output=/home/worker/upload/logs/xml_output.xml --timeout=10000 --log-html=/home/worker/upload/logs/index.html --restart --type=b2g+sanity-dsds --log-mach=- --log-raw=/home/worker/upload/logs/raw.log gaia/source/tests/python/gaia-ui-tests/gaiatest/tests/functional/manifest.ini
artifacts:
'private/device.json':
type: file
path: '/home/worker/data/device.json'
expires: '{{#from_now}}1 year{{/from_now}}'
extra:
treeherder:
groupName: Gaia Python Integration Tests
groupSymbol: tc-Gip
symbol: 'S'
productName: b2g