Merge branch 'dev' of https://github.com/galaxyproject/galaxy into jupytool

This commit is contained in:
Daniel Blankenberg
2022-03-22 08:12:53 -04:00
4764 changed files with 332161 additions and 192088 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
exclude=$(sed -e 's|^|./|' -e 's|/$||' .ci/flake8_blacklist.txt | paste -s -d ',' - )
exclude=$(sed -e 's|^|./|' -e 's|/$||' .ci/flake8_ignorelist.txt | paste -s -d ',' - )
autopep8 -i -r --exclude $exclude --select E11,E101,E127,E201,E202,E22,E301,E302,E303,E304,E306,E711,W291,W292,W293,W391 ./lib/ ./test/
+34 -5
View File
@@ -1,16 +1,45 @@
#!/bin/sh
case "$1" in
galaxy|"")
SCRIPT=./run.sh
PORT=8080
LOGFILE=galaxy.log
GRAVITY_LOGFILE=database/gravity/log/gunicorn.log
SUPERVISORD_LOGFILE=database/gravity/supervisor/supervisord.log
;;
reports)
SCRIPT=./run_reports.sh
PORT=9001
LOGFILE=reports_webapp.log
;;
*)
echo "ERROR: Unrecognized app"
exit 1
;;
esac
TRIES=120
URL=http://localhost:8080
URL=http://localhost:$PORT
EXIT_CODE=1
i=0
echo "Testing for correct startup:"
bash run.sh --daemon && \
$SCRIPT --daemon && \
while [ "$i" -le $TRIES ]; do
curl "$URL" && EXIT_CODE=0 && break
curl --max-time 1 "$URL" && EXIT_CODE=0 && break
sleep 1
i=$((i + 1))
done
kill -9 "$(cat galaxy.pid)"
$SCRIPT --skip-wheels --stop-daemon
echo "exit code:$EXIT_CODE, showing startup log:"
cat galaxy.log
if [ -f "$LOGFILE" ]; then
cat "$LOGFILE"
elif [ ! -f "$LOGFILE" -a -f "$GRAVITY_LOGFILE" ]; then
echo "Warning: $LOGFILE does not exist, showing gravity startup log instead"
cat "$GRAVITY_LOGFILE"
elif [ ! -f "$LOGFILE" -a ! -f "$GRAVITY_LOGFILE" -a -f "$SUPERVISORD_LOGFILE" ]; then
echo "Warning: $LOGFILE and $GRAVITY_LOGFILE do not exist, showing supervisord startup log instead"
cat "$SUPERVISORD_LOGFILE"
else
echo "ERROR: No log files found!"
ls -lR database/gravity
fi
exit $EXIT_CODE
-19
View File
@@ -1,19 +0,0 @@
.git
.tox
.venv
.venv3
packages/*/.venv
packages/*/build
packages/*/dist
packages/venv
node_modules
database
doc/build
doc/source/conf.py
eggs
lib/galaxy/util/jstree.py
lib/galaxy/web/proxy/js/node_modules
static/maps
static/scripts
build
dist
+20
View File
@@ -0,0 +1,20 @@
.git
.tox
.venv
.venv3
packages/*/.venv
packages/*/build
packages/*/dist
packages/venv
node_modules
database
doc/build
doc/source/conf.py
eggs
lib/galaxy/util/jstree.py
lib/galaxy/web/proxy/js/node_modules
static/maps
static/scripts
test/functional/tools/cwl_tools/v1.?/
build
dist
+2 -2
View File
@@ -2,7 +2,7 @@
set -e
flake8 --exclude $(paste -sd, .ci/flake8_blacklist.txt) .
flake8 --exclude $(paste -sd, .ci/flake8_ignorelist.txt) .
# Apply stricter rules for the directories shared with Pulsar
flake8 --ignore=D --max-line-length=150 lib/galaxy/jobs/runners/util/
flake8 --ignore=E203,D --max-line-length=150 lib/galaxy/jobs/runners/util/
+1 -1
View File
@@ -17,5 +17,5 @@ if [ "$1" = "--include" ];
then
flake8 $args $(paste -sd' ' .ci/flake8_docstrings_include_list.txt)
else
flake8 $args --exclude $(paste -sd, .ci/flake8_blacklist.txt) .
flake8 $args --exclude $(paste -sd, .ci/flake8_ignorelist.txt) .
fi
-1
View File
@@ -1 +0,0 @@
api
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
./run_tests.sh --dockerize --db postgres --clean_pyc --skip_flakey_fails -api "$@"
-1
View File
@@ -1 +0,0 @@
framework
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
./run_tests.sh --dockerize --db postgres --clean_pyc --framework "$@"
-1
View File
@@ -1 +0,0 @@
integration
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
DOCKER_RUN_EXTRA_ARGS="--privileged" ./run_tests.sh --dockerize --db postgres --clean_pyc --integration "$@"
-1
View File
@@ -1 +0,0 @@
main-tools
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
./run_tests.sh --dockerize --db postgres --clean_pyc -main "$@"
-24
View File
@@ -1,24 +0,0 @@
FROM toolshed/requirements
LABEL maintainer="John Chilton <jmchilton@gmail.com>"
RUN apt-get -qq update && \
apt-get install --no-install-recommends -y postgresql-client python-pip libffi-dev python-cffi && \
apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
ENV GALAXY_ROOT=/galaxy \
GALAXY_CONFIG_OVERRIDE_ADMIN_USERS=admin@galaxy.org,test@bx.psu.edu \
GALAXY_CONFIG_OVERRIDE_ALLOW_USER_DATASET_PURGE=true \
GALAXY_CONFIG_OVERRIDE_ALLOW_LIBRARY_PATH_PASTE=true \
GALAXY_CONFIG_OVERRIDE_ENABLE_BETA_WORKFLOW_MODULES=true \
GALAXY_CONFIG_OVERRIDE_ALLOW_USER_DELETION=true \
GALAXY_CONFIG_OVERRIDE_DATABASE_CONNECTION=postgresql://postgres@postgres/galaxy \
GALAXY_CONFIG_OVERRIDE_MASTER_API_KEY=94a548bea347a35e457a804bf75bec53 \
GALAXY_CONFIG_OVERRIDE_JOB_CONFIG_FILE=/galaxy/config/job_conf.xml.sample_basic \
GALAXY_CONFIG_OVERRIDE_DATATYPES_CONFIG_FILE=/galaxy/test/functional/tools/sample_datatypes_conf.xml \
GALAXY_CONFIG_OVERRIDE_TOOL_CONFIG_FILE=/galaxy/test/functional/tools/samples_tool_conf.xml \
GALAXY_CONFIG_FILE=/galaxy/.ci/jenkins/selenium/galaxy.ini \
GALAXY_VIRTUAL_ENV=/galaxy_env
ADD run_galaxy.bash /run_galaxy.bash
EXPOSE 8080
CMD /run_galaxy.bash
@@ -1,21 +0,0 @@
version: '2'
services:
postgres:
image: postgres
galaxy:
build: .
image: ubuntu
volumes:
- "${TARGET_ROOT}:${TARGET_PATH}"
links:
- postgres
ports:
- "${GALAXY_PORT}:8080"
environment:
GALAXY_TEST_UID: "${MY_UID}"
selenium:
image: selenium/standalone-chrome:3.5.2
ports:
- "${SELENIUM_PORT}:4444"
links:
- galaxy
-17
View File
@@ -1,17 +0,0 @@
[server:main]
use = egg:Paste#http
port = 8080
host = 0.0.0.0
use_threadpool = True
threadpool_kill_thread_limit = 10800
[filter:proxy-prefix]
use = egg:PasteDeploy#prefix
prefix = /galaxypf
[app:main]
paste.app_factory = galaxy.web.buildapp:app_factory
filter-with = proxy-prefix
@@ -1,39 +0,0 @@
#!/bin/bash
set -e
# Same hacks to setup a Galaxy user as used in test/docker/base/run_test_wrapper.sh
# We want to make sure Galaxy runs as the same user as the external user so the files have the correct permission.
echo "Deleting galaxy user - it may not exist and this is fine."
deluser galaxy | true
: ${GALAXY_TEST_UID:-"1"}
echo "Creating galaxy group with gid $GALAXY_TEST_UID - it may already exist and this is fine."
groupadd -r galaxy -g "$GALAXY_TEST_UID" | true
echo "Creating galaxy user with uid $GALAXY_TEST_UID - it may already exist and this is fine."
useradd -u $GALAXY_TEST_UID -r -g galaxy -d /home/galaxy -c "Galaxy User" galaxy -s /bin/bash | true
echo "Setting galaxy user password - the operation may fail."
echo "galaxy:galaxy" | chpasswd | true
virtualenv "$GALAXY_VIRTUAL_ENV"
chown -R "$GALAXY_TEST_UID:$GALAXY_TEST_UID" "$GALAXY_VIRTUAL_ENV"
cd /galaxy
sudo -E -H -u "#${GALAXY_TEST_UID}" ./scripts/common_startup.sh || { echo "common_startup.sh failed"; exit 1; }
echo "Waiting for postgres to become available"
while ! nc -z postgres 5432;
do
sleep 1
printf "."
done
echo "Creating postgres database for Galaxy"
createdb -w -U postgres -h postgres galaxy
echo "Starting and waiting for Galaxy daemon(s)"
sudo -E -H -u "#${GALAXY_TEST_UID}" GALAXY_RUN_ALL=1 bash "$GALAXY_ROOT/run.sh" --daemon --wait
echo "Galaxy daemon ready, monitoring Galaxy logs"
tail -f "$GALAXY_ROOT/main.log"
-124
View File
@@ -1,124 +0,0 @@
#!/bin/bash
TEST_DIRECTORY=`dirname $0`
DEFAULT_COMPOSE_PROJECT_NAME=`basename $TEST_DIRECTORY`
COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-$DEFAULT_COMPOSE_PROJECT_NAME}
# If in Jenkins environment, append ${BUILD_NUMBER} to project so builds don't interfer.
if [ ! -z "$BUILD_NUMBER" ];
then
COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME}${BUILD_NUMBER}"
fi
export COMPOSE_PROJECT_NAME
echo "Running Jenkins test from $TEST_DIRECTORY with compose project name $COMPOSE_PROJECT_NAME"
find lib -iname '*pyc' -exec rm -rf {} \;
find test -iname '*pyc' -exec rm -rf {} \;
./scripts/common_startup.sh --dev-wheels
. .venv/bin/activate
pip install docker-compose
# TODO: Let docker-compose pick these at random.
export GALAXY_PORT=`python -c 'from __future__ import print_function; import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'`
export SELENIUM_PORT=`python -c 'from __future__ import print_function; import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'`
export TARGET_ROOT=`pwd`
export TARGET_PATH=/galaxy
export MY_UID=$(id -u)
cd $TEST_DIRECTORY
echo "Cleaning up previous executions if needed."
docker-compose down | true
docker-compose build galaxy
docker-compose up -d
function tear_down {
docker-compose down
}
trap tear_down EXIT
for service_name in postgres galaxy selenium
do
echo "Waiting on service ${service_name}"
while true
do
if docker ps | grep -q "${COMPOSE_PROJECT_NAME}_${service_name}"
then
container_id=`docker ps | grep "${COMPOSE_PROJECT_NAME}_${service_name}" | cut -d " " -f 1`
eval "${service_name}_container_id=${container_id}"
echo "Service ${service_name} ready - with container ID ${container_id}"
break
fi
printf "."
sleep 1;
done
done
if [ "$1" = "--debug-running-containers" ];
then
env
exit 0
fi
export GALAXY_TEST_EXTERNAL="http://localhost:$GALAXY_PORT/"
echo "Waiting on docker-compose managed Galaxy server - $GALAXY_TEST_EXTERNAL."
while ! curl -s "$GALAXY_TEST_EXTERNAL";
do
for service_name in postgres galaxy selenium
do
if ! docker ps | grep -q "${COMPOSE_PROJECT_NAME}_${service_name}"
then
echo "Service ${service_name} stopped before Galaxy came up, exiting and halting containers."
for service_name in postgres galaxy selenium
do
container_id_var="${service_name}_container_id"
container_id="${!container_id_var}"
echo "Dumping logs for $service_name container (${container_id})..."
echo "---"
docker logs "${container_id}"
echo "---"
done
exit 1
fi
done
printf "."
sleep 4;
done;
# Access Selenium on localhost via port $SELENIUM_PORT
export GALAXY_TEST_SELENIUM_REMOTE=1
export GALAXY_TEST_SELENIUM_REMOTE_PORT="${SELENIUM_PORT}"
# Retry all failed Selenium tests a second time to deal
# with transiently failing tests. Failure information for
# first tests is still populated in database/test_errors
# and available at the top of the Jenkins test report.
export GALAXY_TEST_SELENIUM_RETRIES=1
# Access Galaxy on localhost via port $GALAXY_PORT
export GALAXY_TEST_PORT="${GALAXY_PORT}"
# Have Selenium access Galaxy at this URL
export GALAXY_TEST_EXTERNAL_FROM_SELENIUM="http://galaxy:8080/galaxypf"
export GALAXY_TEST_EXTERNAL="http://localhost:${GALAXY_TEST_PORT}/galaxypf"
# Point tests at the Master API Key configured in the Dockerfile.
export GALAXY_CONFIG_MASTER_API_KEY=94a548bea347a35e457a804bf75bec53
cd ../../..
./run_tests.sh --selenium "$@"
exit_code=$?
cd $TEST_DIRECTORY
exit $exit_code
-1
View File
@@ -1 +0,0 @@
selenium
-26
View File
@@ -1,26 +0,0 @@
#!/bin/bash
# Enable retries on tests to reduce chances of transient failures.
: ${GALAXY_TEST_SELENIUM_RETRIES:=1}
# If in Jenkins environment, use it for artifacts.
if [ -n "$BUILD_NUMBER" ];
then
: ${GALAXY_TEST_ERRORS_DIRECTORY:=${BUILD_NUMBER}-test-errors}
: ${GALAXY_TEST_SCREENSHOTS_DIRECTORY:=${BUILD_NUMBER}-test-screenshots}
else
: ${GALAXY_TEST_ERRORS_DIRECTORY:=database/test-errors}
: ${GALAXY_TEST_SCREENSHOTS_DIRECTORY:=database/test-screenshots}
fi
mkdir -p "$GALAXY_TEST_ERRORS_DIRECTORY"
mkdir -p "$GALAXY_TEST_SCREENSHOTS_DIRECTORY"
mkdir -p ~/.jenkins-yarn-cache
YARN_CACHE_FOLDER=~/.jenkins-yarn-cache
# Start Selenium server in the test Docker container.
DOCKER_RUN_EXTRA_ARGS="${DOCKER_RUN_EXTRA_ARGS} --shm-size=2g -v $YARN_CACHE_FOLDER:$YARN_CACHE_FOLDER -e YARN_CACHE_FOLDER=$YARN_CACHE_FOLDER -e USE_SELENIUM=1 -e GALAXY_TEST_SELENIUM_RETRIES=${GALAXY_TEST_SELENIUM_RETRIES} -e GALAXY_TEST_ERRORS_DIRECTORY=${GALAXY_TEST_ERRORS_DIRECTORY} -e GALAXY_TEST_SCREENSHOTS_DIRECTORY=${GALAXY_TEST_SCREENSHOTS_DIRECTORY}"
export DOCKER_RUN_EXTRA_ARGS
./run_tests.sh --dockerize --db postgres --clean_pyc --skip_flakey_fails --selenium "$@"
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
./run_tests.sh --dockerize --db postgres --clean_pyc --toolshed "$@"
+32
View File
@@ -0,0 +1,32 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: testing
name: testing
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: test
template:
metadata:
labels:
app.kubernetes.io/name: test
spec:
containers:
- image: postgres:12
name: postgres
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: postgres
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
value: postgres
- image: rabbitmq
name: rabbitmq
ports:
- containerPort: 5672
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -ex
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
kubectl apply -f "$SCRIPTDIR/deployment.yaml"
kubectl expose deployment testing --type=LoadBalancer --name=testing-service
CLUSTER_IP=$(kubectl get service testing-service -o jsonpath='{.spec.clusterIP}')
GALAXY_TEST_DBURI="postgresql://postgres:postgres@${CLUSTER_IP}:5432/galaxy?client_encoding=utf-8"
GALAXY_TEST_AMQP_URL="amqp://${CLUSTER_IP}:5672//"
export GALAXY_TEST_DBURI
export GALAXY_TEST_AMQP_URL
+7 -63
View File
@@ -17,6 +17,8 @@ variables:
- ~/.cache/yarn
install_tox: &install_tox
run: sudo pip install tox
install_deb_reqs: &install_deb_reqs
run: sudo apt-get update && sudo apt-get install ffmpeg nodejs -y
set_workdir: &set_workdir
working_directory: ~/repo
requires_get_code: &requires_get_code
@@ -25,7 +27,7 @@ variables:
jobs:
get_code:
docker:
- image: circleci/python:3.5
- image: circleci/python:3.7
<<: *set_workdir
steps:
# Replace standard code checkout with shallow clone to speed things up.
@@ -81,44 +83,9 @@ jobs:
key: v1-repo-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo
py35_docstring:
docker:
- image: circleci/python:3.5
<<: *set_workdir
steps:
- *restore_repo_cache
- *install_tox
- run: tox -e py35-lint_docstring_include_list
py35_lint:
docker:
- image: circleci/python:3.5
<<: *set_workdir
steps:
- *restore_repo_cache
- *install_tox
- run: tox -e py35-lint
py35_unit:
docker:
- image: circleci/python:3.5
<<: *set_workdir
steps:
- *restore_repo_cache
- *install_tox
- run: tox -e py35-unit
py35_first_startup:
docker:
- image: circleci/python:3.5
<<: *set_workdir
steps:
- *restore_repo_cache
# Use this job to test the latest migrations
- run: wget -q https://github.com/jmchilton/galaxy-downloads/raw/master/db_gx_rev_0141.sqlite
- run: mv db_gx_rev_0141.sqlite database/universe.sqlite
- *install_tox
- run: tox -e py35-first_startup
validate_test_tools:
docker:
- image: circleci/python:3.5
- image: circleci/python:3.7
<<: *set_workdir
steps:
- *restore_repo_cache
@@ -128,29 +95,16 @@ jobs:
- run: tox -e validate_test_tools
test_galaxy_packages:
docker:
- image: circleci/python:3.5
- image: circleci/python:3.7
<<: *set_workdir
steps:
- *restore_repo_cache
- *install_tox
- *install_deb_reqs
- run: tox -e test_galaxy_packages
js_unit:
docker:
- image: circleci/node:12-browsers
<<: *set_workdir
steps:
- *restore_yarn_cache
- run: cd client && yarn install --frozen-lockfile
- *save_yarn_cache
- run:
name: Build client
command: cd client && yarn run build
environment:
NODE_OPTIONS: --max_old_space_size=4096
- run: cd client && yarn run test
js_lint:
docker:
- image: circleci/node:12-browsers
- image: cimg/node:16.13.2
<<: *set_workdir
steps:
- *restore_yarn_cache
@@ -163,19 +117,9 @@ workflows:
get_code_and_test:
jobs:
- get_code
- py35_docstring:
<<: *requires_get_code
- py35_lint:
<<: *requires_get_code
- py35_unit:
<<: *requires_get_code
- py35_first_startup:
<<: *requires_get_code
- test_galaxy_packages:
<<: *requires_get_code
- validate_test_tools:
<<: *requires_get_code
- js_unit:
<<: *requires_get_code
- js_lint:
<<: *requires_get_code
+4
View File
@@ -0,0 +1,4 @@
.k8s_ci.Dockerfile
.venv
database
node_modules
+7
View File
@@ -0,0 +1,7 @@
# Migrate code style to Black and Apply isort
623a5e165ad79e15321b19b2a2afbf2f9224cc90
# Application of black styling to /tools/
03351d2a9f81b938d650e2a955c65c18526ee7f0
# Migrate code style to Prettier
5b2928f851bd5ea3b9c2a04abf2cee9ff0bc54cc
87873c5e2f4e6b97fe0f2084bfca0295fcd471de
+31
View File
@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Galaxy Version and/or server at which you observed the bug**
Galaxy Version: (check <galaxy_url>/api/version if you don't know)
Commit: (run `git rev-parse HEAD` if you run this Galaxy server)
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.
+1
View File
@@ -0,0 +1 @@
comment: false
+68
View File
@@ -0,0 +1,68 @@
---
area/admin:
- client/src/components/admin/**/*
- doc/source/admin/**/*
area/API:
- lib/galaxy/webapps/galaxy/api/**/*
area/client:
- client/*
area/datatypes:
- lib/galaxy/datatypes/**/*
- lib/galaxy/config/sample/datatypes_conf.xml.sample
area/dependencies:
- lib/galaxy/dependencies/**/*
area/documentation:
- doc/**/*
area/jobs:
- lib/galaxy/jobs/**/*
area/libraries:
- client/src/components/LibraryFolder/**/*
- lib/galaxy/webapps/galaxy/api/libraries.py
area/objectstore:
- lib/galaxy/objectstore/**/*
area/packaging:
- packages/**/*
area/reports:
- client/src/reports/**/*
- lib/galaxy/webapps/reports/**/*
- templates/webapps/reports/**/*
area/scripts:
- scripts/**/*
area/security:
- lib/galaxy/security/**/*
area/testing:
- lib/galaxy_test/**/*
- run_tests.sh
- test/**/*
- test-data/**/*
area/testing/api:
- lib/galaxy_test/api/**/*
area/testing/integration:
- test/integration/**/*
- test/integration_selenium/**/*
area/testing/selenium:
- lib/galaxy/selenium/**/*
- lib/galaxy_test/selenium/**/*
area/tool-dependencies:
- lib/galaxy/tool_util/deps/**/*
area/tool-framework:
- lib/galaxy/tools/**/*
- lib/galaxy/tool_util/**/*
- lib/galaxy/webapps/galaxy/api/tools.py
area/tools:
- tools/**/*
- tool-data/**/*
area/toolshed:
- client/src/toolshed/**/*
- lib/galaxy/webapps/galaxy/api/toolshed.py
- lib/toolshed/**/*
- templates/webapps/tool_shed/**/*
area/UI-UX:
- client/src/**/*
- templates/**/*
area/util:
- lib/galaxy/util/**/*
area/visualizations:
- config/plugins/visualizations/**/*
area/workflows:
- lib/galaxy/workflow/**/*
+14
View File
@@ -0,0 +1,14 @@
(Please replace this header with a description of your pull request. Please include *BOTH* what you did and why you made the changes. The "why" may simply be citing a relevant Galaxy issue.)
(If fixing a bug, please add any relevant error or traceback)
(For UI components, it is recommended to include screenshots or screencasts)
## How to test the changes?
(Select all options that apply)
- [ ] I've included appropriate [automated tests](https://docs.galaxyproject.org/en/latest/dev/writing_tests.html).
- [ ] This is a refactoring of components with existing test coverage.
- [ ] Instructions for manual testing are as follows:
1. [add testing steps and prerequisites here if you didn't write automated tests covering all your changes]
## License
- [x] I agree to license these contributions under [Galaxy's current license](https://github.com/galaxyproject/galaxy/blob/dev/LICENSE.txt).
- [x] I agree to allow the Galaxy committers to license these and all my past contributions to the core galaxy codebase under the [MIT license](https://opensource.org/licenses/MIT). If this condition is an issue, uncheck and just let us know why with an e-mail to galaxy-committers@lists.galaxyproject.org.
+76
View File
@@ -0,0 +1,76 @@
name: API tests
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
schedule:
# Run at midnight UTC every Tuesday
- cron: '0 0 * * 2'
env:
GALAXY_DEPENDENCIES_INSTALL_WEASYPRINT: '1'
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
GALAXY_CONFIG_SQLALCHEMY_WARN_20: '1'
concurrency:
group: api-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7']
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- if: github.event_name == 'schedule'
run: |
echo "GALAXY_CONFIG_OVERRIDE_METADATA_STRATEGY=extended" >> $GITHUB_ENV
echo "GALAXY_CONFIG_OVERRIDE_OUTPUTS_TO_WORKING_DIRECTORY=true" >> $GITHUB_ENV
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-api
- name: Run tests
run: ./run_tests.sh --coverage --skip_flakey_fails -api
working-directory: 'galaxy root'
- uses: codecov/codecov-action@v2
with:
flags: api
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: API test results (${{ matrix.python-version }})
path: 'galaxy root/run_api_tests.html'
@@ -0,0 +1,50 @@
name: Build Container Image
on:
push:
branches:
- 'release*'
- dev
concurrency:
group: docker-build-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Build container image
runs-on: ubuntu-latest
if: github.repository_owner == 'galaxyproject'
steps:
- uses: actions/checkout@v2
# https://stackoverflow.com/questions/59810838/how-to-get-the-short-sha-for-the-github-workflow
- name: Set outputs
id: commit
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: Set branch name
id: branch
run: echo "::set-output name=name::$(BRANCH_NAME=${GITHUB_REF##*/}; echo ${BRANCH_NAME/release_/})"
- name: Build container image
run: docker build . --build-arg GIT_COMMIT=$(git rev-parse HEAD) --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg IMAGE_TAG=${{ steps.branch.outputs.name }} -t galaxyproject/galaxy-min:${{ steps.branch.outputs.name }} -t quay.io/galaxyproject/galaxy-min:${{ steps.branch.outputs.name }} -f .k8s_ci.Dockerfile
- name: Create auto-expiring one for per-commit auto repository
run: echo "FROM galaxyproject/galaxy-min:${{ steps.branch.outputs.name }}" | docker build --label "quay.expires-after"="90d" -t "quay.io/galaxyproject/galaxy-k8s-auto:${{ steps.commit.outputs.sha_short }}" -
- name: Login to quay.io
uses: actions-hub/docker/login@master
env:
DOCKER_USERNAME: ${{ secrets.QUAY_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.QUAY_PASSWORD }}
DOCKER_REGISTRY_URL: quay.io
- name: Push to quay.io with branch name
uses: actions-hub/docker@master
with:
args: push quay.io/galaxyproject/galaxy-min:${{ steps.branch.outputs.name }}
- name: Push to quay.io with commit hash
uses: actions-hub/docker@master
with:
args: push quay.io/galaxyproject/galaxy-k8s-auto:${{ steps.commit.outputs.sha_short }}
- name: Login to DockerHub
uses: actions-hub/docker/login@master
env:
DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Push to DockerHub with branch name
uses: actions-hub/docker@master
with:
args: push galaxyproject/galaxy-min:${{ steps.branch.outputs.name }}
+70
View File
@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ dev ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ dev ]
schedule:
- cron: '16 6 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript', 'python']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+56 -5
View File
@@ -1,14 +1,33 @@
name: Converter tests
on: [push, pull_request]
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
schedule:
# Run at midnight UTC every Tuesday
- cron: '0 0 * * 2'
env:
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
concurrency:
group: converter-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7]
python-version: ['3.7']
steps:
- if: github.event_name == 'schedule'
run: |
echo "GALAXY_CONFIG_OVERRIDE_METADATA_STRATEGY=extended" >> $GITHUB_ENV
echo "GALAXY_CONFIG_OVERRIDE_OUTPUTS_TO_WORKING_DIRECTORY=true" >> $GITHUB_ENV
- uses: actions/checkout@v2
with:
path: 'galaxy root'
@@ -30,5 +49,37 @@ jobs:
run: rsync -av --remove-source-files --exclude .git galaxy-test-data/ 'galaxy root/test-data/'
- name: Install planemo
run: pip install planemo
- name: Install jq
run: sudo apt-get install jq
- name: Determine converters to check
run: |
ls 'galaxy root'/lib/galaxy/datatypes/converters/*xml | grep -v -f 'galaxy root'/lib/galaxy/datatypes/converters/.tt_skip > tool_list.txt
echo "Skipping checks for the following converters:"
ls 'galaxy root'/lib/galaxy/datatypes/converters/*xml | grep -f 'galaxy root'/lib/galaxy/datatypes/converters/.tt_skip
echo "Checking only the following converters:"
cat tool_list.txt
- name: Lint converters
run: |
mapfile -t TOOL_ARRAY < tool_list.txt
for CONVERTER in "${TOOL_ARRAY[@]}"; do
planemo lint --skip citations,stdio,help --report_level warn "$CONVERTER"
done
- name: Run tests
run: planemo test --galaxy_python_version ${{ matrix.python-version }} --galaxy_root 'galaxy root' 'galaxy root'/lib/galaxy/datatypes/converters/*xml
run: |
mkdir -p json_output
mapfile -t TOOL_ARRAY < tool_list.txt
for CONVERTER in "${TOOL_ARRAY[@]}"; do
json=$(mktemp -u -p json_output --suff .json)
planemo test --test_output_json "$json" --galaxy_python_version ${{ matrix.python-version }} --galaxy_root 'galaxy root' "$CONVERTER" || true
done
planemo merge_test_reports json_output/*.json tool_test_output.json
planemo test_reports tool_test_output.json --test_output tool_test_output.html
if jq '.["tests"][]["data"]["status"]' tool_test_output.json | grep -v "success"; then
echo "Unsuccessful tests found, inspect the 'Converter test results' artifact for details."
exit 1
fi
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Converter test results (${{ matrix.python-version }})
path: tool_test_output.html
+69
View File
@@ -0,0 +1,69 @@
name: CWL conformance
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
env:
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
concurrency:
group: cwl-conformance-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
if: ${{ false }}
runs-on: ubuntu-latest
continue-on-error: ${{ startsWith(matrix.marker, 'red') }}
strategy:
fail-fast: false
matrix:
python-version: ['3.7']
marker: ['green', 'red and required', 'red and not required']
conformance-version: ['cwl_conformance_v1_0'] #, 'cwl_conformance_v1_1', 'cwl_conformance_v1_2']
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Run tests
run: ./run_tests.sh --coverage --skip_flakey_fails -cwl lib/galaxy_test/api/cwl -- -m "${{ matrix.marker }} and ${{ matrix.conformance-version }}"
working-directory: 'galaxy root'
- uses: codecov/codecov-action@v2
with:
flags: cwl-conformance
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: CWL conformance test results (${{ matrix.python-version }}, ${{ matrix.marker }}, ${{ matrix.conformance-version }})
path: 'galaxy root/run_cwl_tests.html'
+71
View File
@@ -0,0 +1,71 @@
name: Database indexes
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
concurrency:
group: database-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
working-directory: 'galaxy root'
jobs:
check:
name: Check database indexes
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7']
db: ['postgresql', 'sqlite']
postgresql-version: ['13']
include:
- db: postgresql
postgresql-version: '9.6'
services:
postgres:
image: postgres:${{ matrix.postgresql-version }}
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache tox env
uses: actions/cache@v2
with:
path: .tox
key: tox-cache-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-check-indexes
- name: Install tox
run: pip install tox
- name: Check indexes on postgresql
if: matrix.db == 'postgresql'
env:
GALAXY_CONFIG_OVERRIDE_DATABASE_CONNECTION: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
run: tox -e check_indexes
- name: Check indexes on sqlite
if: matrix.db == 'sqlite'
run: tox -e check_indexes
+38
View File
@@ -0,0 +1,38 @@
name: Update dependencies
on:
schedule:
- cron: '0 3 * * 6' # Run every saturday at 3 am.
jobs:
update_dependencies:
name: Update dependencies
if: github.repository_owner == 'galaxyproject'
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7']
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }}
- name: Update dependencies
run: |
python -m venv .venv
make update-dependencies
- name: Create pull request
uses: peter-evans/create-pull-request@v3
with:
author: galaxybot <galaxybot@users.noreply.github.com>
token: ${{ secrets.GALAXYBOT_PAT }}
commit-message: Update Python dependencies
branch: dev_auto_update_dependencies
delete-branch: true
push-to-fork: galaxybot/galaxy
title: Update Python dependencies
body: Run `make update-dependencies`.
labels: area/dependencies
+77
View File
@@ -0,0 +1,77 @@
name: Build docs
on:
push:
paths-ignore:
- 'client/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'lib/galaxy_test/selenium/**'
concurrency:
group: docs-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7']
steps:
- name: Get target branch name (push)
if: github.event_name == 'push'
run: echo "TARGET_BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV
- name: Get target branch name (pull request)
if: github.event_name == 'pull_request'
run: echo "TARGET_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV
- name: Show target branch name
run: echo $TARGET_BRANCH
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }}
- name: Install Python dependencies
run: pip install -r requirements.txt -r lib/galaxy/dependencies/dev-requirements.txt sphinxcontrib-simpleversioning
- name: Add Google Analytics to doc/source/conf.py
run: |
sed -i -e "/html_theme_options = {/a\
\ 'analytics_id': 'UA-45719423-17'," -e "s#https://docs.galaxyproject.org/en/[^/]*/#https://docs.galaxyproject.org/en/$TARGET_BRANCH/#" doc/source/conf.py
- name: Checkout the latest doc/source/conf.versioning.py
if: github.event_name != 'push' || github.ref != 'refs/heads/dev'
run: |
# We cannot just download the latest version from dev, because it may be newer in this branch/PR
git fetch origin dev:dev
if [ ! -f doc/source/conf.versioning.py ] || [ "$(git log -1 --pretty="format:%ct" dev -- doc/source/conf.versioning.py)" -gt "$(git log -1 --pretty="format:%ct" -- doc/source/conf.versioning.py)" ]; then
git checkout dev -- doc/source/conf.versioning.py
fi
- name: Append doc/source/conf.versioning.py
run: cat doc/source/conf.versioning.py >> doc/source/conf.py
- name: Build docs
run: make docs
- name: Deploy docs
if: github.event_name == 'push' && github.repository_owner == 'galaxyproject'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
case "$TARGET_BRANCH" in
release_[[:digit:]][[:digit:]].[[:digit:]][[:digit:]]|master)
UPLOAD_DIR=$TARGET_BRANCH
;;
dev)
UPLOAD_DIR=latest
;;
*)
echo "Not deploying documentation for branch $TARGET_BRANCH"
exit 0
;;
esac
pip install awscli
aws s3 sync doc/build/html/ "s3://galaxy-docs/en/$UPLOAD_DIR" --region us-east-2 --size-only --delete
+58
View File
@@ -0,0 +1,58 @@
name: first startup
on:
push:
paths-ignore:
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
env:
YARN_INSTALL_OPTS: --frozen-lockfile
concurrency:
group: first-startup-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Startup test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.7', '3.10']
defaults:
run:
shell: bash -l {0}
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache tox env
uses: actions/cache@v2
with:
path: .tox
key: tox-cache-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-first-startup
- uses: mvdbeek/gha-yarn-cache@master
with:
yarn-lock-file: 'galaxy root/client/yarn.lock'
- name: Install tox
run: pip install tox
- name: run tests
run: tox -e first_startup
working-directory: 'galaxy root'
+74
View File
@@ -0,0 +1,74 @@
name: Framework tests
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
schedule:
# Run at midnight UTC every Tuesday
- cron: '0 0 * * 2'
env:
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
concurrency:
group: framework-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7']
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- if: github.event_name == 'schedule'
run: |
echo "GALAXY_CONFIG_OVERRIDE_METADATA_STRATEGY=extended" >> $GITHUB_ENV
echo "GALAXY_CONFIG_OVERRIDE_OUTPUTS_TO_WORKING_DIRECTORY=true" >> $GITHUB_ENV
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-framework
- name: Run tests
run: ./run_tests.sh --coverage --framework
working-directory: 'galaxy root'
- uses: codecov/codecov-action@v2
with:
flags: framework
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Framework test results (${{ matrix.python-version }})
path: 'galaxy root/run_framework_tests.html'
+81 -39
View File
@@ -1,19 +1,38 @@
name: Integration
on: [push, pull_request]
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
schedule:
# Run at midnight UTC every Tuesday
- cron: '0 0 * * 2'
env:
GALAXY_TEST_DBURI: 'postgres://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
GALAXY_TEST_AMQP_URL: 'amqp://localhost:5672//'
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
GALAXY_CONFIG_SQLALCHEMY_WARN_20: '1'
concurrency:
group: integration-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.7]
subset: ['upload_datatype', 'extended_metadata', 'kubernetes', 'not (upload_datatype or extended_metadata or kubernetes)']
python-version: ['3.7']
chunk: ['0', '1', '2', '3']
services:
postgres:
image: postgres:11
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
@@ -25,36 +44,59 @@ jobs:
ports:
- 5672:5672
steps:
- name: Prune unused docker image, volumes and containers
run: docker system prune -a -f
- name: Clean dotnet folder for space
if: matrix.subset == 'kubernetes'
run: rm -Rf /usr/share/dotnet
- name: Setup Minikube
if: matrix.subset == 'kubernetes'
id: minikube
uses: CodingNagger/minikube-setup-action@v1.0.3
with:
minikube-version: "1.9.0-0_amd64"
- name: Launch Minikube
if: matrix.subset == 'kubernetes'
run: eval ${{ steps.minikube.outputs.launcher }}
- name: Check pods
if: matrix.subset == 'kubernetes'
run: |
kubectl get pods
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Run tests
run: './run_tests.sh -integration test/integration -- -k "${{ matrix.subset }}"'
working-directory: 'galaxy root'
- if: github.event_name == 'schedule'
run: |
echo "GALAXY_CONFIG_OVERRIDE_METADATA_STRATEGY=extended" >> $GITHUB_ENV
# Skip outputs_to_working_directory: true in integration tests, doesn't work with pulsar
# echo "GALAXY_CONFIG_OVERRIDE_OUTPUTS_TO_WORKING_DIRECTORY=true" >> $GITHUB_ENV
- name: Prune unused docker image, volumes and containers
run: docker system prune -a -f
- name: Clean dotnet folder for space
run: rm -Rf /usr/share/dotnet
- name: Setup Minikube
id: minikube
uses: CodingNagger/minikube-setup-action@v1.0.3
with:
minikube-version: "1.9.0-0_amd64"
- name: Launch Minikube
run: eval ${{ steps.minikube.outputs.launcher }}
- name: Check pods
run: |
kubectl get pods
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-integration
- name: Install ffmpeg
run: sudo apt-get update && sudo apt-get -y install ffmpeg
- name: Run tests
run: |
. .ci/minikube-test-setup/start_services.sh
./run_tests.sh --coverage -integration test/integration -- --num-shards=4 --shard-id=${{ matrix.chunk }}
working-directory: 'galaxy root'
- uses: codecov/codecov-action@v2
with:
flags: integration
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Integration test results (${{ matrix.python-version }}, ${{ matrix.chunk }})
path: 'galaxy root/run_integration_tests.html'
+69 -28
View File
@@ -1,45 +1,86 @@
name: Integration Selenium
on: [push, pull_request]
on:
push:
paths-ignore:
- 'doc/**'
pull_request:
paths-ignore:
- 'doc/**'
schedule:
# Run at midnight UTC every Tuesday
- cron: '0 0 * * 2'
env:
GALAXY_TEST_DBURI: 'postgres://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
GALAXY_TEST_SELENIUM_REMOTE: '1'
GALAXY_TEST_SELENIUM_REMOTE_PORT: "4444"
GALAXY_SKIP_CLIENT_BUILD: '0'
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
GALAXY_TEST_SELENIUM_RETRIES: 1
YARN_INSTALL_OPTS: --frozen-lockfile
GALAXY_CONFIG_SQLALCHEMY_WARN_20: '1'
GALAXY_DEPENDENCIES_INSTALL_WEASYPRINT: '1'
concurrency:
group: integration-selenium-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7]
python-version: ['3.7']
services:
postgres:
image: postgres:11
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
selenium:
image: selenium/standalone-chrome:3.141.59
ports:
- 4444:4444
steps:
- name: Prune unused docker image, volumes and containers
run: docker system prune -a -f
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Run tests
run: './run_tests.sh -integration test/integration_selenium'
working-directory: 'galaxy root'
- if: github.event_name == 'schedule'
run: |
echo "GALAXY_CONFIG_OVERRIDE_METADATA_STRATEGY=extended" >> $GITHUB_ENV
echo "GALAXY_CONFIG_OVERRIDE_OUTPUTS_TO_WORKING_DIRECTORY=true" >> $GITHUB_ENV
- name: Prune unused docker image, volumes and containers
run: docker system prune -a -f
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-integration-selenium
- uses: mvdbeek/gha-yarn-cache@master
with:
yarn-lock-file: 'galaxy root/client/yarn.lock'
- uses: nanasess/setup-chromedriver@master
- name: Run tests
run: ./run_tests.sh --coverage -integration test/integration_selenium
working-directory: 'galaxy root'
- uses: codecov/codecov-action@v2
with:
flags: integration-selenium
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Integration Selenium test results (${{ matrix.python-version }})
path: 'galaxy root/run_integration_tests.html'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Integration Selenium debug info (${{ matrix.python-version }})
path: 'galaxy root/database/test_errors'
+37
View File
@@ -0,0 +1,37 @@
name: Client Unit Testing
on:
push:
paths:
- 'client/**'
- '.github/workflows/jest.yaml'
pull_request:
paths:
- 'client/**'
- '.github/workflows/jest.yaml'
concurrency:
group: client-${{ github.ref }}
cancel-in-progress: true
jobs:
client-unit-test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [16]
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node}}
cache: 'yarn'
cache-dependency-path: 'client/yarn.lock'
- run: yarn install --frozen-lockfile
working-directory: client
- name: Stage client libs (Gulp)
run: yarn run gulp client
working-directory: client
- name: Run Unit Tests
run: yarn run qunit
working-directory: client
- run: yarn jest
working-directory: client
+25
View File
@@ -0,0 +1,25 @@
name: Labels Verifier
on:
pull_request_target:
types: [closed]
jobs:
onMerged:
name: "Check Labels on merge"
runs-on: ubuntu-latest
steps:
- name: Check Labels on merge
if: |
github.event.pull_request.merged == true &&
! contains(join(github.event.pull_request.labels.*.name, ', '), 'kind/') &&
! contains(github.event.pull_request.labels.*.name, 'merge') &&
! contains(github.event.pull_request.labels.*.name, 'minor')
uses: actions/github-script@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: 'This PR was merged without a "kind/" label, please correct.',
})
+47
View File
@@ -0,0 +1,47 @@
name: Python linting
on:
push:
paths:
- '**.py'
pull_request:
paths:
- '**.py'
concurrency:
group: py-lint-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.10']
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('lib/galaxy/dependencies/pinned-lint-requirements.txt') }}
- name: Cache tox env
uses: actions/cache@v2
with:
path: .tox
key: tox-cache-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('lib/galaxy/dependencies/pinned-lint-requirements.txt') }}-lint
- name: Install tox
run: pip install tox
- name: Run linting
run: tox -e lint
- name: Run docstring linting
run: tox -e lint_docstring_include_list
- name: Run mypy checks
run: tox -e mypy
- uses: psf/black@stable
- uses: jamescurtin/isort-action@master
+47
View File
@@ -0,0 +1,47 @@
name: Maintenance Bot
on:
pull_request_target:
types: [opened, reopened, edited, ready_for_review, unlabeled]
jobs:
labeler:
name: Assign labels and milestone
if: github.repository_owner == 'galaxyproject'
runs-on: ubuntu-latest
env:
MILESTONE_NUMBER: 22
steps:
- name: Get latest pull request labels
id: get_pr_labels
uses: actions/github-script@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const response = await github.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
console.log(response);
return response.data;
- name: Add area labels
if: ${{ ! contains(join(fromJSON(steps.get_pr_labels.outputs.result).*.name, ', '), 'area/') }}
uses: actions/labeler@main
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Assign milestone
if: |
! github.event.pull_request.milestone &&
! contains(github.event.pull_request.labels.*.name, 'merge') &&
! contains(github.event.pull_request.labels.*.name, 'status/WIP') &&
! contains(github.event.pull_request.title, 'WIP') &&
! github.event.pull_request.draft
uses: actions/github-script@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
milestone: ${{ env.MILESTONE_NUMBER }},
});
+47 -21
View File
@@ -1,28 +1,54 @@
name: Mulled Unit Tests
on: [push, pull_request]
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
concurrency:
group: mulled-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7]
python-version: ['3.7']
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Install tox
run: pip install tox
- name: run tests
run: tox -e mulled
working-directory: 'galaxy root'
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache tox env
uses: actions/cache@v2
with:
path: .tox
key: tox-cache-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-mulled
- name: Install tox
run: pip install tox
- name: run tests
run: tox -e mulled
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Mulled unit test results (${{ matrix.python-version }})
path: 'galaxy root/run_unit_tests.html'
+30 -9
View File
@@ -1,28 +1,49 @@
name: OSX
on: [push, pull_request]
name: macOS startup
on:
push:
paths-ignore:
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
concurrency:
group: osx-first-startup-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Startup test
runs-on: macos-latest
defaults:
run:
shell: bash -l {0}
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/Library/Caches/pip
# scripts/common_startup.sh creates a conda env for Galaxy containing Python 3.6
key: pip-cache-3.6-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Install tox
run: pip install tox
# scripts/common_startup.sh creates a conda env for Galaxy containing Python 3.7
key: pip-cache-3.7-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache tox env
uses: actions/cache@v2
with:
path: .tox
key: tox-cache-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-osx
- name: Install and activate miniconda # use this job to test using Python from a conda environment
uses: goanpeca/setup-miniconda@v1
uses: conda-incubator/setup-miniconda@v2
with:
activate-environment: ''
- name: Install tox
run: pip install tox
- name: run tests
run: tox -e first_startup
shell: bash -l {0} # need this to have CONDA_EXE set
working-directory: 'galaxy root'
+73
View File
@@ -0,0 +1,73 @@
name: Performance tests
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
schedule:
# Run at midnight UTC every Tuesday
- cron: '0 0 * * 2'
env:
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
concurrency:
group: performance-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7']
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- if: github.event_name == 'schedule'
run: |
echo "GALAXY_CONFIG_OVERRIDE_METADATA_STRATEGY=extended" >> $GITHUB_ENV
echo "GALAXY_CONFIG_OVERRIDE_OUTPUTS_TO_WORKING_DIRECTORY=true" >> $GITHUB_ENV
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-performance
- name: Run tests
run: ./run_tests.sh --ci_test_metrics --structured_data_html --structured_data_report_file "test.json" --skip_flakey_fails -api lib/galaxy_test/performance
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: API test results
path: 'galaxy root/run_api_tests.html'
- uses: actions/upload-artifact@v2
with:
name: Performance Metrics
path: 'galaxy root/test.html'
+55
View File
@@ -0,0 +1,55 @@
name: Reports startup
on:
push:
paths-ignore:
- 'doc/**'
pull_request:
paths-ignore:
- 'doc/**'
env:
YARN_INSTALL_OPTS: --frozen-lockfile
concurrency:
group: reports-startup-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Reports startup test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.7', '3.10']
defaults:
run:
shell: bash -l {0}
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-reports-startup
- uses: mvdbeek/gha-yarn-cache@master
with:
yarn-lock-file: 'galaxy root/client/yarn.lock'
- name: Install tox
run: pip install tox
- name: Run tests
run: tox -e reports_startup
working-directory: 'galaxy root'
+86
View File
@@ -0,0 +1,86 @@
name: Selenium tests
on:
push:
paths-ignore:
- 'doc/**'
pull_request:
paths-ignore:
- 'doc/**'
schedule:
# Run at midnight UTC every Tuesday
- cron: '0 0 * * 2'
env:
GALAXY_CONFIG_GALAXY_URL_PREFIX: '/galaxypf'
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
GALAXY_TEST_SELENIUM_RETRIES: 1
GALAXY_TEST_SKIP_FLAKEY_TESTS_ON_ERROR: 1
YARN_INSTALL_OPTS: --frozen-lockfile
GALAXY_CONFIG_SQLALCHEMY_WARN_20: '1'
concurrency:
group: selenium-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.7']
chunk: [0, 1, 2]
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- if: github.event_name == 'schedule'
run: |
echo "GALAXY_CONFIG_OVERRIDE_METADATA_STRATEGY=extended" >> $GITHUB_ENV
echo "GALAXY_CONFIG_OVERRIDE_OUTPUTS_TO_WORKING_DIRECTORY=true" >> $GITHUB_ENV
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-selenium
- uses: mvdbeek/gha-yarn-cache@master
with:
yarn-lock-file: 'galaxy root/client/yarn.lock'
- uses: nanasess/setup-chromedriver@master
- name: Run tests
run: ./run_tests.sh --coverage -selenium lib/galaxy_test/selenium -- --num-shards=3 --shard-id=${{ matrix.chunk }}
working-directory: 'galaxy root'
- uses: codecov/codecov-action@v2
with:
flags: selenium
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Selenium test results (${{ matrix.python-version }}, ${{ matrix.chunk }})
path: 'galaxy root/run_selenium_tests.html'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Selenium debug info (${{ matrix.python-version }}, ${{ matrix.chunk }})
path: 'galaxy root/database/test_errors'
+87
View File
@@ -0,0 +1,87 @@
name: Selenium tests (beta history panel)
on:
push:
paths-ignore:
- 'doc/**'
pull_request:
paths-ignore:
- 'doc/**'
schedule:
# Run at midnight UTC every Tuesday
- cron: '0 0 * * 2'
env:
GALAXY_CONFIG_GALAXY_URL_PREFIX: '/galaxypf'
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
GALAXY_TEST_RAISE_EXCEPTION_ON_HISTORYLESS_HDA: '1'
GALAXY_TEST_SELENIUM_RETRIES: 1
GALAXY_TEST_SELENIUM_BETA_HISTORY: 1
GALAXY_TEST_SKIP_FLAKEY_TESTS_ON_ERROR: 1
YARN_INSTALL_OPTS: --frozen-lockfile
GALAXY_CONFIG_SQLALCHEMY_WARN_20: '1'
concurrency:
group: selenium-beta-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.7']
chunk: [0, 1, 2]
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- if: github.event_name == 'schedule'
run: |
echo "GALAXY_CONFIG_OVERRIDE_METADATA_STRATEGY=extended" >> $GITHUB_ENV
echo "GALAXY_CONFIG_OVERRIDE_OUTPUTS_TO_WORKING_DIRECTORY=true" >> $GITHUB_ENV
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-selenium-beta
- uses: mvdbeek/gha-yarn-cache@master
with:
yarn-lock-file: 'galaxy root/client/yarn.lock'
- uses: nanasess/setup-chromedriver@master
- name: Run tests
run: ./run_tests.sh --coverage -selenium lib/galaxy_test/selenium -- --num-shards=3 --shard-id=${{ matrix.chunk }}
working-directory: 'galaxy root'
- uses: codecov/codecov-action@v2
with:
flags: selenium-beta-history
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Selenium beta history panel test results (${{ matrix.python-version }}, ${{ matrix.chunk }})
path: 'galaxy root/run_selenium_tests.html'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Selenium beta history panel debug info (${{ matrix.python-version }}, ${{ matrix.chunk }})
path: 'galaxy root/database/test_errors'
@@ -0,0 +1,25 @@
name: Test Galaxy release script
on:
push:
paths:
- lib/galaxy/version.py
- scripts/release.sh
- test/release.sh
pull_request:
paths:
- lib/galaxy/version.py
- scripts/release.sh
- test/release.sh
concurrency:
group: test-galaxy-release-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Run tests
run: ./test/release.sh
+46 -21
View File
@@ -1,18 +1,29 @@
name: Toolshed
on: [push, pull_request]
name: Toolshed tests
on:
push:
paths-ignore:
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
env:
GALAXY_TEST_DBURI: 'postgres://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
TOOL_SHED_TEST_DBURI: 'postgres://postgres:postgres@localhost:5432/toolshed?client_encoding=utf8'
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/galaxy?client_encoding=utf8'
TOOL_SHED_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/toolshed?client_encoding=utf8'
concurrency:
group: toolshed-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-18.04
strategy:
matrix:
python-version: [3.7]
python-version: ['3.7']
services:
postgres:
image: postgres:11
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
@@ -20,18 +31,32 @@ jobs:
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Run tests
run: './run_tests.sh -toolshed'
working-directory: 'galaxy root'
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v1
id: pip-cache
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-toolshed
- name: Run tests
run: './run_tests.sh -toolshed'
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Toolshed test results (${{ matrix.python-version }})
path: 'galaxy root/run_toolshed_tests.html'
+58
View File
@@ -0,0 +1,58 @@
name: Unit w/postgres tests
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
env:
GALAXY_TEST_DBURI: 'postgresql://postgres:postgres@localhost:5432/postgres?client_encoding=utf8' # using postgres as the db
concurrency:
group: py-unit-postgres-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.7']
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-unit-postgres
- name: Run migration tests
run: ./run_tests.sh -unit test/unit/data/model/migrations/test_migrations.py
working-directory: 'galaxy root'
+58
View File
@@ -0,0 +1,58 @@
name: Unit tests
on:
push:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
pull_request:
paths-ignore:
- 'client/**'
- 'doc/**'
- 'lib/galaxy_test/selenium/**'
concurrency:
group: py-unit-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.7', '3.10']
steps:
- uses: actions/checkout@v2
with:
path: 'galaxy root'
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get full Python version
id: full-python-version
shell: bash
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
- name: Cache pip dir
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('galaxy root/requirements.txt') }}
- name: Cache galaxy venv
uses: actions/cache@v2
with:
path: 'galaxy root/.venv'
key: gxy-venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('galaxy root/requirements.txt') }}-unit
- name: Install ffmpeg
run: sudo apt-get update && sudo apt-get -y install ffmpeg
- name: Run tests
run: ./run_tests.sh --coverage -u
working-directory: 'galaxy root'
- uses: codecov/codecov-action@v2
with:
flags: py-unit
working-directory: 'galaxy root'
- uses: actions/upload-artifact@v2
if: failure()
with:
name: Unit test results (${{ matrix.python-version }})
path: 'galaxy root/run_unit_tests.html'
+27 -31
View File
@@ -1,4 +1,5 @@
.hg*
# Downloaded and locally built eggs
eggs
scripts/scramble/build
@@ -21,25 +22,7 @@ lib/galaxy/web/framework/static/scripts
lib/galaxy/web/framework/static/style
# Database stuff
database/*.sqlite
database/beaker_sessions
database/citations
database/community_files
database/compiled_templates
database/dependencies
database/files
database/job_working_directory
database/jobs_directory
database/mulled
database/object_store_cache
database/objects
database/openid_consumer_cache
database/pbs
database/shed_tools
database/test_errors
database/tmp
database/tool_cache
database/tool_search_index
/database/
# Python bytecode
@@ -49,6 +32,10 @@ database/tool_search_index
*.lock
*.log
*.pid
celerybeat-schedule
# Celery state files
celerybeat-schedule.*
# Tool Shed Runtime Files
tool_shed_webapp.lock
@@ -95,6 +82,7 @@ config/plugins/**/.cache
static/welcome.html.*
static/welcome.html
static/client_build_hash.txt
lib/galaxy_test/selenium/jupyter/galaxy_selenium_context.yml
# Tool data.
tool-data/annotation_profiler_options.xml
@@ -121,12 +109,13 @@ tool-data/**/*.fa
.pytest_cache/
assets/
test-data-cache
run_api_tests.html
run_cwl_tests.html
run_framework_tests.html
run_functional_tests.html
run_integration_tests.html
run_selenium_tests.html
run_toolshed_tests.html
run_api_tests.html
test/tool_shed/tmp/*
.coverage
htmlcov
@@ -139,7 +128,7 @@ test/unit/**.log
.idea
.vscode
client/**/jsconfig.json
vetur.config.js
# Chrom len files
*.len
@@ -153,18 +142,16 @@ static/plugins
static/scripts
node_modules
bower_components
client/galaxy/scripts/libs/*
client/galaxy/style/less/*
client/src/libs/*
# Old galaxy client location
client/galaxy
# Documentation build files.
doc/build
doc/schema.md
doc/source/admin/config_logging_default_yaml.rst
doc/source/api/api.rst
doc/source/api/ts_api.rst
doc/source/dev/schema.md
doc/source/dev/schema.rst
client/styleguide
client/docs/dist
# webpack stats
client/webpack-stats.json
@@ -181,7 +168,16 @@ packages/*/*.egg-info
*~
# standalone script + main, or build into dist.
config/plugins/visualizations/**/static/dist
config/plugins/visualizations/**/static/script.js
config/plugins/visualizations/**/static/main.css
config/plugins/visualizations/**/static/plugin_build_hash.txt
config/plugins/**/static/dist
config/plugins/**/static/script.js
config/plugins/**/static/main.css
config/plugins/**/static/plugin_build_hash.txt
config/plugins/**/static/*.map
# viz-specific build artifacts to ignore (until these are removed from codebase)
config/plugins/visualizations/annotate_image/static/jquery.contextMenu.css
config/plugins/visualizations/nvd3/nvd3_bar/static/nvd3.js
# CWL conformance tests
lib/galaxy_test/api/cwl/test_cwl_conformance_v1_?.py
test/functional/tools/cwl_tools/v1.?/
+34
View File
@@ -0,0 +1,34 @@
github:
prebuilds:
# enable for the master/default branch (defaults to true)
master: true
# enable for all branches in this repo (defaults to false)
branches: true
# enable for pull requests coming from this repo (defaults to true)
pullRequests: true
# enable for pull requests coming from forks (defaults to false)
pullRequestsFromForks: true
# add a "Review in Gitpod" button as a comment to pull requests (defaults to true)
addComment: false
# add a "Review in Gitpod" button to pull requests (defaults to false)
addBadge: false
# add a label once the prebuild is ready to pull requests (defaults to false)
addLabel: false
image: gitpod/workspace-postgres
tasks:
- init: >
cp .vscode/settings_gitpod.json .vscode/settings.json &&
cp .vscode/launch_gitpod.json .vscode/launch.json &&
pip install psycopg2 &&
pip install -r lib/galaxy/dependencies/dev-requirements.txt &&
createdb galaxy &&
make client
- command: cp config/galaxy.yml.sample config/galaxy.yml
- command: make client-watch
# Ports to expose on workspace startup (optional)
ports:
- port: 8000
vscode:
extensions:
- ms-python.python
- ms-python.vscode-pylance
+14
View File
@@ -0,0 +1,14 @@
[settings]
extend_skip=doc/source/conf.py,lib/galaxy/util/jstree.py
force_alphabetical_sort_within_sections=true
# Override force_grid_wrap value from profile=black, but black is still happy
force_grid_wrap=2
# Same line length as for black
line_length=120
no_lines_before=LOCALFOLDER
profile=black
reverse_relative=true
skip_gitignore=true
# Make isort run faster by skipping database
skip_glob=database/*
src_paths=lib
+194
View File
@@ -0,0 +1,194 @@
# Stage 1:
# - base: ubuntu (default) OR prebuilt image0
# - install build tools
# - clone playbook
# Stage 2: build galaxy client and server in parallel
# Stage 2.1:
# - run playbook with server build steps only
# - remove build artifacts + files not needed in container
# Stage 2.2:
# - run playbook with client build steps only
# - remove build artifacts + files not needed in container
# Stage 3:
# - create galaxy user + group + directory
# - copy galaxy files from stage 2.1 and 2.2
# - finalize container (set path, user...)
# Init ARGs
ARG ROOT_DIR=/galaxy
ARG SERVER_DIR=$ROOT_DIR/server
ARG STAGE1_BASE=python:3.7-slim
ARG FINAL_STAGE_BASE=$STAGE1_BASE
ARG GALAXY_USER=galaxy
ARG GALAXY_PLAYBOOK_REPO=https://github.com/galaxyproject/galaxy-docker-k8s
ARG GALAXY_PLAYBOOK_BRANCH=v2.0.0
ARG GIT_COMMIT=unspecified
ARG BUILD_DATE=unspecified
ARG IMAGE_TAG=unspecified
#======================================================
# Stage 1 - Setup common requirements for build
#======================================================
FROM $STAGE1_BASE AS stage1
ARG DEBIAN_FRONTEND=noninteractive
ARG SERVER_DIR
ARG GALAXY_PLAYBOOK_REPO
ARG GALAXY_PLAYBOOK_BRANCH
# Init Env
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8
# Install build dependencies + ansible
RUN set -xe; \
echo "Acquire::http {No-Cache=True;};" > /etc/apt/apt.conf.d/no-cache \
&& apt-get -qq update && apt-get install -y --no-install-recommends \
locales locales-all \
git \
make \
libc-dev \
bzip2 \
gcc \
&& pip install --no-cache virtualenv 'ansible<2.10' \
&& apt-get autoremove -y && apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/*
# Remove context from previous build; copy current context; run playbook
WORKDIR /tmp/ansible
RUN rm -rf *
ENV LC_ALL en_US.UTF-8
RUN git clone --depth 1 --branch $GALAXY_PLAYBOOK_BRANCH $GALAXY_PLAYBOOK_REPO galaxy-docker
WORKDIR /tmp/ansible/galaxy-docker
RUN ansible-galaxy install -r requirements.yml -p roles --force-with-deps
# Add Galaxy source code
COPY . $SERVER_DIR/
#======================================================
# Stage 2.1 - Build galaxy server
#======================================================
FROM stage1 AS server_build
ARG SERVER_DIR
RUN ansible-playbook -i localhost, playbook.yml -v -e galaxy_build_client=False -e galaxy_virtualenv_command=virtualenv
RUN cat /galaxy/server/lib/galaxy/dependencies/conditional-requirements.txt | grep psycopg2-binary | xargs /galaxy/server/.venv/bin/pip install
# Remove build artifacts + files not needed in container
WORKDIR $SERVER_DIR
# Save commit hash of HEAD before zapping git folder
RUN git rev-parse HEAD > GITREVISION
RUN rm -rf \
.ci \
.git \
.venv/include/node \
.venv/src/node* \
doc \
test \
test-data
# Clean up *all* node_modules, including plugins. Everything is already built+staged.
RUN find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
#======================================================
# Stage 2.2 - Build galaxy client
#======================================================
FROM stage1 AS client_build
ARG SERVER_DIR
RUN ansible-playbook -i localhost, playbook.yml -v --tags "galaxy_build_client" -e galaxy_virtualenv_command=virtualenv
WORKDIR $SERVER_DIR
RUN rm -rf \
.ci \
.git \
.venv/include/node \
.venv/src/node* \
doc \
test \
test-data
# Clean up *all* node_modules, including plugins. Everything is already built+staged.
RUN find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
#======================================================
# Stage 3 - Build final image based on previous stages
#======================================================
FROM $FINAL_STAGE_BASE
ARG DEBIAN_FRONTEND=noninteractive
ARG ROOT_DIR
ARG SERVER_DIR
ARG GALAXY_USER
ARG GIT_COMMIT
ARG BUILD_DATE
ARG IMAGE_TAG
LABEL org.opencontainers.image.title="Galaxy Minimal Image" \
org.opencontainers.image.description="A size optimized image for Galaxy targeting k8s and ci applications" \
org.opencontainers.image.authors="galaxyproject.org" \
org.opencontainers.image.vendor="Galaxy Project" \
org.opencontainers.image.documentation="https://github.com/galaxyproject/galaxy-docker-k8s" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.version="$IMAGE_TAG" \
org.opencontainers.image.url="https://github.com/galaxyproject/galaxy-docker-k8s" \
org.opencontainers.image.source="https://github.com/galaxyproject/galaxy.git" \
org.opencontainers.image.revision=$GIT_COMMIT \
org.opencontainers.image.created=$BUILD_DATE
# Init Env
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8
# Install procps (contains kill, ps etc.), less, curl, vim-tiny and nano-tiny
# for convenience and debugging purposes. Nano and vim commands are aliased
# to their tiny variants using the debian alternatives system.
# Bzip2 and virtualenv are installed for backwards compatibility with older
# versions of this image which was based on Ubuntu and contained these
# utilities.
RUN set -xe; \
echo "Acquire::http {No-Cache=True;};" > /etc/apt/apt.conf.d/no-cache \
&& apt-get -qq update && apt-get install -y --no-install-recommends \
locales \
vim-tiny \
nano-tiny \
curl \
procps \
less \
bzip2 \
tini \
&& update-alternatives --install /usr/bin/nano nano /bin/nano-tiny 0 \
&& update-alternatives --install /usr/bin/vim vim /usr/bin/vim.tiny 0 \
&& echo "set nocompatible\nset backspace=indent,eol,start" >> /usr/share/vim/vimrc.tiny \
&& echo "$LANG UTF-8" > /etc/locale.gen \
&& locale-gen $LANG && update-locale LANG=$LANG \
&& apt-get autoremove -y && apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/*
# Create Galaxy user, group, directory; chown
RUN set -xe; \
adduser --system --group $GALAXY_USER \
&& mkdir -p $SERVER_DIR \
&& chown $GALAXY_USER:$GALAXY_USER $ROOT_DIR -R
WORKDIR $ROOT_DIR
# Copy galaxy files to final image
# The chown value MUST be hardcoded (see https://github.com/moby/moby/issues/35018)
COPY --chown=$GALAXY_USER:$GALAXY_USER --from=server_build $ROOT_DIR .
COPY --chown=$GALAXY_USER:$GALAXY_USER --from=client_build $SERVER_DIR/static ./server/static
WORKDIR $SERVER_DIR
# The data in version.json will be displayed in Galaxy's /api/version endpoint
RUN printf "{\n \"git_commit\": \"$(cat GITREVISION)\",\n \"build_date\": \"$BUILD_DATE\",\n \"image_tag\": \"$IMAGE_TAG\"\n}\n" > version.json
EXPOSE 8080
USER $GALAXY_USER
ENV PATH="$SERVER_DIR/.venv/bin:${PATH}"
ENV GALAXY_CONFIG_CONDA_AUTO_INIT=False
ENTRYPOINT ["tini", "--"]
# [optional] to run:
CMD galaxy
+1
View File
@@ -0,0 +1 @@
GALAXY_TEST_TOOL_CONF="lib/galaxy/config/sample/tool_conf.xml.sample,test/functional/tools/samples_tool_conf.xml"
+46
View File
@@ -0,0 +1,46 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "GalaxyFastAPI uvicorn",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": ["--app-dir", "lib", "--factory", "galaxy.webapps.galaxy.fast_factory:factory"],
"env": {
"GALAXY_CONFIG_FILE": "${workspaceFolder}/config/galaxy.yml",
"GALAXY_CONDA_AUTO_INIT": "false",
"GALAXY_CONFIG_TOOL_CONFIG_FILE": "lib/galaxy/config/sample/tool_conf.xml.sample,test/functional/tools/samples_tool_conf.xml",
"GALAXY_CONFIG_DATABASE_CONNECTION": "postgresql://localhost/galaxy"
}
},
{
"name": "Tool test framework",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/.venv/bin/pytest",
"args": [
"test/functional/test_toolbox_pytest.py",
"-m",
"tool",
"-k",
"job_properties_test_2"
]
},
{
"type": "node",
"name": "debug selected jest unit test",
"request": "launch",
"program": "${workspaceFolder}/client/node_modules/jest/bin/jest",
"args": [
"--runInBand",
"--config",
"${workspaceFolder}/client/tests/jest/jest.config.js",
"${file}"
],
"cwd": "${workspaceFolder}/client",
"console": "integratedTerminal",
"disableOptimisticBPs": true
}
]
}
+13
View File
@@ -0,0 +1,13 @@
{
"python.testing.pytestArgs": [
"--doctest-modules",
"lib/galaxy_test/api/",
"lib/galaxy/datatypes",
"test/unit",
"test/integration",
"lib/galaxy_test/selenium/"
],
"python.testing.pytestEnabled": true,
"python.envFile": "${workspaceFolder}/.vscode/.test.env"
}
+25 -6
View File
@@ -1,5 +1,16 @@
Galaxy Project Code of Conduct
==============================
# Galaxy Project Code of Conduct
## Note: Change is Coming
Since 2015 the Galaxy Project Code of Conduct has resided here, and updates to it have been coordinated by the Committers Group for this repo.
This code of conduct has served us reasonably well over the years, but it is time for a refresh. Since 2015 the world has become much more aware of the need for codes of conduct, and best practices for creating and enforcing them have moved forward significantly.
**As a result it is past time to update both our code of conduct and our process for maintaining it.** The Galaxy Outreach and Training [Working Group](https://galaxyproject.org/community/wg/) is currently working on a first draft of a new code and new processes. The final code and processes we adopt will be [implemented](https://galaxyproject.org/community/coc/) only after it has been discussed, revised, and approved by the community.
Until that happens this will remain the Galaxy Project Code of Conduct.
# Code of Conduct
This code of conduct outlines our expectations for participants within the
Galaxy community, as well as steps to reporting unacceptable behavior. We are
@@ -71,10 +82,18 @@ participants with disabilities.
### Reporting Issues
If you experience or witness unacceptable behavior, or have any other concerns,
please report it by contacting Dave Clements (clementsgalaxy@gmail.com). To
report an issue involving Dave Clements please email James Taylor
(james@taylorlab.org). All reports will be handled with discretion. In your
report please include:
please report it to any combination of the following people that makes you feel
the most comfortable:
- Dave Clements (clementsgalaxy@gmail.com). Dave is the Galaxy Project community
outreach manager and has experience handling Code of Conduct related issues.
- Dr. Mike Schatz (mschatz@cs.jhu.edu). Mike is Dave Clements' direct manager
and issues related to Dave in some way should be reported to Mike.
- Helena Rasche (helena.rasche@gmail.com). Helena is a well-known, trusted
community member, is LGBT+, and has completely separate funding and
institutional affiliation from Dave and Mike.
All reports will be handled with discretion. In your report please include:
- Your contact information.
+28 -10
View File
@@ -41,7 +41,10 @@ Git](https://swcarpentry.github.io/git-novice/) tutorial is a good place to
start. More learning resources are listed at
https://help.github.com/en/github/getting-started-with-github/git-and-github-learning-resources
1. Make sure you have a free [GitHub](https://github.com/) account.
1. Make sure you have a free [GitHub](https://github.com/) account. To increase
the security of your account, we strongly recommend that you configure
[two-factor authentication](https://docs.github.com/en/github/authenticating-to-github/securing-your-account-with-two-factor-authentication-2fa).
Additionally, you may want to [sign your commits](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification).
2. Fork the [galaxy repository](https://github.com/galaxyproject/galaxy) on
GitHub to make your changes. To keep your copy up to date with respect to
@@ -88,10 +91,23 @@ https://help.github.com/en/github/getting-started-with-github/git-and-github-lea
Developers reviewing your pull request will be happy to help you add or run
the relevant tests as part of the pull request review process.
6. Commit and push your changes to your
6. Write a useful and properly formatted commit message.
Follow [these guidelines and template](https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines),
in particular start your message with a short imperative sentence on a single
line, possibly followed by a blank line and a more detailed explanation.
In the detailed explanation it's good to include relevant external references
(e.g. GitHub issue fixed) using full URLs, and errors or tracebacks the
commit is supposed to fix.
You can use the Markdown syntax for lists and code highlighting, wrapping the
explanation text at 72 characters when possible.
Example of a good commit message: https://github.com/galaxyproject/galaxy/commit/0429c4d515536f9cca6b70b2abeb019de807c955
7. Commit and push your changes to your
[fork](https://help.github.com/en/github/using-git/pushing-commits-to-a-remote-repository).
7. Open a [pull
8. Open a [pull
request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)
with these changes. Your pull request message ideally should include:
@@ -101,10 +117,10 @@ https://help.github.com/en/github/getting-started-with-github/git-and-github-lea
* How to test the changes, if you haven't included specific tests already.
8. The pull request should pass all the continuous integration tests which are
9. The pull request should pass all the continuous integration tests which are
automatically started by GitHub using e.g. Travis CI.
9. Your pull request will be handled according to [some
10. Your pull request will be handled according to [some
rules](doc/source/project/organization.rst#handling-pull-requests).
## Style guidelines
@@ -114,11 +130,13 @@ https://help.github.com/en/github/getting-started-with-github/git-and-github-lea
- Galaxy follows [PEP-8](https://www.python.org/dev/peps/pep-0008/), with
particular emphasis on readability being the ultimate goal:
- 4 spaces (not tabs!) per indentation level
- divergences from PEP-8 are listed in the `[flake8]` section of the `setup.cfg`
file.
- Python imports should be ordered following the
[smarkets](https://github.com/PyCQA/flake8-import-order/blob/master/tests/test_cases/complete_smarkets.py)
style.
- divergences from PEP-8 are listed in the `[flake8]` section of the
`setup.cfg` file
- The Python code base is automatically formatted using
[isort](https://pycqa.github.io/isort/) (for imports) and
[black](https://black.readthedocs.io). To easily format your Python code
before submitting your contribution, please either use `make diff-format`
or run `isort FILE; black FILE` for each FILE you modify.
- Python [docstrings](http://www.python.org/dev/peps/pep-0257/) need to be in
[reStructured Text (RST)](https://docutils.sourceforge.io/rst.html) format and
compatible with [Sphinx](https://www.sphinx-doc.org).
+1
View File
@@ -132,6 +132,7 @@ The following individuals have contributed code to Galaxy:
* Michael Sauria <crockopotamus@gmail.com>
* Andrea Sbardellati <andrea.sbardellati@crs4.it>
* Ian Schenck <ian@bx.psu.edu>
* Jelle Scholtalbers <j.scholtalbers@gmail.com>
* Nick Semenkovich <semenko@alum.mit.edu>
* Varun Shankar <varunshankar55@gmail.com>
* Matthew Shirley <mdshw5@gmail.com>
+54 -114
View File
@@ -1,15 +1,10 @@
# Location of virtualenv used for development.
VENV?=.venv
# Source virtualenv to execute command (flake8, sphinx, twine, etc...)
IN_VENV=if [ -f $(VENV)/bin/activate ]; then . $(VENV)/bin/activate; fi;
RELEASE_CURR:=16.01
RELEASE_CURR_MINOR_NEXT:=$(shell $(IN_VENV) python scripts/bootstrap_history.py --print-next-minor-version)
RELEASE_NEXT:=16.04
# TODO: This needs to be updated with create_release_rc
#RELEASE_NEXT_BRANCH:=release_$(RELEASE_NEXT)
RELEASE_NEXT_BRANCH:=dev
IN_VENV=if [ -f "$(VENV)/bin/activate" ]; then . "$(VENV)/bin/activate"; fi;
RELEASE_CURR:=22.05
RELEASE_UPSTREAM:=upstream
MY_UPSTREAM:=origin
TARGET_BRANCH=$(RELEASE_UPSTREAM)/dev
CONFIG_MANAGE=$(IN_VENV) python lib/galaxy/config/config_manage.py
PROJECT_URL?=https://github.com/galaxyproject/galaxy
DOCS_DIR=doc
@@ -18,6 +13,13 @@ SLIDESHOW_DIR=$(DOC_SOURCE_DIR)/slideshow
OPEN_RESOURCE=bash -c 'open $$0 || xdg-open $$0'
SLIDESHOW_TO_PDF?=bash -c 'docker run --rm -v `pwd`:/cwd astefanutti/decktape /cwd/$$0 /cwd/`dirname $$0`/`basename -s .html $$0`.pdf'
YARN := $(shell command -v yarn 2> /dev/null)
YARN_INSTALL_OPTS=--network-timeout 300000 --check-files
CWL_TARGETS := test/functional/tools/cwl_tools/v1.0/conformance_tests.yaml \
test/functional/tools/cwl_tools/v1.1/conformance_tests.yaml \
test/functional/tools/cwl_tools/v1.2/conformance_tests.yaml \
lib/galaxy_test/api/cwl/test_cwl_conformance_v1_0.py \
lib/galaxy_test/api/cwl/test_cwl_conformance_v1_1.py \
lib/galaxy_test/api/cwl/test_cwl_conformance_v1_2.py
all: help
@echo "This makefile is used for building Galaxy's JS client, documentation, and drive the release process. A sensible all target is not implemented."
@@ -30,9 +32,19 @@ docs: ## Generate HTML documentation.
$(IN_VENV) $(MAKE) -C doc clean
$(IN_VENV) $(MAKE) -C doc html
docs-develop: ## Fast doc generation and more warnings (for development)
$(IN_VENV) GALAXY_DOCS_SKIP_VIEW_CODE=1 SPHINXOPTS='-j 4' $(MAKE) -C doc html
setup-venv:
if [ ! -f $(VENV)/bin/activate ]; then bash scripts/common_startup.sh --dev-wheels; fi
diff-format: ## Format Python code changes since last commit
$(IN_VENV) darker .
format: ## Format Python code base
$(IN_VENV) isort .
$(IN_VENV) black .
list-dependency-updates: setup-venv
$(IN_VENV) pip list --outdated --format=columns
@@ -52,12 +64,6 @@ open-docs: docs _open-docs ## generate Sphinx HTML documentation and open in bro
open-project: ## open project on github
$(OPEN_RESOURCE) $(PROJECT_URL)
lint: ## check style using tox and flake8 for Python 2 and Python 3
$(IN_VENV) tox -e py27-lint && tox -e py34-lint
uwsgi-rebuild-validation: ## rebuild uwsgi_config.yml kwalify schema against latest uwsgi master.
$(CONFIG_MANAGE) build_uwsgi_yaml
tool-shed-config-validate: ## validate tool shed YAML configuration file
$(CONFIG_MANAGE) validate tool_shed
@@ -129,21 +135,36 @@ release-check-blocking-prs: ## Check github for release blocking PRs
release-bootstrap-history: ## bootstrap history for a new release
$(IN_VENV) python scripts/bootstrap_history.py --release $(RELEASE_CURR)
build-dependencies-docker: ## Builds the docker container used for dependency updates
$(MAKE) -C lib/galaxy/dependencies/pipfiles/docker
update-lint-requirements:
./lib/galaxy/dependencies/update_lint_requirements.sh
update-dependencies: build-dependencies-docker ## update linting + dev dependencies
sh lib/galaxy/dependencies/pipfiles/update.sh -d
update-dependencies: update-lint-requirements ## update pinned and dev dependencies
$(IN_VENV) ./lib/galaxy/dependencies/update.sh
update-and-commit-dependencies: build-dependencies-docker ## update and commit linting + dev dependencies
sh lib/galaxy/dependencies/pipfiles/update.sh -d -c
$(CWL_TARGETS):
./scripts/update_cwl_conformance_tests.sh
generate-cwl-conformance-tests: $(CWL_TARGETS) ## Initialise CWL conformance tests
clean-cwl-conformance-tests: ## Clean CWL conformance tests
for f in $(CWL_TARGETS); do \
if [ $$(basename "$$f") = conformance_tests.yaml ]; then \
rm -rf $$(dirname "$$f"); \
else \
rm -f "$$f"; \
fi \
done
update-cwl-conformance-tests: ## update CWL conformance tests
$(MAKE) clean-cwl-conformance-tests
$(MAKE) generate-cwl-conformance-tests
node-deps: ## Install NodeJS dependencies.
ifndef YARN
@echo "Could not find yarn, which is required to build the Galaxy client.\nTo install yarn, please visit \033[0;34mhttps://yarnpkg.com/en/docs/install\033[0m for instructions, and package information for all platforms.\n"
false;
else
cd client && yarn install --network-timeout 300000 --check-files
cd client && yarn install $(YARN_INSTALL_OPTS)
endif
@@ -163,9 +184,9 @@ client-watch: node-deps ## A useful target for parallel development building. S
cd client && yarn run watch
client-dev-server: node-deps ## Starts a webpack dev server for client development (HMR enabled)
cd client && yarn run webpack-dev-server
cd client && yarn run serve
client-test: node-deps ## Run JS unit tests via Karma
client-test: node-deps ## Run JS unit tests
cd client && yarn run test
client-eslint: node-deps # Run client linting
@@ -176,101 +197,20 @@ client-format-check: node-deps # Run client formatting check
client-lint: client-eslint client-format-check ## ES lint and check format of client
client-test-watch: client ## Watch and run qunit tests on changes via Karma
cd client && yarn run test-watch
client-test-watch: client ## Watch and run all client unit tests on changes
cd client && yarn run jest-watch
serve-selenium-notebooks: ## Serve testing notebooks for Jupyter
cd lib && export PYTHONPATH=`pwd`; jupyter notebook --notebook-dir=galaxy_test/selenium/jupyter
# Release Targets
release-create-rc: release-ensure-upstream ## Create a release-candidate branch
git checkout dev
git pull --ff-only $(RELEASE_UPSTREAM) dev
git push $(MY_UPSTREAM) dev
git checkout -b release_$(RELEASE_CURR)
git push $(MY_UPSTREAM) release_$(RELEASE_CURR)
git push $(RELEASE_UPSTREAM) release_$(RELEASE_CURR)
git checkout -b version-$(RELEASE_CURR)
sed -i.bak -e "s/^VERSION_MAJOR = .*/VERSION_MAJOR = \"$(RELEASE_CURR)\"/" lib/galaxy/version.py
sed -i.bak -e "s/^VERSION_MINOR = .*/VERSION_MINOR = \"rc1\"/" lib/galaxy/version.py
rm -f lib/galaxy/version.py.bak
git add lib/galaxy/version.py
git commit -m "Update version to $(RELEASE_CURR).rc1"
git checkout dev
release-create-rc: ## Create a release-candidate branch or new release-candidate version
$(IN_VENV) ./scripts/release.sh -c
git checkout -b version-$(RELEASE_NEXT).dev
sed -i.bak -e "s/^VERSION_MAJOR = .*/VERSION_MAJOR = \"$(RELEASE_NEXT)\"/" lib/galaxy/version.py
rm -f lib/galaxy/version.py.bak
git add lib/galaxy/version.py
git commit -m "Update version to $(RELEASE_NEXT).dev"
release-create: ## Create a release branch
$(IN_VENV) ./scripts/release.sh
-git merge version-$(RELEASE_CURR)
git checkout --ours lib/galaxy/version.py
git add lib/galaxy/version.py
git commit -m "Merge branch 'version-$(RELEASE_CURR)' into version-$(RELEASE_NEXT).dev"
git push $(MY_UPSTREAM) version-$(RELEASE_CURR):version-$(RELEASE_CURR)
git push $(MY_UPSTREAM) version-$(RELEASE_NEXT).dev:version-$(RELEASE_NEXT).dev
git checkout dev
# TODO: Use hub to automate these PR creations or push directly.
@echo "Open a PR from version-$(RELEASE_CURR) of your fork to release_$(RELEASE_CURR)"
@echo "Open a PR from version-$(RELEASE_NEXT).dev of your fork to dev"
release-create: release-ensure-upstream ## Create a release branch
git checkout master
git pull --ff-only $(RELEASE_UPSTREAM) master
git push $(MY_UPSTREAM) master
git checkout release_$(RELEASE_CURR)
git pull --ff-only $(RELEASE_UPSTREAM) release_$(RELEASE_CURR)
#git push $(MY_UPSTREAM) release_$(RELEASE_CURR)
git checkout dev
git pull --ff-only $(RELEASE_UPSTREAM) dev
#git push $(MY_UPSTREAM) dev
# Test run of merging. If there are conflicts, it will fail here.
git merge release_$(RELEASE_CURR)
git checkout release_$(RELEASE_CURR)
sed -i.bak -e "s/^VERSION_MINOR = .*/VERSION_MINOR = None/" lib/galaxy/version.py
rm -f lib/galaxy/version.py.bak
git add lib/galaxy/version.py
git commit -m "Update version to $(RELEASE_CURR)"
git tag -m "Tag version $(RELEASE_CURR)" v$(RELEASE_CURR)
git checkout dev
-git merge release_$(RELEASE_CURR)
git checkout --ours lib/galaxy/version.py
git add lib/galaxy/version.py
git commit -m "Merge branch 'release_$(RELEASE_CURR)' into dev"
git checkout master
git merge release_$(RELEASE_CURR)
git push $(RELEASE_UPSTREAM) release_$(RELEASE_CURR):release_$(RELEASE_CURR)
git push $(RELEASE_UPSTREAM) dev:dev
git push $(RELEASE_UPSTREAM) master:master
git push $(RELEASE_UPSTREAM) --tags
release-create-point: ## Create a point release
git pull --ff-only $(RELEASE_UPSTREAM) master
git push $(MY_UPSTREAM) master
git checkout release_$(RELEASE_CURR)
git pull --ff-only $(RELEASE_UPSTREAM) release_$(RELEASE_CURR)
#git push $(MY_UPSTREAM) release_$(RELEASE_CURR)
git checkout $(RELEASE_NEXT_BRANCH)
git pull --ff-only $(RELEASE_UPSTREAM) $(RELEASE_NEXT_BRANCH)
#git push $(MY_UPSTREAM) $(RELEASE_NEXT_BRANCH)
git merge release_$(RELEASE_CURR)
git checkout release_$(RELEASE_CURR)
sed -i.bak -e "s/^VERSION_MINOR = .*/VERSION_MINOR = \"$(RELEASE_CURR_MINOR_NEXT)\"/" lib/galaxy/version.py
rm -f lib/galaxy/version.py.bak
git add lib/galaxy/version.py
git commit -m "Update version to $(RELEASE_CURR).$(RELEASE_CURR_MINOR_NEXT)"
git tag -m "Tag version $(RELEASE_CURR).$(RELEASE_CURR_MINOR_NEXT)" v$(RELEASE_CURR).$(RELEASE_CURR_MINOR_NEXT)
git checkout $(RELEASE_NEXT_BRANCH)
-git merge release_$(RELEASE_CURR)
git checkout --ours lib/galaxy/version.py
git add lib/galaxy/version.py
git commit -m "Merge branch 'release_$(RELEASE_CURR)' into $(RELEASE_NEXT_BRANCH)"
git checkout master
git merge release_$(RELEASE_CURR)
#git push origin release_$(RELEASE_CURR):release_$(RELEASE_CURR)
#git push origin $(RELEASE_NEXT_BRANCH):release_$(RELEASE_NEXT_BRANCH)
#git push origin master:master
#git push origin --tags
git checkout release_$(RELEASE_CURR)
release-create-point: release-create ## Create a point release
.PHONY: help
+2 -2
View File
@@ -24,12 +24,12 @@ Community support is available at `Galaxy Help <https://help.galaxyproject.org/>
Galaxy Quickstart
=================
Galaxy requires Python 3.5 or 3.6 . To check your Python version, run:
Galaxy requires Python 3.7 . To check your Python version, run:
.. code:: console
$ python -V
Python 3.6.10
Python 3.7.6
Start Galaxy:
Executable
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
cd "$(dirname "$0")"
. ./scripts/common_startup_functions.sh
setup_python
python ./scripts/check_model.py "$@"
[ $? -ne 0 ] && exit 1;
exit 0;
-6
View File
@@ -1,6 +0,0 @@
*.test.js
galaxy/scripts/qunit
galaxy/scripts/mocha
galaxy/scripts/libs
galaxy/scripts/nls
galaxy/scripts/legacy
-47
View File
@@ -1,47 +0,0 @@
module.exports = {
extends: [
"eslint:recommended",
"plugin:vue/strongly-recommended"
//"airbnb-base", eventually
],
env: {
browser: true,
commonjs: true,
es6: true,
node: true,
mocha: true
},
parserOptions: {
parser: "babel-eslint",
sourceType: "module"
},
rules: {
// Standard rules
"no-console": "off",
"no-unused-vars": ["error", { args: "none" }],
"prefer-const": "error",
"one-var": ["error", "never"],
"vue/valid-v-slot": "error",
"vue/v-slot-style": ["error", { atComponent: "v-slot", default: "v-slot", named: "longform" }],
// Vue TODO (enable these)
"vue/require-default-prop": "warn",
"vue/require-prop-types": "warn",
"vue/prop-name-casing": "warn",
// Prettier compromises/workarounds -- mostly #wontfix?
"vue/html-indent": "off",
"vue/max-attributes-per-line": "off",
"vue/html-self-closing": "off",
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline": "off",
"vue/html-closing-bracket-newline": "off",
"vue/html-closing-bracket-spacing": "off"
},
globals: {
// chai tests
assert: true,
expect: true
}
};
+45
View File
@@ -0,0 +1,45 @@
{
"extends": [
"eslint:recommended",
"plugin:vue/strongly-recommended"
//"airbnb-base", eventually
],
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true,
"jest": true
},
"parserOptions": {
"parser": "@babel/eslint-parser",
"sourceType": "module"
},
"rules": {
// Standard rules
"no-console": "off",
"no-unused-vars": ["error", { "args": "none" }],
"prefer-const": "error",
"one-var": ["error", "never"],
"curly": "error",
"vue/valid-v-slot": "error",
"vue/v-slot-style": ["error", { "atComponent": "v-slot", "default": "v-slot", "named": "longform" }],
// Vue TODO (enable these)
"vue/require-default-prop": "warn",
"vue/require-prop-types": "warn",
"vue/prop-name-casing": "warn",
"vue/multi-word-component-names": "warn",
// Prettier compromises/workarounds -- mostly #wontfix?
"vue/html-indent": "off",
"vue/max-attributes-per-line": "off",
"vue/html-self-closing": "off",
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline": "off",
"vue/html-closing-bracket-newline": "off",
"vue/html-closing-bracket-spacing": "off"
},
"ignorePatterns": ["src/qunit", "src/mocha", "src/libs", "src/nls", "src/legacy"]
}
+1 -1
View File
@@ -1 +1 @@
12.16.3
16.13.2
+74 -231
View File
@@ -1,36 +1,35 @@
Client Build System
===================
# Client Build System
Installs, stages, and builds the client-side scripts necessary for running the
Galaxy webapp. When started through `run.sh` or any other method that utilizes
`scripts/common_startup.sh`, Galaxy will (since 18.09) *automatically* build
`scripts/common_startup.sh`, Galaxy will (since 18.09) _automatically_ build
the client as a part of server startup, when it detects changes, unless that
functionality is explicitly disabled.
The base dependencies used are Node.js and Yarn. Galaxy now includes these in
The base dependencies used are Node.js and Yarn. Galaxy now includes these in
the virtual environment, and they can be accessed by activating that with `.
.venv/bin/activate` from the Galaxy root directory.
If you'd like to install your own dependencies, on OSX the easiest way to get
set up is using `homebrew` and the command `brew install nodejs yarn`. More
set up is using `homebrew` and the command `brew install nodejs yarn`. More
information, including instructions for other platforms, is available at
https://nodejs.org/ and https://yarnpkg.com/ .
[https://nodejs.org](https://nodejs.org) and
[https://yarnpkg.com/](https://yarnpkg.com).
The Galaxy client build has necessarily grown more complex in the past several
years, but we are still trying to keep things as simple as possible for
everyone. If you're having any trouble with building the client after
following the instructions below, please create an issue on GitHub or reach out
for help directly on Gitter at https://gitter.im/galaxyproject/Lobby .
everyone. If you're having any trouble with building the client after following
the instructions below, please create an issue on GitHub or reach out for help
directly on Gitter at
[https://gitter.im/galaxyproject/Lobby](https://gitter.im/galaxyproject/Lobby).
Complete Client Build
=====================
## Complete Client Build
There are many moving parts to the client build system, but the entry point for
most people is the 'client' rule in the Makefile at the root of the Galaxy
repository. Execute the following to perform a complete build suitable for
repository. Execute the following to perform a complete build suitable for
local development, including dependency staging, style building, script
processing, and bundling. This is a development-specific build which includes
processing, and bundling. This is a development-specific build which includes
extra debugging features, and excludes several production optimizations made
during the build process.
@@ -49,276 +48,120 @@ for inspection of live javascript to facilitate debugging, use:
Important Note: The Galaxy repository does not include client script artifacts,
and these should not be committed.
## Automatic Rebuilding
Automatic Rebuilding (Watch Mode)
=================================
When you're actively developing, it is sometimes convenient to have the client
automatically rebuild every time you save a file. You can do this using:
When you're actively developing, it is convenient to have the client
automatically rebuild every time you save a file. You can do this using:
make client-watch
This will first stage any dependencies (yarn-installed packages like jquery,
etc), and then will watch for changes in any of the galaxy client source files.
When a file is changed, the client will automatically rebuild, after which you
can usually force refresh your browser to see changes. Note that it is still
recommended to run `make client` after you are finished actively developing
using `make client-watch`.
This will first stage client dependencies, initiate a build, and then will
watch for changes in any of the galaxy client source files. When a file is
changed, the client will automatically rebuild, after which you can refresh
your browser to see changes.
Note that there's a new, better option described in the next section. This
method of building will likely be deprecated as HMR is more widely tested.
For even more rapid development you can use the webpack development server,
which takes advantage of hot module replacement (HMR). This technique allows
swapping out of javascript modules while the application is running without
requiring a full page reload most of the time, at least in the more modern
parts of the application.
Even Better Automatic Rebuilding (HMR)
======================================
For even more rapid development you can use the webpack development server for
Hot Module Replacement (HMR). This technique allows swapping out of modules
while the application is running without requiring a full page reload most of
the time.
Setting this up is a little more involved, but it is the fastest possible way
to iterate when developing the client. You'll need to start two separate
processes here. The first command below starts a special webpack dev server
after a client build, and the second starts a Galaxy server like usual, but
with extra mappings that redirect client artifact requests to the mentioned
webpack dev server.
The command below starts a special webpack dev server after a client
build.
make client-dev-server
GALAXY_CLIENT_DEV_SERVER=1 sh run.sh
Note that this only works under uWSGI due to the extra internal routing rules
employed. If you're using the older Paste-based galaxy webserver you'll need
to swap it over to take advantage of this functionality.
This will start up an extra client development server running on port 8081.
Open your browser to http://localhost:8081 (instead of the default 8080 that
Galaxy would run on), and you should see Galaxy like normal. Except now, when
you change client code it'll automatically rebuild *and* reload the relevant
portion of the application for you. Note that unlike previous versions of this
functionality, it is no longer required to use uWSGI for this. Lastly, if you
are running Galaxy at a location other than the default, you can specify a
different proxy target (in this example, port 8000) using the GALAXY_URL
environment variable:
GALAXY_URL="http://localhost:8000" make client-dev-server
Changing Styles/CSS
===================
Sometimes you want to run your local UI against a remote Galaxy server. This is also possible, if you enable `CHANGE_ORIGIN` flag
CHANGE_ORIGIN=true GALAXY_URL="https://usegalaxy.org/" make client-dev-server
## Changing Styles/CSS
Galaxy uses Sass for its styling, which is a superset of CSS that compiles down
to regular CSS. Most Galaxy styling source (.scss) files are kept in
`client/galaxy/style/scss. There are additionally style blocks alongside some
Vue components -- styles that are particular to that individual component and
do not apply site-wide.
to regular CSS. Most Galaxy styling source (.scss) files are kept in
`client/src/style/scss. There are additionally style blocks alongside some Vue
components -- styles that are particular to that individual component and do
not apply site-wide.
On build, the compiled css bundle is served at `/static/style/base.css`.
As mentioned above, `make client` will rebuild styles, as a part of the webpack
build. For iterative development, "Watch Mode" rebuilds as described above do
build. For iterative development, "Watch Mode" rebuilds as described above do
include style changes.
# Client-Side Unit Testing
## Client-Side Unit Testing
Galaxy's client is undergoing an extensive refactoring and modernizing process.
As part of this initiative, we would like to request that all new client-side
code submissions come with accompanying javascript unit-tests for the
developer-facing API of your new code.
## Testing Technologies
### Testing Technologies
[Galaxy uses Mocha](https://mochajs.org/) for its client-side unit testing
framework with [Chai as its assertion library](https://www.chaijs.com/) and
[karma as a test runner](https://karma-runner.github.io/latest/index.html).
The karma configs are contained in the client/karma folder. Unit tests are run
using Chrome headless by default.
[Galaxy uses Jest](https://jestjs.io/) for its client-side unit testing
framework.
For testing Vue components, we use the [Vue testing
utils](https://vue-test-utils.vuejs.org/) to mount individual components in a
test bed and check them for rendered features.
test bed and check them for rendered features. Please use jest-based mocking
for isolating test functionality.
We use the [babel plugin
Rewire](https://github.com/speedskater/babel-plugin-rewire) to mock imported
ES6 dependencies during unit-testing. [Sinon](https://sinonjs.org/) is also
available for more robust stubbing, mocking and spying utilities.
A set of older qUnit tests also exist which will be phased-out as the code they
support is replaced with modern component-based implementations. In the
meantime, we still run the qunit tests in sequence.
A set of older qUnit tests also exist which will likely be phased-out as the
code they support is replaced with modern component-based implementations. In
the meantime, karma runs both the mocha and qunit tests in sequence.
### Running the tests
#### At Build-Time
## Running the tests
### At Build-Time
To simply run all the javascript unit tests, you can use make from the root
directory. This is what happens during a complete client build.
make client-test
### During Development
#### During Development
During client-side development, it is more convenient to have granular testing
options. The various testing scripts are defined inside package.json within the
client folder, and are called either with `yarn` as demonstrated in the
client folder, and are called with `yarn` as demonstrated in the
following commands.
#### Run all tests (mocha and qunit):
This is what CI is going to run, and also what 'make client-test' invokes,
executing all the client tests:
yarn run test
#### Watch and rerun all client-side unit-tests every time a source file changes:
You can also bypass qunit and single-run all of the jest tests like so:
yarn run test-watch
yarn run jest
#### Run only specified test files when a source file changes:
Or, if you really want to run just the qunit tests:
yarn run test-watch watch-only="Tags/*.test.js"
yarn run qunit
(The above watch-only parameter will be mapped to the following glob expression "**/Tags/*.test.js")
##### Watch and rerun jest unit tests every time a source file changes
#### Run qunit legacy tests
This is incredibly handy, and there are a host of options in the interactive
terminal this starts for executing Jest tests.
yarn run test-qunit
yarn run jest-watch
##### Run only specified test files when a source file changes
## Writing a test file
yarn run jest-watch MyModule
The karma configs are setup to look at any file ending in "*.test.js". Please
place your test files inside client/galaxy/scripts folders right next to
whatever files that they are testing.
yarn run jest-watch Dialog
```javascript
// yourtestfile.test.js
import { things } from "./yourtestfile.js";
describe("some module you wrote", () => {
let transientVariables, serviceInstances, testData;
beforeEach(() => {
// setup your code (if necessary)
})
afterEach(() => {
// teardown your code (so it doesn't ruin the next test)
})
it("should do something or other", () => {
assert(somethingThatShouldTrue, "explain what went wrong");
expect(something).to.eq(true);
})
})
```
## Testing ~~Suggestions~~ Obligations
### Clearly document the intent of your test
Please remember that these tests are not *for* you. They're for the people who
come after you. It will be a lot easier to modify, repair and upgrade your code
if they can figure out what you were originally hoping to accomplish.
Add a couple of comments. Use variable names that mean something. Use the
assertion failure description parameters when possible. Nobody's code is as
self-documenting as they believe it to be.
```javascript
// NOT AWESOME
// this test forces the next victim to have to
// read every single line of source code you wrote
it("should work", async () => {
let thing = await svc.loadHistories();
assert(thing);
})
// BETTER
// With this test, you can just read at the errors on the mocha
// test output to have a pretty good idea of what went sour.
it("should have resolved to an array of integer IDs", async () => {
let historyIds = await historyService.loadHistories();
assert(historyIds, "History service should have had a result");
assert(historyIds instanceof Array, "History results should have been an array");
assert(historyIds.length == 4, "History call should have returned 4 ids");
})
```
### Only test the public API that you define (carefully!)
Internal implementations come and go with library upgrades and new tech. But
the point of the unit test is to make sure your units work as designed....
which means you need to... you know... design your code to work in units.
Separate your concerns and identify the developer-facing methods and functions
you expect them to use. Test THOSE. Everything else should probably be
considered an implementation detail.
Assume nobody cares *how* your code works, we just need to know that the public
API you designed *does* work. If performance problems or new tech necessitate a
re-write, these tests become a guide for the next implementation.
### Wrap native browser resources in a function so they can be easily mocked
If your javascript needs to talk to the window object, or navigator, etc. wrap
that in a function call so that it can be easily mocked during testing.
```javascript
// myModule.js
// ... other code
export function redirectTo(url) {
window.location = url;
}
// myModule.test.js
import { __RewireAPI__ as myModuleRewire} from "./myModule";
function fakeRedirect(url) {
console.log(`I would have gone to: ${url}`);
}
describe("some module", () => {
beforeEach(() => {
myModuleRewire.__Rewire__("redirectTo", fakeRedirect);
})
// ....
})
```
### Implement logic in pure functions when possible
The more of your logic that is written in deterministic functions (i.e. no
side-effects, same inputs always result in same outputs) the easier it is to
test. Just load up the functions and supply suitable test inputs.
There is almost definitely no such thing as a well-written 1000 line function.
Most of whatever happened in that thing was probably deterministic and can be
broken up into easily testable chunks.
## Specific test scenarios & examples
[Mocking an imported dependency](https://github.com/galaxyproject/galaxy/blob/dev/client/galaxy/scripts/components/Tags/tagService.test.js)
[Testing async operations](https://github.com/galaxyproject/galaxy/blob/dev/client/galaxy/scripts/components/Tags/tagService.test.js)
[Testing a Vue component for expected rendering output](https://github.com/galaxyproject/galaxy/blob/dev/client/galaxy/scripts/components/Tags/StatelessTags.test.js)
[Firing an event against a shallow mounted vue component](https://github.com/galaxyproject/galaxy/blob/dev/client/galaxy/scripts/components/Tags/StatelessTags.test.js)
## The dirty secret about testing
It's good to have tests, but testing code isn't really about testing at all,
it's actually about software design.
Maintainable software is testable software. If you can run a unit test on your
code, then that means you must have necessarily separated your code into
testable units and you will have almost definitely written better, more
modular, more easily manipulated code, and nobody will ever contemplate using
git-blame to figure out what went wrong.
Probably.
yarn run jest-watch workflow/run
+8
View File
@@ -0,0 +1,8 @@
{
"presets": ["@babel/preset-env"],
"env": {
"test": {
"plugins": ["@babel/plugin-transform-runtime"]
}
}
}
-22
View File
@@ -1,22 +0,0 @@
{
"name": "galaxy-client-libs",
"version": "0.0.0",
"description": "External client-side libraries used by Galaxy",
"keywords": [
"galaxy",
"galaxyproject"
],
"homepage": "usegalaxy.org",
"dependencies": {
"farbtastic": "~2.0.0-alpha.1",
"jquery-form": "~3.46.0",
"jquery-autocomplete": "git://github.com/dyve/jquery-autocomplete",
"select2": "~3.5.2",
"jStorage": "~0.4.12",
"dynatree": "~1.2.5",
"wymeditor": "~1.0.0-rc.1",
"jstree": "~3.0.9",
"jquery-ui": "git://github.com/jquery/jquery-ui.git#~1.11.2",
"threedubmedia.jquery.event": "*"
}
}
+73
View File
@@ -0,0 +1,73 @@
Without a doubt. The most problematic part of the old client is the way every important piece of
information was hung on a global variable whose initialization is completely unregulated.
### Don't directly reference window.Galaxy in Vue components
Components take props. Please pass in any values you might need from window.Galaxy as props and
avoid referencing global Galaxy inside your components. I've even created basic providers which give
you access to the Galaxy.config, current user, and current user histories. Please use them to
retrieve your values, and bypass importing Galaxy altogether.
#### Sometimes you still need to update Vue from backbone as the legacy environment changes
There are definitely use-cases where the Backbone models update over time and we need to update some
value inside Vue. Instead of importing backbone models directly into Vue components, try building a
backbone event listener that updates some relevant Vuex store.
* [Keeping Vuex in Sync with
Galaxy](https://github.com/galaxyproject/galaxy/blob/dev/client/src/store/syncVuexToGalaxy.js)
These issues should disappear over time as the all of the old client is rebuilt in the new
ecosystem.
## Mount Functions
In what most people think of as a "standard" Vue application there would be only one place that Vue
is mounted to the HTML environment, and that would be in a main.j or an app.js. Most modern
single-page applications only have one starting point like that.
However, we are incrementally replacing old Backbone views, so in its current state, Galaxy may have
several mounting functions for various components depending on where that component is intended to
fit into the existing Backbone layouts.
### Using the standard mount to pass in Galaxy variables as props
A standard mount function has been provided in src/utils. This mount function accepts a component
definition, and then allows you to start up your Vue component with our standard load-out of plugins
including localization, Vuex, and a couple other utilities. This is the preferred way to mount your
component inside the old Backbone layout until the application is fully converted.
```js static
// src/mvc/OldBackboneView.js
import { getGalaxyInstance } from "app";
import MyComponent from "components/MyComponent";
import { mountVueComponent } from "utils/mountVueComponent";
const OldBackboneView = {
someInitMethodYouMake() {
const Galaxy = getGalaxyInstance();
const mounter = mountVueComponent(MyComponent);
// pass in required props
const props = {
// Something peeled off the global galaxy
somePropVal: Galaxy.someDealie,
// ...or the current history
name: Galaxy.currentHistory.name,
// or maybe from the backbone model for this view
shoeSize: this.model.shoeSize
};
// VM is a Vue instance.
// this.$el is some jquery selection, first item is the actual DOM object
const container = this.$el[0];
const vm = mounter(props, container);
}
}
```
+18
View File
@@ -0,0 +1,18 @@
Did you know, jQuery is old enough to drive? It's old enough to get a driver's license. jQuery is a
tool that was built to deal with inconsistencies in browsers that NO LONGER EXIST. In a couple
years, jQuery will be voting, drinking, and capable of being tried as an adult.
If you think you need jQuery, you are mistaken. Please seek help from somebody in the wg-ui-ux
workgroup. There is nothing jQuery can provide you that isn't already part of vanilla javascript or
a standard well-tested 3rd party modern npm module.
But that's not even the main problem. jQuery injects global initializations into every page on the
site whether you want it or not. jQuery leverages an outdated initialization paradigm which is
hugely problematic when it comes to unit testing and module building.
One of our most important goals in redesigning Galaxy is the complete elimination of this library
from our source, along with all its invasive plugins.
### References
* [You Don't Need jQuery](https://github.com/nefe/You-Dont-Need-jQuery)
* [document.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
+164
View File
@@ -0,0 +1,164 @@
We are using components in two very distinct ways. The first, "normal", kind of component will
probably look familiar to anybody whis is already passingly familiar with Vue. Here the relevant
information comes in as properties, any internal variables get defined in "data", changes go out as
events.
### Composition Example
```html static
<!-- Use of a renderless component with a display component -->
<DoodadProvider v-slot="{ doodad, saveDoodad }">
<DoodadEditor :doodad="doodad" @update:doodad="saveDoodad" />
</DoodadProvider>
```
In this example, we've created a component whose job is to deal with loading and updating the doodad
object. Notice that there is no markup inside the DoodadProvider other than the explicit renderless
component we previously made, but you are free to putput whatever you want in there, accessing the
doodad and saveDoddad properties as desired, as well as any other local data with the only
restriction that Vue needs a single root element in which to render.
## The Renderer
```html static
<!-- DoodadEditor.vue, a simple "rendering" component -->
<template>
<AutoComplete
:options="options"
:value="doodad.category"
@select="saveCategory"
/>
</template>
<script>
export default {
props: {
doodad: { type: Object, required: true },
options: { type: Array, required: true },
},
methods: {
saveCategory(newCategory) {
this.$emit('update:doodad', { ...this.doodad, category: newCategory });
}
}
}
</script>
```
This component accepts a mandatory input object (doodad), lets the user play with a category prop,
then emits a fresh object after it's done. So what, what's the big deal? The important part to walk
away from this dumb example is the things that are NOT in this sample component.
This component doesn't save the data. This component doesn't make ajax calls, and this component
doesn't mutate its props. What it does do is to allow the user to edit some object named "doodad"
and emits a new fresh version of that doodad when it's done. (Note also that we are using the
update:propname event syntax whenever possible [to facilitate .sync
binds](https://vuejs.org/v2/guide/components-custom-events.html#sync-Modifier)).
Whatever happens to that new object is somebody else's job. As soon as you tie the data management
to the rendering, the re-usability of your components craters.
## The Provider
As the opposite of the rendering component, a provider or renderless component, is pure logic. It
should not know or care what your renderer is going to do with the data it provides. It is simply a
fancy way of configuring some data manipulation methods. This is one of the many ways of reusing
functionality available in Vue. Some others are [Mixins](https://vuejs.org/v2/guide/mixins.html),
[Provide/Inject](https://v3.vuejs.org/guide/component-provide-inject.html) and (in Vue3) [the
composition API](https://v3.vuejs.org/guide/composition-api-introduction.html).
```js static
// DoodadProvider.js
import { loadDoodad, saveDoodad } from "./someAjaxQueryModule";
export default {
data() {
return {
loaded: false,
doodad: null
}
},
methods: {
async saveDoodad(newVal) {
this.loaded = false;
const newVal = await saveDoodad(newVal);
this.doodad = newVal;
this.loaded = true;
},
async loadDoodad(newVal) {
this.loaded = false;
const newVal = await loadDoodad(newVal);
this.loaded = true;
return newVal;
}
},
async created() {
this.doodad = await loadDoodad();
},
render() {
return return this.$scopedSlots.default({
loaded: this.loaded,
doodad: this.doodad,
saveDoodad: this.saveDoodad
});
}
}
```
Here is an example of a simple possible renderless provider. The important part about this is the
render() function which simply renders [one big default
slot](https://vuejs.org/v2/guide/components-slots.html) and binds some of its own properties to that
slot for use by downstream components.
## Unit Testing a renderless component
Testing of a component like our editor is pretty straightforward and follows the standard Vue
guidelines. If you did a clean-enough job you won't even need to mock anything since all your data
dependencies should be delivered via props.
But it's not so obvious how to unit-test a renderless provider. What do you check for? There's no
mandatory markup, just one big empty slot.
```js static
// Testing a renderless component
import { shallowMount } from "@vue/test-utils";
import { getLocalVue, waitForLifecyleEvent } from "jest/helpers";
import DoodadProvider from "./DoodadProvider";
describe("A renderless component", () => {
const localVue = getLocalVue();
let wrapper;
let slotProps;
beforeEach(async () => {
wrapper = shallowMount(DoodadProvider, {
localVue,
// The mount fn allows you to hook into a slot for this very reason
scopedSlots: {
default(props) {
slotProps = props;
},
},
});
// waits for "updated" Vue lifecycle hook to fire on the renderless
// component. This is often good enough for waiting for
// an initial ajax load to finish, for example
await waitForLifecyleEvent(wrapper.vm, "updated");
})
test("someProp", () => {
const { someProp } = slotProps;
expect(someProp).toExist();
// ...more tests
})
})
```
+71
View File
@@ -0,0 +1,71 @@
### A component is really just a fancy function
I'm not talking about how webpack turns it into a rendering function. That's obvious.
I mean conceptually, props come in (like arguments) and events go out (like the return statements).
A component is a fancy kind of function that can keep emitting results and accept changing inputs
over time. In truth it more closely resembles an Observable, but an observable is ALSO a slightly
fancier kind of function.
If you just think of a component as thing that takes input props and emits output events you're well
on your way to using them well.
The worst components are ones that might as well just be a big single page script. That's zero
percent better than the spaghetti we're working so hard to replace. That's just repackaging all the
problems of the old imperative class-based legacy code.
### Get comfortable with events, limit your dependence on Vuex
New vue programmers are ok at handing props to components, but they rarely use events effectively
(at first). As a result they end up using a lot of global state, a million little data props and
relying on imperfect globalized tools like Vuex or other imported dependencies for every little
variable.
Vuex definitely has its uses, but not as many as you might expect given the way it is
overly-emphasized in common tutorials. It's easy to walk away from an "Intro to Vue" video with the
idea that all data must live in Vuex all the time. That's a really undesirable situation.
Although vuex is a well-organized (many would say over-organized) state machine, it is important
to remember that it is still a kind of global injection and deserves to be considered as such.
* [Should I Store This Data in
Vuex](https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/)
* [Vuex getters are great, but don’t overuse
them](https://codeburst.io/vuex-getters-are-great-but-dont-overuse-them-9c946689b414)
Data persistence should be something that happens near the top of your component tree, not down in
the guts.
Your first thought with a component should be: "How can I offload the handling of the results of
this component to my caller?" The answer is usually going to be events. A component that simply
accepts props and emits events can be re-used in more contexts than one that relies on an external
global state to operate.
#### Read up on .sync and v-model
They're just fancy shorthands for a prop / event handler combination. They are fundamentally no
different from props and events, but the syntax is important to understand.
### Think carefully about what should really be in "data".
Most of good component design boils down to answering the following question: What do I want to put
in data, computed, and props?
Data is the place where temp data goes that is not sensible to persist in Vuex or other
application-wide global state, usually because its use is very specific to the operation of this
particular component. There really should only be a few variables in data.
#### Break down your own internal dependencies
Most components only need one or two variables in data. If you have a large amount of data
variables, it's worth taking a little time to stop and build a mini-dependency tree for yourself.
You will probably find that almost everything can be written in terms of computed transformations on
a small number of data and properties.
Defining your values using computes will lead to a lot less "oh I forgot to update that
variable"-style bugs.
If you have more than a few data variables you probably (a) aren't leveraging computeds and
properties, or (b) are trying to implement too many features for just one component. It is important
separate your concerns in components just like you do in any other kind of programming.
@@ -0,0 +1,76 @@
### ...in VSCode
There's a bunch of "how to debug javascript in vscode" cookbooks out there for the googling, but
most of them don't bother explaining all the gotchas and what each of the cryptic configuration
parameters actually does.
I've gone ahead and annotated all the options, hopefully this will save some time, at least until VS
code updates its test extensions again.
#### To debug a single Jest test:
1. Open a jest test (a file that ends with *.test.js)
1. Make sure the test file is selected, especially if you have multiple files open. This process
will fail confusingly and without obvious error if you have not launched the debugger with the
actual Jest test file selected, and it's easy to accidentally click into another file if you've
got a dozen open.
1. Place a breakpoint in the margin of the file. You can place breakpoints anywhere in your source,
but you must launch the debugger while the jest file is selected because that is where jest and
webpack will start compiling. Alternatively, you can manually override the selected file in the
configuration definition, like if you're testing the same file over and over again and don't want
to worry about selecting it.
1. Update your .vscode/launch.json file to include the following launch configuration. If you don't
have a .vscode folder, you can just make one, but my experience is this all works better if you
have explicitly saved your VSCode project into a workspace rather than just using "code ." from a
terminal. Doing so will have initialized the .vscode folder already.
1. Click on the "Run and Debug" tab from the vscode icons on the left and choose the sample launch
configuration (defined below) from the dropdown "run and debug". Or just hit F5.
1. Wait a bit, for webpack to compile everything, eventually you should be able to hover over
variables near your breakpoint and see their values in the "Variables" section of the Run and
Debug pane.
```json
// sample launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"name": "debug selected jest test",
"request": "launch",
// launches version of jest from inside the node_modules
// this means you need to have run yarn first
"program": "${workspaceFolder}/client/node_modules/jest/bin/jest",
"args": [
// Alias -i.
// Normally jest opens up a bunch of workers to run all your tests faster
// but we don't want that right now.
"--runInBand",
// finds jest config
"--config",
"${workspaceFolder}/client/tests/jest/jest.config.js",
// This is how vscode references the currently selected file
"${file}"
],
"cwd": "${workspaceFolder}/client",
// opens jest output in integrated terminal
"console": "integratedTerminal",
// allows you to place breakpoints right in vscode's gutter
"disableOptimisticBPs": true,
},
]
}
```
+20
View File
@@ -0,0 +1,20 @@
[Galaxy uses Jest](https://jestjs.io/) for its client-side unit testing
framework.
For testing Vue components, we use the [Vue testing
utils](https://vue-test-utils.vuejs.org/) to mount individual components in a
test bed and check them for rendered features. Please use jest-based mocking
for isolating test functionality.
### Specific test scenarios & examples
* [Mocking an imported
dependency](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/tagService.test.js)
* [Testing async
operations](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/tagService.test.js)
* [Testing a Vue component for expected rendering
output](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/StatelessTags.test.js)
* [Firing an event against a shallow mounted vue
component](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/StatelessTags.test.js)
+59
View File
@@ -0,0 +1,59 @@
Part of making good code is making that code easy to test.
### Implement logic in pure functions when possible
The more of your logic that is written in deterministic functions (i.e. no
side-effects, same inputs always result in same outputs) the easier it is to
test. Just load up the functions and supply suitable test inputs.
There is almost definitely no such thing as a well-written 1000 line function.
Most of whatever happened in that thing was probably deterministic and can be
broken up into easily testable chunks.
### Wrap native browser resources in a function so they can be easily mocked
If your javascript needs to talk to the window object, or navigator, etc. wrap
that in a function call so that it can be easily mocked during testing.
#### Your Module
```js static
// myModule.js
// ... other code
export function redirectTo(url) {
window.location = url;
}
export function theThingYouReallyCareAbout() {
.....
redirectTo(somePlace);
....
}
```
#### Your test file
```js static
// myModule.test.js
import { theThingYouReallyCareAbout, redirectTo } from "./myModule";
// calling jest.mock on the appropriate import path wraps the exports and gives
// access to new testing methods like mockImplementation
jest.mock("./myModule");
redirectTo.mockImplementation((url) => {
console.log(`I would have gone to: ${url}`);
});
// You are testing theThingYouReallyCareAbout, but that function needs
// to call a window.relocate, By wrapping redirectTo as a function it was easy to mock
// and avoid errors in your test, because native browser objects do not even exist
// in the unit-testing environment.
describe("theThingYouReallyCareAbout", () => {
it("Performs a redirect when Foo is clicked"){
const result = theThingYouReallyCareAbout(abc123);
expect(result).toBe(1);
}
});
```
+73
View File
@@ -0,0 +1,73 @@
### Clearly document the intent of your test
Please remember that these tests are not _for_ you. They're for the people who
come after you. It will be a lot easier to modify, repair and upgrade your code
if they can figure out what you were originally hoping to accomplish. Try to
use as detailed 'expect' statements as possible -- overuse of 'toBeTruthy()'
for example, can hide the intent of your test.
Add a couple of comments. Use variable names that mean something. Nobody's
code is as self-documenting as they believe it to be.
### Only test the public API that you define
Internal implementations come and go with library upgrades and new tech. But
the point of the unit test is to make sure your units work as designed....
which means you need to... you know... design your code to work in units.
Separate your concerns and identify the developer-facing methods and functions
you expect them to use. Test THOSE. Everything else should probably be
considered an implementation detail.
The other side of the same coin is to test *only* the unit in question. If your
component has a model that uses a service that touches Vuex, which then uses
Axios to fetch some data -- don't test all that at once. Break things apart and
mock functionality to isolate testing to units. End to end testing is a
separate thing that shouldn't be attempted using spec tests in Jest.
Assume nobody cares _how_ your code works, we just need to know that the public
API you designed _does_ work. If performance problems or new tech necessitate a
re-write, these tests become a guide for the next implementation.
### Writing a test file
Jest will try to test any file ending in "\*.test.js". Please place your test
files inside client/src folders right next to whatever files that they are
testing.
Jest has extensive documentation on the expect API, mocking, and more on the
[official docs page](https://jestjs.io/docs/en/getting-started.html), which will
be your best resource here.
```js static
// yourcode.test.js
import { things } from "./yourcode.js";
describe("some module you wrote", () => {
let transientVariables;
let serviceInstances;
let testData;
beforeEach(() => {
// setup your code (if necessary)
});
afterEach(() => {
// teardown your code (so it doesn't ruin the next test)
});
it("should do something or other", () => {
expect(workflowNodeCount()).toBe(5);
});
});
```
### Check out the Jest helper functions
We have created some [common helpers for common testing
scenarios](https://github.com/galaxyproject/galaxy/blob/dev/client/tests/jest/helpers.js).
-3
View File
@@ -1,3 +0,0 @@
export default {
name: "development configs"
}
-3
View File
@@ -1,3 +0,0 @@
export default {
name: "production configs"
}
-4
View File
@@ -1,4 +0,0 @@
export default {
name: "unit testing configs",
testBuild: true,
};
-5
View File
@@ -1,5 +0,0 @@
The \*.md files in this directory are rendered as a style guide generated when
running ```yarn run styleguide```.
For more details see [Vue
Styleguidist](https://github.com/vue-styleguidist/vue-styleguidist).
-379
View File
@@ -1,379 +0,0 @@
## Buttons
Regular buttons
```vue
<div>
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-secondary">Secondary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-info">Info</button>
<button type="button" class="btn btn-warning">Warning</button>
<button type="button" class="btn btn-danger">Danger</button>
<button type="button" class="btn btn-link">Link</button>
</div>
```
Disabled
```vue
<div>
<button type="button" class="btn btn-primary disabled">Primary</button>
<button type="button" class="btn btn-secondary disabled">Secondary</button>
<button type="button" class="btn btn-success disabled">Success</button>
<button type="button" class="btn btn-info disabled">Info</button>
<button type="button" class="btn btn-warning disabled">Warning</button>
<button type="button" class="btn btn-danger disabled">Danger</button>
<button type="button" class="btn btn-link disabled">Link</button>
</div>
```
```vue
<div>
<button type="button" class="btn btn-outline-primary">Primary</button>
<button type="button" class="btn btn-outline-secondary">Secondary</button>
<button type="button" class="btn btn-outline-success">Success</button>
<button type="button" class="btn btn-outline-info">Info</button>
<button type="button" class="btn btn-outline-warning">Warning</button>
<button type="button" class="btn btn-outline-danger">Danger</button>
</div>
```
```vue
<div class="btn-group" role="group" aria-label="Button group with nested dropdown">
<button type="button" class="btn btn-primary">Primary</button>
<div class="btn-group" role="group">
<button id="btnGroupDrop1" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
<a class="dropdown-item" href="javascript:void(0)">Dropdown link</a>
<a class="dropdown-item" href="javascript:void(0)">Dropdown link</a>
</div>
</div>
</div>
```
```vue
<div class="btn-group" role="group" aria-label="Button group with nested dropdown">
<button type="button" class="btn btn-success">Success</button>
<div class="btn-group" role="group">
<button id="btnGroupDrop2" type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu" aria-labelledby="btnGroupDrop2">
<a class="dropdown-item" href="javascript:void(0)">Dropdown link</a>
<a class="dropdown-item" href="javascript:void(0)">Dropdown link</a>
</div>
</div>
</div>
```
```vue
<div class="btn-group" role="group" aria-label="Button group with nested dropdown">
<button type="button" class="btn btn-info">Info</button>
<div class="btn-group" role="group">
<button id="btnGroupDrop3" type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu" aria-labelledby="btnGroupDrop3">
<a class="dropdown-item" href="javascript:void(0)">Dropdown link</a>
<a class="dropdown-item" href="javascript:void(0)">Dropdown link</a>
</div>
</div>
</div>
```
```vue
<div class="btn-group" role="group" aria-label="Button group with nested dropdown">
<button type="button" class="btn btn-danger">Danger</button>
<div class="btn-group" role="group">
<button id="btnGroupDrop4" type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu" aria-labelledby="btnGroupDrop4">
<a class="dropdown-item" href="javascript:void(0)">Dropdown link</a>
<a class="dropdown-item" href="javascript:void(0)">Dropdown link</a>
</div>
</div>
</div>
```
```vue
<div>
<button type="button" class="btn btn-primary btn-lg">Large button</button>
<button type="button" class="btn btn-primary">Default button</button>
<button type="button" class="btn btn-primary btn-sm">Small button</button>
</div>
```
## Alerts
```vue
<div class="alert alert-dismissable alert-warning">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<h4>Warning!</h4>
<p>Best check yo self, you're not looking too good. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, <a href="javascript:void(0)" class="alert-link">vel scelerisque nisl consectetur et</a>.</p>
</div>
```
```vue
<div class="alert alert-dismissable alert-danger">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>Oh snap!</strong> <a href="javascript:void(0)" class="alert-link">Change a few things up</a> and try submitting again.
</div>
```
```vue
<div class="alert alert-dismissable alert-success">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>Well done!</strong> You successfully read <a href="javascript:void(0)" class="alert-link">this important alert message</a>.
</div>
```
```vue
<div class="alert alert-dismissable alert-info">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>Heads up!</strong> This <a href="javascript:void(0)" class="alert-link">alert needs your attention</a>, but it's not super important.
</div>
```
## Badges
```vue
<div>
<span class="badge badge-primary">Primary</span>
<span class="badge badge-secondary">Secondary</span>
<span class="badge badge-success">Success</span>
<span class="badge badge-warning">Warning</span>
<span class="badge badge-danger">Danger</span>
<span class="badge badge-info">Info</span>
</div>
```
```vue
<div class="">
<ul class="nav nav-pills">
<li class="active"><a href="javascript:void(0)">Home <span class="badge">42</span></a></li>
<li><a href="javascript:void(0)">Profile <span class="badge-pill"></span></a></li>
<li><a href="javascript:void(0)">Messages <span class="badge-pill">3</span></a></li>
</ul>
</div>
```
## Tables
```vue
<div class="">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>Column heading</th>
<th>Column heading</th>
<th>Column heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Column content</td>
<td>Column content</td>
<td>Column content</td>
</tr>
<tr>
<td>2</td>
<td>Column content</td>
<td>Column content</td>
<td>Column content</td>
</tr>
<tr>
<td>3</td>
<td>Column content</td>
<td>Column content</td>
<td>Column content</td>
</tr>
<tr class="table-success">
<td>4</td>
<td>Column content</td>
<td>Column content</td>
<td>Column content</td>
</tr>
<tr class="table-danger">
<td>5</td>
<td>Column content</td>
<td>Column content</td>
<td>Column content</td>
</tr>
<tr class="table-warning">
<td>6</td>
<td>Column content</td>
<td>Column content</td>
<td>Column content</td>
</tr>
<tr class="table-active">
<td>7</td>
<td>Column content</td>
<td>Column content</td>
<td>Column content</td>
</tr>
</tbody>
</table>
</div>
```
## Cards
```vue
<div class="row">
<div class="col-lg-4">
<div class="bs-component">
<div class="card text-white bg-primary mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Primary card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card text-white bg-secondary mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Secondary card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card text-white bg-success mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Success card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card text-white bg-danger mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Danger card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card text-white bg-warning mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Warning card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card text-white bg-info mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Info card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card bg-light mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Light card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card text-white bg-dark mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Dark card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="bs-component">
<div class="card border-primary mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Primary card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card border-secondary mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Secondary card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card border-success mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Success card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card border-danger mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Danger card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card border-warning mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Warning card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card border-info mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Info card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card border-light mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Light card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
<div class="card border-dark mb-3" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h4 class="card-title">Dark card title</h4>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="bs-component">
<div class="card mb-3">
<h3 class="card-header">Card header</h3>
<div class="card-body">
<h5 class="card-title">Special title treatment</h5>
<h6 class="card-subtitle text-muted">Support card subtitle</h6>
</div>
<img style="height: 200px; width: 100%; display: block;" src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22318%22%20height%3D%22180%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20318%20180%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_158bd1d28ef%20text%20%7B%20fill%3Argba(255%2C255%2C255%2C.75)%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A16pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_158bd1d28ef%22%3E%3Crect%20width%3D%22318%22%20height%3D%22180%22%20fill%3D%22%23777%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22129.359375%22%20y%3D%2297.35%22%3EImage%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E" alt="Card image">
<div class="card-body">
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Vestibulum at eros</li>
</ul>
<div class="card-body">
<a href="javascript:void(0)" class="card-link">Card link</a>
<a href="javascript:void(0)" class="card-link">Another link</a>
</div>
<div class="card-footer text-muted">
2 days ago
</div>
</div>
<div class="card">
<div class="card-body">
<h4 class="card-title">Card title</h4>
<h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<a href="javascript:void(0)" class="card-link">Card link</a>
<a href="javascript:void(0)" class="card-link">Another link</a>
</div>
</div>
</div>
</div>
</div>
```
-49
View File
@@ -1,49 +0,0 @@
## Buttons
```vue
<button>Just a default button</button>
```
```vue
<a href="javascript:void(0)" class="action-button">An anchor with .action-button</a>
```
All the crazy permutations of menu button...
```vue
<a href="javascript:void(0)" class="menubutton">An anchor with .menu-button</a>
```
```vue
<a href="javascript:void(0)" class="menubutton popup">An anchor with .menu-button.popup</a>
```
```vue
<a href="javascript:void(0)" class="menubutton popup split">
<a class="menubutton-label">An anchor with .menu-button.popup.split</a>
</a>
```
## Radio Buttons
As generated by mvc.ui.ui-options
```vue
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary active">
<input type="radio" name="options" id="option1" autocomplete="off" checked> Active
</label>
<label class="btn btn-secondary">
<input type="radio" name="options" id="option2" autocomplete="off"> Radio
</label>
<label class="btn btn-secondary">
<input type="radio" name="options" id="option3" autocomplete="off"> Radio
</label>
</div>
```
## Pagination
```vue
<ul class="pagination"><li class="page-item disabled"><a class="page-link" href="#page/1"><span class="fa fa-angle-double-left"></span></a></li><li class="page-item disabled"><a class="page-link" href="#page/1">0</a></li><li class="page-item active"><a class="page-link" href="#page/1">1</a></li><li class="page-item"><a class="page-link" href="#page/2">2</a></li><li class="page-item"><a class="page-link" href="#page/4"><span class="fa fa-angle-double-right"></span></a></li></ul>
```
-55
View File
@@ -1,55 +0,0 @@
## Forms
Manually crafted "tool" form class, this is broken in the BS4 branch I think.
```vue
<div class="tool-form">
<form name="foo">
<div class="form-row">
<label>Label Input 1</label>
<input id="input1" type="text" name="input1" size="40" />
</div>
<div class="form-row">
<input type="submit" id="send" name="submit" value="submit" />
</div>
</form>
</div>
```
Portlet variant generated by mvc.form.form-view
```vue
<div class="ui-portlet-limited" id="uid-8">
<div class="portlet-header">
<div class="portlet-operations"></div>
<div class="portlet-title">
<i class="portlet-title-icon fa fa-unlock-alt" style="display: inline;"></i>
<span class="portlet-title-text">Portlet Title</span></div>
</div>
<div class="portlet-content">
<div class="portlet-body">
<div class="ui-message alert alert-info"></div>
<div>
<div class="ui-form-element section-row">
<div class="ui-form-error ui-error"><span class="fa fa-arrow-down"></span><span class="ui-form-error-text"></span></div>
<div class="ui-form-title">
<div class="ui-form-collapsible" style="display: none;">
<i class="ui-form-collapsible-icon"></i>
<span class="ui-form-collapsible-text"></span>
</div>
<span class="ui-form-title-text">Text Field 1</span>
</div>
<div class="ui-form-field">
<input class="ui-input" id="field-uid-4" type="text">
<span class="ui-form-info"></span>
<div class="ui-form-backdrop" style="display: none;"></div>
</div>
<div class="ui-form-preview" style="display: none;"></div>
</div>
<div class="ui-form-element section-row">
<div class="ui-form-error ui-error" style="display: none;"><span class="fa fa-arrow-down"></span><span class="ui-form-error-text"></span></div>
<div class="ui-form-title"><div class="ui-form-collapsible" style="display: none;"><i class="ui-form-collapsible-icon"></i><span class="ui-form-collapsible-text"></span></div><span class="ui-form-title-text" style="display: inline;">Password</span></div>
<div class="ui-form-field">
<input class="ui-input" type="password"><span class="ui-form-info"></span><div class="ui-form-backdrop" style="display: none;"></div></div><div class="ui-form-preview" style="display: none;"></div></div>
<div class="ui-form-element section-row" id="uid-7" style="display: none;"><div class="ui-form-error ui-error" style="display: none;"><span class="fa fa-arrow-down"></span><span class="ui-form-error-text"></span></div><div class="ui-form-title"><div class="ui-form-collapsible" style="display: none;"><i class="ui-form-collapsible-icon"></i><span class="ui-form-collapsible-text"></span></div><span class="ui-form-title-text" style="display: inline;">token</span></div><div class="ui-form-field"><div id="field-uid-7"><div style="display: none;"></div><div></div></div><span class="ui-form-info"></span><div class="ui-form-backdrop" style="display: none;"></div></div><div class="ui-form-preview" style="display: none;"></div></div></div></div><div class="portlet-buttons"><button type="button" class="ui-button-default btn btn-primary ui-clear-float" id="submit" data-original-title="" title=""><i class="icon fa fa-save ui-margin-right"></i><span class="title">Submit</span><div class="progress" style="display: none;"><div class="progress-bar" style="width: 0%;"></div></div></button></div></div><div class="portlet-backdrop"></div></div>
```
-69
View File
@@ -1,69 +0,0 @@
## Masthead
As generated by layout.masthead.js
Default height:
```vue
<nav id="masthead" class="navbar navbar-expand justify-content-center navbar-dark bg-dark">
<a class="navbar-brand">
<img class="navbar-brand-image"/>
<span class="navbar-brand-title">Title</span>
</a>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link">Header 1</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle">Header 2</a>
</li>
<li class="nav-item active">
<a class="nav-link">Active Header</a>
</li>
</ul>
</nav>
```
Override height with "height: 80px;"
```vue
<nav id="masthead" class="navbar navbar-expand justify-content-center navbar-dark bg-dark" style="height: 80px;">
<a class="navbar-brand">
<img class="navbar-brand-image"/>
<span class="navbar-brand-title">Title</span>
</a>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link">Header 1</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle">Header 2</a>
</li>
<li class="nav-item active">
<a class="nav-link">Active Header</a>
</li>
</ul>
</nav>
```
Override height with "height: 4rem;"
```vue
<nav id="masthead" class="navbar navbar-expand justify-content-center navbar-dark bg-dark" style="height: 4rem;">
<a class="navbar-brand">
<img class="navbar-brand-image"/>
<span class="navbar-brand-title">Title</span>
</a>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link">Header 1</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle">Header 2</a>
</li>
<li class="nav-item active">
<a class="nav-link">Active Header</a>
</li>
</ul>
</nav>
```
-19
View File
@@ -1,19 +0,0 @@
## Popup menus
These are the classes for the menu itself, normally floating, so placed inside
a relative element.
```vue
<div style="position: relative; height: 12rem;">
<div class="popmenu-wrapper" style="top: 0;">
<ul class="dropdown-menu">
<li class="head"><a>Heading one</a></li>
<li><a>An item</a></li>
<li><a>Another item</a></li>
<li class="head"><a>Heading two</a></li>
<li><a>Third item</a></li>
<li><a>Last item</a></li>
</ul>
</div>
</div>
```
-33
View File
@@ -1,33 +0,0 @@
### Panel Messages
Messages that appear across the top of the panel view below the masthead.
```vue
<div>
<div v-for="type in ['done', 'info', 'warning', 'error']">
<div v-bind:class="'panel-' + type + '-message'">I'm a panel-{{type}}-message</div>
</div>
</div>
```
### Large Messages
Used for providing feedback inline.
```vue
<div>
<div v-for="type in ['done', 'info', 'warning', 'error']">
<div v-bind:class="type + 'messagelarge'">I'm a {{type}}messagelarge</div>
</div>
</div>
```
### Small Messages
```vue
<div>
<div v-for="type in ['done', 'info', 'warning', 'error']">
<div v-bind:class="type + 'message'">I'm a {{type}}message</div>
</div>
</div>
```
-20
View File
@@ -1,20 +0,0 @@
## Panel (toolMenuContainer)
```vue
<div style="height: 200px;">
<div style="position: absolute; width: 250px; height: 200px; border: dotted gray 1px">
<div class="unified-panel-header">
<div class="unified-panel-header-inner">
Header
</div>
</div>
<div class="unified-panel-body">
<div class="toolMenuContainer">
one<br>
two<br>
three<br>
</div>
</div>
</div>
</div>
```
-14
View File
@@ -1,14 +0,0 @@
## Tables
Tables using the .grid class
```vue
<table class="grid">
<thead class="grid-table-header">
<tr><th>One</th><th>Two</th></tr>
</thead>
<tbody class="grid-table-body">
<tr><td>Value 1</td><td>Value 2</td></tr>
</tbody>
</table>
```
-32
View File
@@ -1,32 +0,0 @@
## Tabs
Tabs as generated by mvc.ui.ui-tabs
```vue
<ul style="display: flex;" class="tab-navigation nav nav-tabs">
<li class="tab-element nav-item" id="tab-attribute" style="display: list-item;" data-original-title="" title="">
<a class="nav-link active" id="tab-title-link-attribute">
<i class="tab-icon fa fa-bars"></i>
<span id="tab-title-text-attribute" class="tab-title-text">Attributes</span>
</a>
</li>
<li class="tab-element nav-item" id="tab-convert" style="display: list-item;" data-original-title="" title="">
<a class="nav-link" id="tab-title-link-convert">
<i class="tab-icon fa fa-gear"></i>
<span id="tab-title-text-convert" class="tab-title-text">Convert</span>
</a>
</li>
<li class="tab-element nav-item" id="tab-datatype" style="display: list-item;" data-original-title="" title="">
<a class="nav-link" id="tab-title-link-datatype">
<i class="tab-icon fa fa-database"></i>
<span id="tab-title-text-datatype" class="tab-title-text">Datatypes</span>
</a>
</li>
<li class="tab-element nav-item" id="tab-permissions" style="display: list-item;" data-original-title="" title="">
<a class="nav-link" id="tab-title-link-permissions">
<i class="tab-icon fa fa-user"></i>
<span id="tab-title-text-permissions" class="tab-title-text">Permissions</span>
</a>
</li>
</ul>
```
-5
View File
@@ -1,5 +0,0 @@
{
"compilerOptions": {
"baseUrl": "./scripts/"
}
}
@@ -1,140 +0,0 @@
<template>
<div>
<b-card class="citation-card" v-if="!simple" header-tag="nav">
<template v-slot:header>
<b-nav card-header tabs>
<b-nav-item
:active="outputFormat === outputFormats.CITATION"
@click="outputFormat = outputFormats.CITATION"
>Citations (APA)</b-nav-item
>
<b-nav-item
:active="outputFormat === outputFormats.BIBTEX"
@click="outputFormat = outputFormats.BIBTEX"
>BibTeX</b-nav-item
>
</b-nav>
</template>
<div v-if="source === 'histories'" class="infomessage">
When writing up your analysis, remember to include all references that should be cited in order to
completely describe your work. Also, please remember to
<a href="https://galaxyproject.org/citing-galaxy">cite Galaxy</a>.
</div>
<div class="citations-formatted">
<template v-for="citation in formattedCitations">
<div :key="citation" class="formatted-reference" v-html="citation"></div>
</template>
</div>
</b-card>
<div v-else-if="formattedCitations.length">
<b-btn v-b-toggle="id" variant="primary">Citations</b-btn>
<b-collapse
:id="id.replace(/ /g, '_')"
class="mt-2"
@show="$emit('show')"
@shown="$emit('shown')"
@hide="$emit('hide')"
@hidden="$emit('hidden')"
>
<b-card>
<template v-for="citation in formattedCitations">
<div :key="citation" class="formatted-reference" v-html="citation"></div>
</template>
</b-card>
</b-collapse>
</div>
</div>
</template>
<script>
import Vue from "vue";
import BootstrapVue from "bootstrap-vue";
import axios from "axios";
import Cite from "citation-js";
import { getAppRoot } from "onload/loadConfig";
Vue.use(BootstrapVue);
const outputFormats = Object.freeze({
CITATION: "bibliography",
BIBTEX: "bibtex",
RAW: "raw",
});
export default {
props: {
source: {
type: String,
required: true,
},
id: {
type: String,
required: true,
},
simple: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
citations: [],
errors: [],
showCollapse: false,
outputFormats,
outputFormat: outputFormats.CITATION,
};
},
computed: {
formattedCitations() {
const processed = [];
if (this.citations.length !== 0) {
for (const c of this.citations) {
let link = "";
if (c.cite.data && c.cite.data[0] && c.cite.data[0].URL) {
link = `&nbsp<a href="${c.cite.data[0].URL}" target="_blank">[Link]</a>`;
}
const formattedCitation = c.cite.format(this.outputFormat, {
format: "html",
template: "apa",
lang: "en-US",
append: link,
});
processed.push(formattedCitation);
}
}
return processed;
},
},
updated() {
this.$nextTick(() => {
this.$emit("rendered");
});
},
created() {
axios
.get(`${getAppRoot()}api/${this.source}/${this.id}/citations`)
.then((response) => {
response.data.forEach((rawCitation) => {
try {
const cite = new Cite(rawCitation.content);
this.citations.push({ raw: rawCitation.content, cite: cite });
} catch (err) {
console.warn(`Error parsing bibtex: ${err}`);
}
});
})
.catch((e) => {
console.error(e);
});
},
};
</script>
<style>
.citation-card .card-header .nav-tabs {
margin-bottom: -0.75rem !important;
}
.formatted-reference {
margin-bottom: 0.5rem;
}
</style>

Some files were not shown because too many files have changed in this diff Show More