+
+
+
+
+ Save
+
+
+
+ Cancel
+
+
+
+
+
+
+
diff --git a/client/src/components/History/Layout.vue b/client/src/components/History/Layout/Layout.vue
similarity index 50%
rename from client/src/components/History/Layout.vue
rename to client/src/components/History/Layout/Layout.vue
index cbcf3e1ee3f..aa7e53e29fd 100644
--- a/client/src/components/History/Layout.vue
+++ b/client/src/components/History/Layout/Layout.vue
@@ -1,47 +1,41 @@
-
-
-
+
+
- Global Nav Default
- Local nav Default
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/client/src/components/History/CopyModal.vue b/client/src/components/History/Modals/CopyModal.vue
similarity index 98%
rename from client/src/components/History/CopyModal.vue
rename to client/src/components/History/Modals/CopyModal.vue
index 5d93707c302..3abd7b3c152 100644
--- a/client/src/components/History/CopyModal.vue
+++ b/client/src/components/History/Modals/CopyModal.vue
@@ -45,7 +45,7 @@
-
-
diff --git a/client/src/components/History/StatusIcon.vue b/client/src/components/History/StatusIcon.vue
deleted file mode 100644
index 82fa5d5b0a1..00000000000
--- a/client/src/components/History/StatusIcon.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-
diff --git a/client/src/components/History/adapters/HistoryPanelProxy.js b/client/src/components/History/adapters/HistoryPanelProxy.js
index 66dc13d49fc..4ebbe3336da 100644
--- a/client/src/components/History/adapters/HistoryPanelProxy.js
+++ b/client/src/components/History/adapters/HistoryPanelProxy.js
@@ -5,8 +5,7 @@
*/
import { mountVueComponent } from "utils/mountVueComponent";
-import CurrentHistoryPanel from "../CurrentHistoryPanel";
-// import { genericProxy } from "utils/proxy";
+import HistoryIndex from "components/History/Index";
// mvc nonsense
import $ from "jquery";
@@ -88,7 +87,7 @@ export const HistoryPanelProxy = Backbone.View.extend({
$("#right").addClass("beta").prepend(this.$el);
const container = this.$el[0];
- const mountHistory = mountVueComponent(CurrentHistoryPanel);
+ const mountHistory = mountVueComponent(HistoryIndex);
mountHistory({}, container);
return this;
diff --git a/client/src/components/History/index.js b/client/src/components/History/index.js
deleted file mode 100644
index 55b124ab919..00000000000
--- a/client/src/components/History/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Right-hand panel
-export { default as HistoryPanel } from "./HistoryPanel";
-export { default as CurrentHistoryPanel } from "./CurrentHistoryPanel";
-
-// Adapter: backbone view that mounts HistoryPanel
-export { default as HistoryPanelProxy } from "./adapters/HistoryPanelProxy";
-
-// rxjs debugging panel
-// import { initSpy } from "utils/observable/rxjsDebugging";
-// initSpy();
diff --git a/client/src/components/History/model/CurveFit.js b/client/src/components/History/model/CurveFit.js
deleted file mode 100644
index 9d863e798d9..00000000000
--- a/client/src/components/History/model/CurveFit.js
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- * Houses linear regression and polynomial fitting methods in the API of
- * a Map. Set values to insert data points, Get other x values to return
- * approximations (or the actual datapoints if they exist)
- */
-
-import { linear, polynomial } from "regression";
-import { map, pipe, filter, windowAhead } from "iter-tools";
-
-class CurveFitInputError extends Error {}
-class CurveFitSampleError extends Error {}
-
-const xAscending = ([xa], [xb]) => xa - xb;
-const isDefined = filter((pt) => pt !== undefined);
-
-export class CurveFit extends Map {
- constructor(data) {
- super(data);
- this._domain = [-Infinity, Infinity];
- this.xPrecision = 0;
- this.yPrecision = 0;
- }
-
- // cast keys and vals as numbers
- set(key, val) {
- const x = this.round(key, this.xPrecision);
- const y = this.round(val, this.yPrecision);
- if (isFinite(x) && isFinite(y) && val !== undefined && val !== null && this.valInDomain(x)) {
- super.set(x, y);
- }
- }
-
- get(key, opts = {}) {
- if (isNaN(key)) {
- const errMsg = "Please provide a numeric input";
- throw new CurveFitInputError(errMsg);
- }
-
- const { interpolate = false, order = 2, precision = this.yPrecision } = opts;
- const x = this.round(key, this.xPrecision);
- const inDomain = this.valInDomain(x);
-
- let result = undefined;
- if (inDomain) {
- if (this.has(x)) {
- result = super.get(x);
- } else {
- const method = interpolate ? this.linearInterpolate : this.curveFit;
- result = method.call(this, x, { order, precision });
- }
- }
-
- return result;
- }
-
- get hasData() {
- return this.size >= 2;
- }
-
- get dataPoints() {
- return Array.from(this.entries()).sort(xAscending);
- }
-
- get domain() {
- return this._domain;
- }
-
- set domain(newDomain) {
- this.pruneDomain(newDomain);
- this._domain = newDomain;
- }
-
- // fancier round function, has precision option so we can round to the
- // nearest indicated power of 10
- round(n, precision) {
- const factor = 10 ** precision;
- return Math.round(+n * factor) / factor;
- }
-
- pruneDomain(domain) {
- const notInDomain = (val) => !this.valInDomain(val, domain);
- const doomed = filter(notInDomain, this.keys());
- for (const x of doomed) {
- this.delete(x);
- }
- }
-
- valInDomain(x, domain = this.domain) {
- const [bottom, top] = domain;
- return x >= bottom && x <= top;
- }
-
- pointInDomain([x], domain = this.domain) {
- return this.valInDomain(x, domain);
- }
-
- curveFit(x, opts = {}) {
- if (this.size < 2) {
- const errMsg = "Need at least 2 points to perform an approximation";
- throw new CurveFitSampleError(errMsg);
- }
- const approxMethod = this.size == 2 ? linear : polynomial;
- const { predict } = approxMethod(this.dataPoints, opts);
- const [, y] = predict(x);
- return y;
- }
-
- // finds closest two data points and does a linear interpolation between
- // them at the provided x value
- linearInterpolate(x, opts = {}) {
- const fn = this.getPointWiseFilter(x);
- const [bookends] = Array.from(fn(this.dataPoints));
- if (bookends && bookends.length) {
- const { predict } = linear(bookends, opts);
- const [, y] = predict(x);
- return y;
- }
- return undefined;
- }
-
- // finds the data points to the left and right of indicated xval
- getPointWiseFilter(x) {
- return pipe(
- windowAhead(2),
- map((w) => Array.from(isDefined(w))),
- filter((pts) => {
- if (pts.length == 2) {
- const [[x1], [x2]] = pts;
- return x > x1 && x < x2;
- }
- return false;
- })
- );
- }
-
- clone() {
- const newFit = new CurveFit();
- newFit.xPrecision = this.xPrecision;
- newFit.yPrecision = this.yPrecision;
- newFit.domain = this.domain;
- for (const [x, y] of this.entries()) {
- newFit.set(x, y);
- }
- return newFit;
- }
-}
diff --git a/client/src/components/History/model/CurveFit.test.js b/client/src/components/History/model/CurveFit.test.js
deleted file mode 100644
index a79bbde6ff6..00000000000
--- a/client/src/components/History/model/CurveFit.test.js
+++ /dev/null
@@ -1,213 +0,0 @@
-import { CurveFit } from "./CurveFit";
-
-describe("CurveFit utility", () => {
- describe("size prop", () => {
- test("should be a map with a size prop", () => {
- const fit = new CurveFit();
- expect(fit.size).toBe(0);
- });
-
- test("can accept new data points", () => {
- const fit = new CurveFit();
- fit.set(0, 0);
- fit.set(100, 100);
- expect(fit.size).toBe(2);
- expect(fit.dataPoints.length).toEqual(2);
- });
-
- test("converts all inputs to numeric values", () => {
- const fit = new CurveFit();
- fit.set("0", 0);
- fit.set("100", "100");
- expect(fit.dataPoints.length).toEqual(2);
- expect(fit.dataPoints).toEqual([
- [0, 0],
- [100, 100],
- ]);
- });
- });
-
- describe("dataPoints prop", () => {
- test("has a data property which is an array of arrays", () => {
- const fit = new CurveFit();
- fit.set(100, 100);
- fit.set(20, 3000);
- fit.set(0, 0);
- expect(fit.dataPoints).toEqual([
- [0, 0],
- [20, 3000],
- [100, 100],
- ]);
- });
- });
-
- describe("xPrecision & yPrecision", () => {
- test("integers (precision = 0)", () => {
- const fit = new CurveFit();
- fit.xPrecision = 0;
- fit.yPrecision = 0;
- fit.set(100.234234, 100.234234);
- fit.set(20.2342342342, 3000.2342342342);
- fit.set(0.000003, 0.000002);
-
- expect(fit.dataPoints).toEqual([
- [0, 0],
- [20, 3000],
- [100, 100],
- ]);
- });
-
- test("positive precision", () => {
- const fit = new CurveFit();
- fit.xPrecision = 1;
- fit.yPrecision = 2;
- fit.set(100.234234, 100.234234);
- fit.set(20.2342342342, 3000.2342342342);
- fit.set(0.000003, 0.000002);
-
- expect(fit.dataPoints).toEqual([
- [0, 0],
- [20.2, 3000.23],
- [100.2, 100.23],
- ]);
- });
-
- test("negative precision", () => {
- const fit = new CurveFit();
- fit.xPrecision = -1;
- fit.yPrecision = -2;
- fit.set(111.234234, 22222.234234);
- fit.set(20.2342342342, 3333.2342342342);
- fit.set(2.11111111, 40.2222222);
-
- expect(fit.dataPoints).toEqual([
- [0, 0],
- [20, 3300],
- [110, 22200],
- ]);
- });
- });
-
- describe("fit a 2 point line", () => {
- // given (0,0), (100,300), expect (50,150)
- test("find the middle of a line when the data set is only 2 points", () => {
- const fit = new CurveFit();
- fit.set(100, 300);
- fit.set(0, 0);
-
- expect(fit.get(0)).toBe(0);
- expect(fit.get(100)).toBe(300);
- expect(fit.get(50)).toBe(150);
- });
- });
-
- describe("fit a point on simple curves", () => {
- test("y = x^2", () => {
- const fit = new CurveFit();
- fit.set(0, 0);
- fit.set(2, 4);
- fit.set(3, 9);
-
- expect(fit.get(4, { order: 2 })).toEqual(16);
- expect(fit.get(4, { order: 3 })).toEqual(16);
- expect(fit.get(4, { order: 4 })).toEqual(16);
- });
-
- test("y = x^3", () => {
- const fit = new CurveFit();
- fit.set(0, 0);
- fit.set(1, 1);
- fit.set(2, 8);
- fit.set(3, 27);
-
- expect(fit.get(4, { order: 3 })).toEqual(64);
- });
-
- test("approximation should be in the ballpark", () => {
- const fit = new CurveFit();
- fit.set(0, 0);
- fit.set(1, 1);
- fit.set(2, 8);
- fit.set(3, 27);
-
- // approximate with only 2 terms, but w know it's really a cubic,
- // should be off but in the ballpark
- const approx = fit.get(4, { order: 2 });
- expect(approx).toBeGreaterThan(Math.pow(3, 3));
- expect(approx).toBeLessThan(Math.pow(5, 3));
- });
- });
-
- describe("domain prop", () => {
- let fit;
- beforeEach(() => {
- fit = new CurveFit();
- fit.domain = [0, 2];
- fit.set(0, 0);
- fit.set(1, 1);
- fit.set(2, 8);
- fit.set(3, 1000000000);
- });
-
- test("resetting domain removes datapoints outside of new domain", () => {
- fit.domain = [0, 1];
- expect(fit.dataPoints).toEqual([
- [0, 0],
- [1, 1],
- ]);
- });
-
- test("can restrict evaluated datapoints based on a set domain of inputs", () => {
- expect(fit.dataPoints).toEqual([
- [0, 0],
- [1, 1],
- [2, 8],
- ]);
- });
-
- test("appoximations will ignore datapoints outside domain", () => {
- expect(fit.get(3, { order: 3 })).toBe(undefined);
- fit.domain = [0, 3];
- expect(fit.get(3, { order: 3 })).toBe(27);
- });
- });
-
- // estimates value by drawing a line between the two closest points and
- // doing a linear approx
- describe("linear pointwise interpolation", () => {
- let fit;
- beforeEach(() => {
- fit = new CurveFit();
- fit.xPrecision = 1;
- fit.domain = [0, 3];
- fit.set(0.0, 0);
- fit.set(1.0, 1);
- fit.set(2.0, 8);
- fit.set(3.0, 32);
- });
-
- test("2.5 -> 20", () => {
- expect(fit.linearInterpolate(2.5)).toEqual(20);
- expect(fit.get(2.5, { interpolate: true })).toEqual(20);
- });
- });
-
- describe("clone", () => {
- let fit;
- beforeEach(() => {
- fit = new CurveFit();
- fit.xPrecision = 1;
- fit.domain = [0, 3];
- fit.set(0.0, 0);
- fit.set(1.0, 1);
- fit.set(2.0, 8);
- });
-
- test("clone, hope for same data", () => {
- const existingData = fit.dataPoints;
- const newMap = fit.clone();
- const cloneData = newMap.dataPoints;
- expect(existingData).toEqual(cloneData);
- });
- });
-});
diff --git a/client/src/components/History/model/Dataset.test.js b/client/src/components/History/model/Dataset.test.js
index 68ab03cc4ab..5a5c7891ef2 100644
--- a/client/src/components/History/model/Dataset.test.js
+++ b/client/src/components/History/model/Dataset.test.js
@@ -1,7 +1,7 @@
import { Content } from "./Content";
import { Dataset } from "./Dataset";
-import raw from "components/providers/History/test/json/Dataset.json";
+import raw from "components/providers/test/json/Dataset.json";
const elementIdentifier = "collection_element1";
diff --git a/client/src/components/History/model/DatasetCollection.test.js b/client/src/components/History/model/DatasetCollection.test.js
index e339c89f52c..e9df257c261 100644
--- a/client/src/components/History/model/DatasetCollection.test.js
+++ b/client/src/components/History/model/DatasetCollection.test.js
@@ -3,15 +3,15 @@ import { DatasetCollection } from "./DatasetCollection";
import { STATES } from "./states";
// test data
-import raw from "components/providers/History/test/json/DatasetCollection.json";
+import raw from "components/providers/test/json/DatasetCollection.json";
// error on load
-import rawError from "components/providers/History/test/json/DatasetCollection.error.json";
+import rawError from "components/providers/test/json/DatasetCollection.error.json";
// mixed bag
-import rawProcessing from "components/providers/History/test/json/DatasetCollection.processing.json";
-import rawHomogeneous from "components/providers/History/test/json/DatasetCollection.homogeneous.json";
-import rawHeterogeneous from "components/providers/History/test/json/DatasetCollection.heterogeneous.json";
+import rawProcessing from "components/providers/test/json/DatasetCollection.processing.json";
+import rawHomogeneous from "components/providers/test/json/DatasetCollection.homogeneous.json";
+import rawHeterogeneous from "components/providers/test/json/DatasetCollection.heterogeneous.json";
describe("DatasetCollection", () => {
const model = new DatasetCollection(raw);
diff --git a/client/src/components/History/model/ScrollPos.js b/client/src/components/History/model/ScrollPos.js
deleted file mode 100644
index dde873dfb64..00000000000
--- a/client/src/components/History/model/ScrollPos.js
+++ /dev/null
@@ -1,16 +0,0 @@
-export class ScrollPos {
- constructor(props = {}) {
- const { cursor = null, key = null } = props;
- this.cursor = key === null && cursor === null ? 0 : cursor;
- this.key = key;
- }
-}
-
-ScrollPos.create = function (props) {
- const o = new ScrollPos(props);
- return Object.freeze(o);
-};
-
-ScrollPos.equals = function (a, b) {
- return a.cursor === b.cursor && a.key === b.key;
-};
diff --git a/client/src/components/providers/History/SearchParams.js b/client/src/components/History/model/SearchParams.js
similarity index 58%
rename from client/src/components/providers/History/SearchParams.js
rename to client/src/components/History/model/SearchParams.js
index 23a85b7dba3..a697423d253 100644
--- a/client/src/components/providers/History/SearchParams.js
+++ b/client/src/components/History/model/SearchParams.js
@@ -1,6 +1,3 @@
-import deepEqual from "deep-equal";
-import { isString } from "underscore";
-
const pairSplitRE = /(\w+=\w+)|(\w+="(\w|\s)+")/g;
const scrubFieldRE = /[^\w]/g;
const scrubQuotesRE = /'|"/g;
@@ -22,17 +19,7 @@ const validTextFields = new Set([
"tags",
]);
-// alias search field to internal field (requestd name: pouch field name)
-const pouchFieldAlias = {
- format: "file_ext",
- database: "genome_build",
- description: "annotation",
- tag: "tags",
- deleted: "isDeleted",
- type: "history_content_type",
-};
-
-// maps user-field -> server querystring field
+// Maps user-field -> server querystring field
// if maps to null, that filter not available on server
const serverFieldAlias = {
tags: "tag",
@@ -40,8 +27,8 @@ const serverFieldAlias = {
genome_build: null,
};
-// Convert actualy boolean into objectively incorrect python value our server accepts
-const dumbBool = (val) => (val ? "True" : "False");
+// Convert boolean into python value as currently expected by the api
+const pythonBool = (val) => (val ? "True" : "False");
export class SearchParams {
constructor(props = {}) {
@@ -51,20 +38,6 @@ export class SearchParams {
Object.assign(this, props);
}
- get pageSize() {
- return SearchParams.pageSize;
- }
-
- clone() {
- return new SearchParams(this);
- }
-
- // need this because of what Vue does to objects to make them reactive
- export() {
- const { filterText, showDeleted, showHidden } = this;
- return { filterText, showDeleted, showHidden };
- }
-
// Filtering, parses single text input into a map of field->value
// in the case of multiples, maps to field -> [value, value]
get textCriteria() {
@@ -107,28 +80,6 @@ export class SearchParams {
return criteria;
}
- // Generates an array of pouchDB selector objects
- // { field: { $operator: value }}
- get pouchFilters() {
- const filters = Array.from(this.criteria)
- // generate multiple objects for duplicated field=val entries
- // these will be AND-ed together in the final pouch selector
- // map userfield to pouchfield, userfield = what the user typed in the box
- // pouchfield = the actual field in the cache
- .map(([userField, val]) => [this.getPouchFieldName(userField), val])
- .map(([pouchField, val]) => {
- const vals = Array.isArray(val) ? val : [val];
- return vals.map((v) => [pouchField, v]);
- })
- .flat()
- .map(([pouchField, val]) => {
- const comparator = isString(val) ? { $regex: new RegExp(val) } : { $eq: val };
- return { [pouchField]: comparator };
- });
-
- return filters;
- }
-
// Creates an object of query criteria for use with the api
get historyContentQueryFields() {
return Array.from(this.criteria)
@@ -152,7 +103,7 @@ export class SearchParams {
// deleted serverField was reserved by pouchDB, needed to rename it to "isDeleted"
case "deleted":
case "visible":
- serverVal = dumbBool(val);
+ serverVal = pythonBool(val);
break;
// no text searching in some fields
@@ -178,14 +129,6 @@ export class SearchParams {
}, {});
}
- // legacy q/qv syntax for content api
- // TODO: Delete when we no longer use q/qv
- get legacyContentQueryString() {
- return Object.entries(this.historyContentQueryFields)
- .map(([f, v]) => `q=${f}&qv=${v}`)
- .join("&");
- }
-
// Standard query string (field=val&field=val...)
get historyContentQueryString() {
return Object.entries(this.historyContentQueryFields)
@@ -193,36 +136,8 @@ export class SearchParams {
.join("&");
}
- // maps friendly user field name to internal data field if necessary
- getPouchFieldName(field) {
- const cleanName = field.replace(scrubFieldRE, "");
- return cleanName in pouchFieldAlias ? pouchFieldAlias[cleanName] : cleanName;
- }
-
getServerFieldName(field) {
const cleanName = field.replace(scrubFieldRE, "");
return cleanName in serverFieldAlias ? serverFieldAlias[cleanName] : cleanName;
}
-
- // output current state to log
- report(label = "params", collapsed = true) {
- const { showDeleted, showHidden, filterText } = this;
- const consoleOpen = collapsed ? console.groupCollapsed : console.group;
- consoleOpen.call(console, label);
- console.log("showDeleted", showDeleted);
- console.log("showHidden", showHidden);
- console.log("filterText", filterText);
- console.groupEnd();
- }
}
-
-// Statics
-
-SearchParams.pageSize = 30;
-
-SearchParams.equals = function (a, b) {
- if (a !== undefined && b !== undefined) {
- return deepEqual(a.export(), b.export());
- }
- return false;
-};
diff --git a/client/src/components/History/model/crud.js b/client/src/components/History/model/crud.js
index f009023f492..abf1db00c8c 100644
--- a/client/src/components/History/model/crud.js
+++ b/client/src/components/History/model/crud.js
@@ -1,38 +1,39 @@
-import { bulkCacheContent } from "components/providers/History/caching";
-import { bulkContentUpdate, getAllContentByFilter } from "./queries";
+import { contentUpdate, getAllContentByFilter } from "./queries";
/**
- * Content crud operations, usually an ajax call + a cache function
+ * Content operations
*/
-export const updateSelectedContent = (updates) => async (history, type_ids) => {
- // single ajax call with wierd syntax because.... reasons
- const changes = await bulkContentUpdate(history, type_ids, updates);
- const cacheResult = await bulkCacheContent(changes, true);
- console.log("cacheResult", changes, cacheResult);
- return cacheResult;
-};
+export async function hideSelectedContent(history, type_ids) {
+ return await contentUpdate(history, type_ids, {
+ visible: false,
+ });
+}
-export const hideSelectedContent = updateSelectedContent({
- visible: false,
-});
+export async function unhideSelectedContent(history, type_ids) {
+ return await contentUpdate(history, type_ids, {
+ visible: true,
+ });
+}
-export const unhideSelectedContent = updateSelectedContent({
- visible: true,
-});
+export async function deleteSelectedContent(history, type_ids) {
+ return await contentUpdate(history, type_ids, {
+ deleted: true,
+ });
+}
-export const deleteSelectedContent = updateSelectedContent({
- deleted: true,
-});
+export async function undeleteSelectedContent(history, type_ids) {
+ return await contentUpdate(history, type_ids, {
+ deleted: false,
+ });
+}
-export const undeleteSelectedContent = updateSelectedContent({
- deleted: false,
-});
-
-export const purgeSelectedContent = updateSelectedContent({
- deleted: true,
- purged: true,
-});
+export async function purgeSelectedContent(history, type_ids) {
+ return await contentUpdate(history, type_ids, {
+ deleted: true,
+ purged: true,
+ });
+}
export async function unhideAllHiddenContent(history) {
const filter = { visible: false };
diff --git a/client/src/components/History/model/index.js b/client/src/components/History/model/index.js
index 6e488a3de07..bc36542a48d 100644
--- a/client/src/components/History/model/index.js
+++ b/client/src/components/History/model/index.js
@@ -4,8 +4,6 @@ export { DatasetCollection } from "./DatasetCollection";
export { JobStateSummary } from "./JobStateSummary";
export { DateStore } from "./DateStore";
export { History } from "./History";
-export { ScrollPos } from "./ScrollPos";
-export { CurveFit } from "./CurveFit";
export { STATES } from "./states";
// crud functions, ajax call + cache
diff --git a/client/src/components/History/model/queries.js b/client/src/components/History/model/queries.js
index ee92eb052dd..953b104214c 100644
--- a/client/src/components/History/model/queries.js
+++ b/client/src/components/History/model/queries.js
@@ -80,9 +80,7 @@ function formData(fields = {}) {
// #region History Queries
-const stdHistoryParams = {
- view: "betawebclient",
-};
+const stdHistoryParams = {};
/**
* Return list of available histories
@@ -274,23 +272,23 @@ export async function updateContentFields(content, newFields = {}) {
}
/**
- * Bulk update endpoint (TODO: rewrite)
+ * Updates history item contents
*
* @param {*} history
* @param {*} type_ids
* @param {*} fields
*/
-export async function bulkContentUpdate(history, type_ids = [], fields = {}) {
+export async function contentUpdate(history, type_ids = [], fields = {}) {
const items = type_ids.map((type_id) => {
const [history_content_type, id] = type_id.split("-");
return { id, type_id, history_content_type };
});
const { id } = history;
- const url = `/histories/${id}/contents?view=betawebclient`;
+ const url = `/histories/${id}/contents`;
const payload = Object.assign({}, fields, { items });
const response = await api.put(url, payload);
- console.log("bulkContentUpdate response", response);
+ console.debug("Submitted request to update selected content.", response);
return doResponse(response);
}
@@ -309,7 +307,7 @@ export async function createDatasetCollection(history, inputs = {}) {
};
const payload = Object.assign({}, defaults, inputs);
- const url = `/histories/${history.id}/contents?view=betawebclient`; // keys=${keys}`;
+ const url = `/histories/${history.id}/contents`;
const response = await api.post(url, payload);
return doResponse(response);
}
diff --git a/client/src/components/History/readme.md b/client/src/components/History/readme.md
deleted file mode 100644
index ed74cef8944..00000000000
--- a/client/src/components/History/readme.md
+++ /dev/null
@@ -1,69 +0,0 @@
-### Beta History Panel Component Tree
-This is not intended to be a complete listing, but a general idea of how the components are intended
-to interact with each other.
-
-```html static
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ()
-
-
-
-
-
-
-
-
-
-
-```
\ No newline at end of file
diff --git a/client/src/components/HistoryExport/ToLink.vue b/client/src/components/HistoryExport/ToLink.vue
index e468c02fc76..041f95effdd 100644
--- a/client/src/components/HistoryExport/ToLink.vue
+++ b/client/src/components/HistoryExport/ToLink.vue
@@ -17,7 +17,11 @@
Link for download ready
- . Use this link to download the archive or import it on another Galaxy server.
+
Use this link to download the archive or import it on another Galaxy server.
+ History archives are removed at regular intervals. For permanent storage download the archive, export
+ to a remote file or import the archive on another Galaxy server.
+
`;
var controlsTemplate = BASE_MVC.wrapTemplate(
[
- '
',
+ '
',
'
',
'
<%- history.name %>
',
"
",
diff --git a/client/src/mvc/rules/rule-definitions.js b/client/src/mvc/rules/rule-definitions.js
index dda2879ed47..0a69c965454 100644
--- a/client/src/mvc/rules/rule-definitions.js
+++ b/client/src/mvc/rules/rule-definitions.js
@@ -904,3 +904,5 @@ export default {
RULES: RULES,
MAPPING_TARGETS: MAPPING_TARGETS,
};
+
+export { RULES, MAPPING_TARGETS };
diff --git a/client/src/mvc/ui/ui-misc.js b/client/src/mvc/ui/ui-misc.js
index d32c0cdc7da..f6a755145ab 100644
--- a/client/src/mvc/ui/ui-misc.js
+++ b/client/src/mvc/ui/ui-misc.js
@@ -86,8 +86,7 @@ export var Input = Backbone.View.extend({
input: "_onchange",
},
value: function (new_val) {
- new_val !== undefined &&
- this.model.set("value", new_val === null || typeof new_val === "string" ? new_val : "");
+ new_val !== undefined && this.model.set("value", typeof new_val === "string" ? new_val : "");
return this.model.get("value");
},
render: function () {
diff --git a/client/src/store/index.js b/client/src/store/index.js
index b6b06ed2963..734d60ffb22 100644
--- a/client/src/store/index.js
+++ b/client/src/store/index.js
@@ -5,7 +5,8 @@
import Vue from "vue";
import Vuex from "vuex";
import createCache from "vuex-cache";
-import createPersistedState from "vuex-persistedstate";
+import VuexPersistence from "vuex-persist";
+import localForage from "localforage";
import config from "config";
@@ -35,19 +36,28 @@ import { syncVuextoGalaxy } from "./syncVuextoGalaxy";
Vue.use(Vuex);
-const panelsState = createPersistedState({
- paths: ["panels"],
+const galaxyStorage = localForage.createInstance({});
+galaxyStorage.config({
+ driver: [localForage.INDEXEDDB, localForage.LOCALSTORAGE],
+ name: "galaxyIndexedDB",
+ version: 1.0,
+ storeName: "galaxyStore",
+});
+
+const panelsPersistence = new VuexPersistence({
+ storage: galaxyStorage,
+ asyncStorage: true,
+ modules: ["panels"],
});
export function createStore() {
const storeConfig = {
- plugins: [createCache(), panelsState],
+ plugins: [createCache(), panelsPersistence.plugin],
modules: {
user: userStore,
config: configStore,
betaHistory: betaHistoryStore,
panels: panelStore,
-
// TODO: please namespace all store modules
gridSearch: gridSearchStore,
histories: historyStore,
diff --git a/client/src/ui/search-input.js b/client/src/ui/search-input.js
index 21c36f4e7dd..06acd5ce212 100644
--- a/client/src/ui/search-input.js
+++ b/client/src/ui/search-input.js
@@ -152,6 +152,18 @@ function searchInput(parentNode, options) {
.popover("show");
});
}
+ // Hack to hide the advanced search popover when clicking outside
+ $("body").on("click", function (e) {
+ $('[data-toggle="advSearchPopover"]').each(function () {
+ if (
+ !$(this).is(e.target) &&
+ $(this).has(e.target).length === 0 &&
+ $(".popover").has(e.target).length === 0
+ ) {
+ $(this).popover("hide");
+ }
+ });
+ });
// .................................................................... loadingIndicator rendering
// a button for clearing the search bar, placed on the right hand side
diff --git a/client/src/utils/observable/index.js b/client/src/utils/observable/index.js
index 8e26b1d8369..430e19c50ff 100644
--- a/client/src/utils/observable/index.js
+++ b/client/src/utils/observable/index.js
@@ -6,7 +6,6 @@ export { firstValueFrom } from "./firstValueFrom";
export { hydrate } from "./hydrate";
export { monitorBackboneModel } from "./monitorBackboneModel";
export { monitorXHR } from "./monitorXHR";
-export { needs } from "./needs";
export { nth } from "./nth";
export { shareButDie } from "./shareButDie";
export { show } from "./show";
diff --git a/client/src/utils/observable/needs.js b/client/src/utils/observable/needs.js
deleted file mode 100644
index 3900a76f90e..00000000000
--- a/client/src/utils/observable/needs.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// I'm actually unclear on why I needed this operator to make pouchdb
-// observables work. This bears further investigation. To my knowledge
-// withLatestFrom() does the same thing as this operator, yet this works and
-// withLatestFrom() doesn't when used with pouchdb observable creation.
-
-import { zip, of, pipe } from "rxjs";
-import { concatMap } from "rxjs/operators";
-
-// prettier-ignore
-export const needs = (dep$) => pipe(
- concatMap((src) => zip(of(src), dep$))
-);
diff --git a/client/src/utils/promise-queue.js b/client/src/utils/promise-queue.js
index 01a7e36db4d..bd6d9bcfff8 100644
--- a/client/src/utils/promise-queue.js
+++ b/client/src/utils/promise-queue.js
@@ -11,7 +11,7 @@ export class LastQueue {
this.pendingPromise = false;
}
- async enqueue(action, ...args) {
+ async enqueue(action, args) {
return new Promise((resolve, reject) => {
this.nextPromise = { action, args, resolve, reject };
this.dequeue();
@@ -24,7 +24,7 @@ export class LastQueue {
this.nextPromise = null;
this.pendingPromise = true;
try {
- const payload = await item.action(...item.args);
+ const payload = await item.action(item.args);
item.resolve(payload);
} catch (e) {
item.reject(e);
diff --git a/client/yarn.lock b/client/yarn.lock
index 34265f13732..a902a914e00 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -1167,10 +1167,10 @@
resolved "https://registry.yarnpkg.com/@fortawesome/vue-fontawesome/-/vue-fontawesome-2.0.6.tgz#87e691ed87f28f4667238573a29743f543a087f6"
integrity sha512-V3vT3flY15AKbUS31aZOP12awQI3aAzkr2B1KnqcHLmwrmy51DW3pwyBczKdypV8QxBZ8U68Hl2XxK2nudTxpg==
-"@galaxyproject/bootstrap-tour@^0.12.1":
- version "0.12.1"
- resolved "https://registry.yarnpkg.com/@galaxyproject/bootstrap-tour/-/bootstrap-tour-0.12.1.tgz#138ab9d993fda658220dea2662fc8e0d0c720577"
- integrity sha512-fnDLpaQx/RFKLL9xtuaVz2RTCo4qQrWYrvFspu6h5ZObgFmTGLTQm3tjiZ0qWBV7Npmwt7X9mc8lUpSCwFPmQw==
+"@galaxyproject/bootstrap-tour@0.12.2":
+ version "0.12.2"
+ resolved "https://registry.yarnpkg.com/@galaxyproject/bootstrap-tour/-/bootstrap-tour-0.12.2.tgz#9277e2dd976b8c778927c70d8180bb7a7090f009"
+ integrity sha512-iGmRhRhoq5vuhgVNig5/Hiu+86emgBDMtB12vo0ApAh9K+1lSnb8NLvfxDOOD7XlO9n4UMFJ5xnjSzeKCnOhqQ==
dependencies:
bootstrap ">=4.0.0-beta"
jquery "^3.0.0"
@@ -2020,42 +2020,6 @@ abbrev@1:
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-abort-controller@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
- integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
- dependencies:
- event-target-shim "^5.0.0"
-
-abstract-leveldown@^6.2.1:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a"
- integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==
- dependencies:
- buffer "^5.5.0"
- immediate "^3.2.3"
- level-concat-iterator "~2.0.0"
- level-supports "~1.0.0"
- xtend "~4.0.0"
-
-abstract-leveldown@~2.7.1:
- version "2.7.2"
- resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93"
- integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==
- dependencies:
- xtend "~4.0.0"
-
-abstract-leveldown@~6.2.1, abstract-leveldown@~6.2.3:
- version "6.2.3"
- resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb"
- integrity sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==
- dependencies:
- buffer "^5.5.0"
- immediate "^3.2.3"
- level-concat-iterator "~2.0.0"
- level-supports "~1.0.0"
- xtend "~4.0.0"
-
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
@@ -2264,11 +2228,6 @@ argparse@^2.0.1:
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
-argsarray@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb"
- integrity sha1-bnIHtOzbObCviDA/pa4ivajfYcs=
-
aria-query@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c"
@@ -2779,11 +2738,6 @@ buffer-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe"
integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74=
-buffer-from@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
- integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-
buffer-from@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0"
@@ -2799,7 +2753,7 @@ buffer-indexof@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==
-buffer@^5.5.0, buffer@^5.6.0, buffer@^5.7.0:
+buffer@^5.7.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
@@ -3045,7 +2999,7 @@ cliui@^7.0.2:
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
-clone-buffer@1.0.0, clone-buffer@^1.0.0:
+clone-buffer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg=
@@ -3603,13 +3557,6 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
dependencies:
ms "2.0.0"
-debug@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
- integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
- dependencies:
- ms "2.0.0"
-
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.2, debug@^4.3.3, debug@~4.3.1, debug@~4.3.2:
version "4.3.3"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
@@ -3718,14 +3665,6 @@ default-resolution@^2.0.0:
resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684"
integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=
-deferred-leveldown@~5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz#27a997ad95408b61161aa69bd489b86c71b78058"
- integrity sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==
- dependencies:
- abstract-leveldown "~6.2.1"
- inherits "^2.0.3"
-
define-lazy-prop@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
@@ -3933,11 +3872,6 @@ dot-case@^3.0.4:
no-case "^3.0.4"
tslib "^2.0.3"
-double-ended-queue@2.1.0-0:
- version "2.1.0-0"
- resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
- integrity sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=
-
duplexify@^3.6.0:
version "3.7.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
@@ -4001,16 +3935,6 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
-encoding-down@^6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b"
- integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==
- dependencies:
- abstract-leveldown "^6.2.1"
- inherits "^2.0.3"
- level-codec "^9.0.0"
- level-errors "^2.0.0"
-
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@@ -4018,13 +3942,6 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
-end-stream@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/end-stream/-/end-stream-0.1.0.tgz#32003f3f438a2b0143168137f8fa6e9866c81ed5"
- integrity sha1-MgA/P0OKKwFDFoE3+PpumGbIHtU=
- dependencies:
- write-stream "~0.4.3"
-
engine.io-parser@~5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.3.tgz#ca1f0d7b11e290b4bfda251803baea765ed89c09"
@@ -4076,13 +3993,6 @@ envinfo@^7.7.3:
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
-errno@~0.1.1:
- version "0.1.8"
- resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
- integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
- dependencies:
- prr "~1.0.1"
-
error-ex@^1.2.0, error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@@ -4371,11 +4281,6 @@ ev-emitter@^1.0.0:
resolved "https://registry.yarnpkg.com/ev-emitter/-/ev-emitter-1.1.1.tgz#8f18b0ce5c76a5d18017f71c0a795c65b9138f2a"
integrity sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q==
-event-target-shim@^5.0.0:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
- integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
-
eventemitter3@^4.0.0:
version "4.0.7"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
@@ -4592,13 +4497,6 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"
-fetch-cookie@0.10.1:
- version "0.10.1"
- resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-0.10.1.tgz#5ea88f3d36950543c87997c27ae2aeafb4b5c4d4"
- integrity sha512-beB+VEd4cNeVG1PY+ee74+PkuCQnik78pgLi5Ah/7qdUfov8IctU0vLUbBT8/10Ma5GMBeI4wtxhGrEfKNYs2g==
- dependencies:
- tough-cookie "^2.3.3 || ^3.0.1 || ^4.0.0"
-
fflate@^0.4.8:
version "0.4.8"
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
@@ -4727,10 +4625,15 @@ flat-cache@^3.0.4:
flatted "^3.1.0"
rimraf "^3.0.2"
-flatted@^3.0.5, flatted@^3.1.0, flatted@^3.2.4:
- version "3.2.5"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
- integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
+flatted@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
+ integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
+
+flatted@^3.1.0, flatted@^3.2.4:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2"
+ integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==
flush-promises@^1.0.2:
version "1.0.2"
@@ -4746,9 +4649,9 @@ flush-write-stream@^1.0.2:
readable-stream "^2.3.6"
follow-redirects@^1.0.0, follow-redirects@^1.14.7:
- version "1.14.7"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
- integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
+ version "1.14.8"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
+ integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
for-in@^1.0.1, for-in@^1.0.2:
version "1.0.2"
@@ -5318,11 +5221,6 @@ imask@^6.4.0:
resolved "https://registry.yarnpkg.com/imask/-/imask-6.4.0.tgz#76e48e6bbf5306f7de058f8a1b90fd2282d446bc"
integrity sha512-iXXgSQA6TJX/RSKivKoTYYoCc4ZmVseMcoDIxMrlW1JPpc8LU9FtCp3f80vg1eUQvmVfEQbh+vybFVDRt2o9TQ==
-immediate@3.3.0, immediate@^3.2.3:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266"
- integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==
-
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
@@ -5380,7 +5278,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -6555,10 +6453,10 @@ karma-webpack@^5.0.0:
minimatch "^3.0.4"
webpack-merge "^4.1.5"
-karma@^6.3.13:
- version "6.3.13"
- resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.13.tgz#ff58622c4f913508dbf86506a5fc614be0e98137"
- integrity sha512-64lbtHBnM/sG7XKvitSQVlImKYNugyjw4K2e8cZYrlZm0GwoWrfsrkzgS/KWY/r3+fVM/2xvT/JN6MyfdttxLw==
+karma@^6.3.16:
+ version "6.3.16"
+ resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.16.tgz#76d1a705fd1cf864ee5ed85270b572641e0958ef"
+ integrity sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ==
dependencies:
body-parser "^1.19.0"
braces "^3.0.2"
@@ -6575,6 +6473,7 @@ karma@^6.3.13:
log4js "^6.4.1"
mime "^2.5.2"
minimatch "^3.0.4"
+ mkdirp "^0.5.5"
qjobs "^1.2.0"
range-parser "^1.2.1"
rimraf "^3.0.2"
@@ -6647,95 +6546,6 @@ lead@^1.0.0:
dependencies:
flush-write-stream "^1.0.2"
-level-codec@9.0.2, level-codec@^9.0.0:
- version "9.0.2"
- resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc"
- integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==
- dependencies:
- buffer "^5.6.0"
-
-level-concat-iterator@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263"
- integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==
-
-level-errors@^2.0.0, level-errors@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8"
- integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==
- dependencies:
- errno "~0.1.1"
-
-level-iterator-stream@~4.0.0:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz#7ceba69b713b0d7e22fcc0d1f128ccdc8a24f79c"
- integrity sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==
- dependencies:
- inherits "^2.0.4"
- readable-stream "^3.4.0"
- xtend "^4.0.2"
-
-level-js@^5.0.0:
- version "5.0.2"
- resolved "https://registry.yarnpkg.com/level-js/-/level-js-5.0.2.tgz#5e280b8f93abd9ef3a305b13faf0b5397c969b55"
- integrity sha512-SnBIDo2pdO5VXh02ZmtAyPP6/+6YTJg2ibLtl9C34pWvmtMEmRTWpra+qO/hifkUtBTOtfx6S9vLDjBsBK4gRg==
- dependencies:
- abstract-leveldown "~6.2.3"
- buffer "^5.5.0"
- inherits "^2.0.3"
- ltgt "^2.1.2"
-
-level-packager@^5.1.0:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939"
- integrity sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==
- dependencies:
- encoding-down "^6.3.0"
- levelup "^4.3.2"
-
-level-supports@~1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d"
- integrity sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==
- dependencies:
- xtend "^4.0.2"
-
-level-write-stream@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/level-write-stream/-/level-write-stream-1.0.0.tgz#3f7fbb679a55137c0feb303dee766e12ee13c1dc"
- integrity sha1-P3+7Z5pVE3wP6zA97nZuEu4Twdw=
- dependencies:
- end-stream "~0.1.0"
-
-level@6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/level/-/level-6.0.1.tgz#dc34c5edb81846a6de5079eac15706334b0d7cd6"
- integrity sha512-psRSqJZCsC/irNhfHzrVZbmPYXDcEYhA5TVNwr+V92jF44rbf86hqGp8fiT702FyiArScYIlPSBTDUASCVNSpw==
- dependencies:
- level-js "^5.0.0"
- level-packager "^5.1.0"
- leveldown "^5.4.0"
-
-leveldown@5.6.0, leveldown@^5.4.0:
- version "5.6.0"
- resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-5.6.0.tgz#16ba937bb2991c6094e13ac5a6898ee66d3eee98"
- integrity sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==
- dependencies:
- abstract-leveldown "~6.2.1"
- napi-macros "~2.0.0"
- node-gyp-build "~4.1.0"
-
-levelup@4.4.0, levelup@^4.3.2:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6"
- integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==
- dependencies:
- deferred-leveldown "~5.3.0"
- level-errors "~2.0.0"
- level-iterator-stream "~4.0.0"
- level-supports "~1.0.0"
- xtend "~4.0.0"
-
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@@ -6839,6 +6649,13 @@ loader-utils@^2.0.0:
emojis-list "^3.0.0"
json5 "^2.1.2"
+localforage@^1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4"
+ integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==
+ dependencies:
+ lie "3.1.1"
+
locate-path@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
@@ -6926,7 +6743,7 @@ lodash.uniqby@4.5.0:
lodash._baseiteratee "~4.7.0"
lodash._baseuniq "~4.6.0"
-lodash@^4.13.1, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.7.0:
+lodash@^4.13.1, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -6971,11 +6788,6 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
-ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5"
- integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=
-
make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
@@ -7058,18 +6870,6 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-memdown@1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215"
- integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=
- dependencies:
- abstract-leveldown "~2.7.1"
- functional-red-black-tree "^1.0.1"
- immediate "^3.2.3"
- inherits "~2.0.1"
- ltgt "~2.2.0"
- safe-buffer "~5.1.1"
-
memfs@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305"
@@ -7272,11 +7072,6 @@ nanomatch@^1.2.9:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-napi-macros@~2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b"
- integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==
-
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -7316,11 +7111,6 @@ no-case@^3.0.4:
lower-case "^2.0.2"
tslib "^2.0.3"
-node-fetch@2.6.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
- integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
-
node-fetch@^2.6.1:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
@@ -7333,11 +7123,6 @@ node-forge@^1.2.0:
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c"
integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==
-node-gyp-build@~4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb"
- integrity sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==
-
node-int64@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
@@ -7447,12 +7232,17 @@ object-hash@^2.2.0:
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
-object-inspect@^1.11.0, object-inspect@^1.9.0:
+object-inspect@^1.11.0:
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
+ integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
+
+object-inspect@^1.9.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0"
integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==
-object-is@^1.0.1, object-is@^1.1.4:
+object-is@^1.0.1:
version "1.1.5"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
@@ -7460,6 +7250,14 @@ object-is@^1.0.1, object-is@^1.1.4:
call-bind "^1.0.2"
define-properties "^1.1.3"
+object-is@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.4.tgz#63d6c83c00a43f4cbc9434eb9757c8a5b8565068"
+ integrity sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==
+ dependencies:
+ call-bind "^1.0.0"
+ define-properties "^1.1.3"
+
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
@@ -8117,213 +7915,6 @@ postcss@^8.3.5, postcss@^8.4.5:
picocolors "^1.0.0"
source-map-js "^1.0.2"
-pouchdb-abstract-mapreduce@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-abstract-mapreduce/-/pouchdb-abstract-mapreduce-7.2.2.tgz#dd1b10a83f8d24361dce9aaaab054614b39f766f"
- integrity sha512-7HWN/2yV2JkwMnGnlp84lGvFtnm0Q55NiBUdbBcaT810+clCGKvhssBCrXnmwShD1SXTwT83aszsgiSfW+SnBA==
- dependencies:
- pouchdb-binary-utils "7.2.2"
- pouchdb-collate "7.2.2"
- pouchdb-collections "7.2.2"
- pouchdb-errors "7.2.2"
- pouchdb-fetch "7.2.2"
- pouchdb-mapreduce-utils "7.2.2"
- pouchdb-md5 "7.2.2"
- pouchdb-utils "7.2.2"
-
-pouchdb-adapter-leveldb-core@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-adapter-leveldb-core/-/pouchdb-adapter-leveldb-core-7.2.2.tgz#e0aa6a476e2607d7ae89f4a803c9fba6e6d05a8a"
- integrity sha512-K9UGf1Ivwe87mjrMqN+1D07tO/DfU7ariVDrGffuOjvl+3BcvUF25IWrxsBObd4iPOYCH7NVQWRpojhBgxULtQ==
- dependencies:
- argsarray "0.0.1"
- buffer-from "1.1.1"
- double-ended-queue "2.1.0-0"
- levelup "4.4.0"
- pouchdb-adapter-utils "7.2.2"
- pouchdb-binary-utils "7.2.2"
- pouchdb-collections "7.2.2"
- pouchdb-errors "7.2.2"
- pouchdb-json "7.2.2"
- pouchdb-md5 "7.2.2"
- pouchdb-merge "7.2.2"
- pouchdb-utils "7.2.2"
- sublevel-pouchdb "7.2.2"
- through2 "3.0.2"
-
-pouchdb-adapter-memory@^7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-adapter-memory/-/pouchdb-adapter-memory-7.2.2.tgz#c0ec2e87928d516ca9d1b5badc7269df6f95e5ea"
- integrity sha512-9o+zdItPEq7rIrxdkUxgsLNaZkDJAGEqqoYgeYdrHidOCZnlhxhX3g7/R/HcpDKC513iEPqJWDJQSfeT6nVKkw==
- dependencies:
- memdown "1.4.1"
- pouchdb-adapter-leveldb-core "7.2.2"
- pouchdb-utils "7.2.2"
-
-pouchdb-adapter-utils@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-adapter-utils/-/pouchdb-adapter-utils-7.2.2.tgz#c64426447d9044ba31517a18500d6d2d28abd47d"
- integrity sha512-2CzZkTyTyHZkr3ePiWFMTiD5+56lnembMjaTl8ohwegM0+hYhRyJux0biAZafVxgIL4gnCUC4w2xf6WVztzKdg==
- dependencies:
- pouchdb-binary-utils "7.2.2"
- pouchdb-collections "7.2.2"
- pouchdb-errors "7.2.2"
- pouchdb-md5 "7.2.2"
- pouchdb-merge "7.2.2"
- pouchdb-utils "7.2.2"
-
-pouchdb-binary-utils@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-binary-utils/-/pouchdb-binary-utils-7.2.2.tgz#0690b348052c543b1e67f032f47092ca82bcb10e"
- integrity sha512-shacxlmyHbUrNfE6FGYpfyAJx7Q0m91lDdEAaPoKZM3SzAmbtB1i+OaDNtYFztXjJl16yeudkDb3xOeokVL3Qw==
- dependencies:
- buffer-from "1.1.1"
-
-pouchdb-collate@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-collate/-/pouchdb-collate-7.2.2.tgz#fc261f5ef837c437e3445fb0abc3f125d982c37c"
- integrity sha512-/SMY9GGasslknivWlCVwXMRMnQ8myKHs4WryQ5535nq1Wj/ehpqWloMwxEQGvZE1Sda3LOm7/5HwLTcB8Our+w==
-
-pouchdb-collections@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-collections/-/pouchdb-collections-7.2.2.tgz#aeed77f33322429e3f59d59ea233b48ff0e68572"
- integrity sha512-6O9zyAYlp3UdtfneiMYuOCWdUCQNo2bgdjvNsMSacQX+3g8WvIoFQCYJjZZCpTttQGb+MHeRMr8m2U95lhJTew==
-
-pouchdb-debug@^7.2.1:
- version "7.2.1"
- resolved "https://registry.yarnpkg.com/pouchdb-debug/-/pouchdb-debug-7.2.1.tgz#f5f869f6113c12ccb97cddf5b0a32b6e0e67e961"
- integrity sha512-eP3ht/AKavLF2RjTzBM6S9gaI2/apcW6xvaKRQhEdOfiANqerFuksFqHCal3aikVQuDO+cB/cw+a4RyJn/glBw==
- dependencies:
- debug "3.1.0"
-
-pouchdb-erase@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/pouchdb-erase/-/pouchdb-erase-1.0.2.tgz#cbdfdddf2dfcd814d0cad72221514237eeb2c151"
- integrity sha1-y9/d3y382BTQytciIVFCN+6ywVE=
- dependencies:
- promise-nodify "^1.0.1"
-
-pouchdb-errors@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-errors/-/pouchdb-errors-7.2.2.tgz#80d811d65c766c9d20b755c6e6cc123f8c3c4792"
- integrity sha512-6GQsiWc+7uPfgEHeavG+7wuzH3JZW29Dnrvz8eVbDFE50kVFxNDVm3EkYHskvo5isG7/IkOx7PV7RPTA3keG3g==
- dependencies:
- inherits "2.0.4"
-
-pouchdb-fetch@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-fetch/-/pouchdb-fetch-7.2.2.tgz#492791236d60c899d7e9973f9aca0d7b9cc02230"
- integrity sha512-lUHmaG6U3zjdMkh8Vob9GvEiRGwJfXKE02aZfjiVQgew+9SLkuOxNw3y2q4d1B6mBd273y1k2Lm0IAziRNxQnA==
- dependencies:
- abort-controller "3.0.0"
- fetch-cookie "0.10.1"
- node-fetch "2.6.0"
-
-pouchdb-find@^7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-find/-/pouchdb-find-7.2.2.tgz#1227afdd761812d508fe0794b3e904518a721089"
- integrity sha512-BmFeFVQ0kHmDehvJxNZl9OmIztCjPlZlVSdpijuFbk/Fi1EFPU1BAv3kLC+6DhZuOqU/BCoaUBY9sn66pPY2ag==
- dependencies:
- pouchdb-abstract-mapreduce "7.2.2"
- pouchdb-collate "7.2.2"
- pouchdb-errors "7.2.2"
- pouchdb-fetch "7.2.2"
- pouchdb-md5 "7.2.2"
- pouchdb-selector-core "7.2.2"
- pouchdb-utils "7.2.2"
-
-pouchdb-json@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-json/-/pouchdb-json-7.2.2.tgz#b939be24b91a7322e9a24b8880a6e21514ec5e1f"
- integrity sha512-3b2S2ynN+aoB7aCNyDZc/4c0IAdx/ir3nsHB+/RrKE9cM3QkQYbnnE3r/RvOD1Xvr6ji/KOCBie+Pz/6sxoaug==
- dependencies:
- vuvuzela "1.0.3"
-
-pouchdb-mapreduce-utils@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-mapreduce-utils/-/pouchdb-mapreduce-utils-7.2.2.tgz#13a46a3cc2a3f3b8e24861da26966904f2963146"
- integrity sha512-rAllb73hIkU8rU2LJNbzlcj91KuulpwQu804/F6xF3fhZKC/4JQMClahk+N/+VATkpmLxp1zWmvmgdlwVU4HtQ==
- dependencies:
- argsarray "0.0.1"
- inherits "2.0.4"
- pouchdb-collections "7.2.2"
- pouchdb-utils "7.2.2"
-
-pouchdb-md5@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-md5/-/pouchdb-md5-7.2.2.tgz#415401acc5a844112d765bd1fb4e5d9f38fb0838"
- integrity sha512-c/RvLp2oSh8PLAWU5vFBnp6ejJABIdKqboZwRRUrWcfGDf+oyX8RgmJFlYlzMMOh4XQLUT1IoaDV8cwlsuryZw==
- dependencies:
- pouchdb-binary-utils "7.2.2"
- spark-md5 "3.0.1"
-
-pouchdb-merge@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-merge/-/pouchdb-merge-7.2.2.tgz#940d85a2b532d6a93a6cab4b250f5648511bcc16"
- integrity sha512-6yzKJfjIchBaS7Tusuk8280WJdESzFfQ0sb4jeMUNnrqs4Cx3b0DIEOYTRRD9EJDM+je7D3AZZ4AT0tFw8gb4A==
-
-pouchdb-promise@^6.1.2:
- version "6.4.3"
- resolved "https://registry.yarnpkg.com/pouchdb-promise/-/pouchdb-promise-6.4.3.tgz#74516f4acf74957b54debd0fb2c0e5b5a68ca7b3"
- integrity sha512-ruJaSFXwzsxRHQfwNHjQfsj58LBOY1RzGzde4PM5CWINZwFjCQAhZwfMrch2o/0oZT6d+Xtt0HTWhq35p3b0qw==
- dependencies:
- lie "3.1.1"
-
-pouchdb-selector-core@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-selector-core/-/pouchdb-selector-core-7.2.2.tgz#264d7436a8c8ac3801f39960e79875ef7f3879a0"
- integrity sha512-XYKCNv9oiNmSXV5+CgR9pkEkTFqxQGWplnVhO3W9P154H08lU0ZoNH02+uf+NjZ2kjse7Q1fxV4r401LEcGMMg==
- dependencies:
- pouchdb-collate "7.2.2"
- pouchdb-utils "7.2.2"
-
-pouchdb-upsert@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/pouchdb-upsert/-/pouchdb-upsert-2.2.0.tgz#42b15e420848f3b294c35060589fdb51cf7f7f5f"
- integrity sha1-QrFeQghI87KUw1BgWJ/bUc9/f18=
- dependencies:
- pouchdb-promise "^6.1.2"
-
-pouchdb-utils@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb-utils/-/pouchdb-utils-7.2.2.tgz#c17c4788f1d052b0daf4ef8797bbc4aaa3945aa4"
- integrity sha512-XmeM5ioB4KCfyB2MGZXu1Bb2xkElNwF1qG+zVFbQsKQij0zvepdOUfGuWvLRHxTOmt4muIuSOmWZObZa3NOgzQ==
- dependencies:
- argsarray "0.0.1"
- clone-buffer "1.0.0"
- immediate "3.3.0"
- inherits "2.0.4"
- pouchdb-collections "7.2.2"
- pouchdb-errors "7.2.2"
- pouchdb-md5 "7.2.2"
- uuid "8.1.0"
-
-pouchdb@^7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-7.2.2.tgz#fcae82862db527e4cf7576ed8549d1384961f364"
- integrity sha512-5gf5nw5XH/2H/DJj8b0YkvG9fhA/4Jt6kL0Y8QjtztVjb1y4J19Rg4rG+fUbXu96gsUrlyIvZ3XfM0b4mogGmw==
- dependencies:
- abort-controller "3.0.0"
- argsarray "0.0.1"
- buffer-from "1.1.1"
- clone-buffer "1.0.0"
- double-ended-queue "2.1.0-0"
- fetch-cookie "0.10.1"
- immediate "3.3.0"
- inherits "2.0.4"
- level "6.0.1"
- level-codec "9.0.2"
- level-write-stream "1.0.0"
- leveldown "5.6.0"
- levelup "4.4.0"
- ltgt "2.2.1"
- node-fetch "2.6.0"
- readable-stream "1.1.14"
- spark-md5 "3.0.1"
- through2 "3.0.2"
- uuid "8.1.0"
- vuvuzela "1.0.3"
-
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -8368,9 +7959,9 @@ pretty@^2.0.0:
js-beautify "^1.6.12"
prismjs@^1.6.0:
- version "1.26.0"
- resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.26.0.tgz#16881b594828bb6b45296083a8cbab46b0accd47"
- integrity sha512-HUoH9C5Z3jKkl3UunCyiD5jwk0+Hz0fIgQ2nbwU2Oo/ceuTAQAg+pPVnfdt2TJWRVLcxKh9iuoYDUSc8clb5UQ==
+ version "1.27.0"
+ resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057"
+ integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==
process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
version "2.0.1"
@@ -8382,11 +7973,6 @@ process@^0.11.10:
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
-promise-nodify@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/promise-nodify/-/promise-nodify-1.0.2.tgz#0d0fb143c33400b0061b47e581257557047d4c5a"
- integrity sha1-DQ+xQ8M0ALAGG0flgSV1VwR9TFo=
-
prompts@^2.0.1, prompts@~2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
@@ -8421,11 +8007,6 @@ proxy-addr@~2.0.7:
forwarded "0.2.0"
ipaddr.js "1.9.1"
-prr@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
- integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
-
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@@ -8556,25 +8137,6 @@ read-pkg@^1.0.0:
normalize-package-data "^2.3.2"
path-type "^1.0.0"
-readable-stream@1.1.14:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
- integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
-
-"readable-stream@2 || 3", readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.5.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
- integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
- dependencies:
- inherits "^2.0.3"
- string_decoder "^1.1.1"
- util-deprecate "^1.0.1"
-
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
@@ -8588,10 +8150,14 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.5, readable
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-readable-stream@~0.0.2:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-0.0.4.tgz#f32d76e3fb863344a548d79923007173665b3b8d"
- integrity sha1-8y124/uGM0SlSNeZIwBxc2ZbO40=
+readable-stream@^3.0.6, readable-stream@^3.5.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
+ integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
readdirp@~3.6.0:
version "3.6.0"
@@ -9139,11 +8705,6 @@ shebang-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-shvl@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/shvl/-/shvl-2.0.3.tgz#eb4bd37644f5684bba1fc52c3010c96fb5e6afd1"
- integrity sha512-V7C6S9Hlol6SzOJPnQ7qzOVEWUQImt3BNmmzh40wObhla3XOYMe4gGiYzLrJd5TFa+cI2f9LKIRJTTKZSTbWgw==
-
side-channel@^1.0.3, side-channel@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
@@ -9330,11 +8891,6 @@ sourcemap-codec@1.4.8:
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
-spark-md5@3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.1.tgz#83a0e255734f2ab4e5c466e5a2cfc9ba2aa2124d"
- integrity sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig==
-
sparkles@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c"
@@ -9540,11 +9096,6 @@ string_decoder@^1.1.1:
dependencies:
safe-buffer "~5.2.0"
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@@ -9620,16 +9171,6 @@ stylehacks@^5.0.2:
browserslist "^4.16.6"
postcss-selector-parser "^6.0.4"
-sublevel-pouchdb@7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/sublevel-pouchdb/-/sublevel-pouchdb-7.2.2.tgz#49e46cd37883bf7ff5006d7c5b9bcc7bcc1f422f"
- integrity sha512-y5uYgwKDgXVyPZceTDGWsSFAhpSddY29l9PJbXqMJLfREdPmQTY8InpatohlEfCXX7s1LGcrfYAhxPFZaJOLnQ==
- dependencies:
- inherits "2.0.4"
- level-codec "9.0.2"
- ltgt "2.2.1"
- readable-stream "1.1.14"
-
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -9782,14 +9323,6 @@ through2-filter@^3.0.0:
through2 "~2.0.0"
xtend "~4.0.0"
-through2@3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4"
- integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==
- dependencies:
- inherits "^2.0.4"
- readable-stream "2 || 3"
-
through2@^2.0.0, through2@^2.0.3, through2@~2.0.0:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -9911,7 +9444,7 @@ toidentifier@1.0.1:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
-"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0:
+tough-cookie@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==
@@ -10150,9 +9683,9 @@ urix@^0.1.0:
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
url-parse@^1.4.3:
- version "1.5.4"
- resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.4.tgz#e4f645a7e2a0852cc8a66b14b292a3e9a11a97fd"
- integrity sha512-ITeAByWWoqutFClc/lRZnFplgXgEZr3WJ6XngMM/N9DMIm4K8zXPCZ1Jdu0rERwO84w1WC5wkle2ubwTA4NTBg==
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
+ integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"
@@ -10191,11 +9724,6 @@ utrie@^1.0.2:
dependencies:
base64-arraybuffer "^1.0.2"
-uuid@8.1.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
- integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==
-
uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
@@ -10387,6 +9915,11 @@ vue-template-es2015-compiler@^1.5.3, vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
+vue-virtual-scroll-list@^2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-2.3.3.tgz#290f0d04be814b93585f2ef232097b671141e5b1"
+ integrity sha512-heuwlZ+lEdcVSp66CpVXnyNdsiHl/XU1cvqJb0yUHGlLv6DGK8OX16FH8I3w/wKNXtHSPF9itdBBGJFrXkyHeg==
+
vue@^2.6.10, vue@^2.6.14:
version "2.6.14"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
@@ -10412,32 +9945,19 @@ vuex-cache@^3.4.0:
resolved "https://registry.yarnpkg.com/vuex-cache/-/vuex-cache-3.4.0.tgz#0aec66b7abb370b1a089f678681af8efe5a9289b"
integrity sha512-C0HJvVTEdjn8gq0EXemcJCBgAyPLnms8VGz/kMakrpaF6XNwkZY5KvySkdBJSY6rp0eTdWMoHPVU2Oq+dK7WEQ==
-vuex-persist@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/vuex-persist/-/vuex-persist-3.1.3.tgz#518c722a2ca3026bcee5732f99d24f75cee0f3b6"
- integrity sha512-QWOpP4SxmJDC5Y1+0+Yl/F4n7z27syd1St/oP+IYCGe0X0GFio0Zan6kngZFufdIhJm+5dFGDo3VG5kdkCGeRQ==
+vuex-persist@2.3:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/vuex-persist/-/vuex-persist-2.3.0.tgz#f3d21b6d631078667d6834f2f74442ee332ac281"
+ integrity sha512-0QPZQYgQ72SbXkdwctXGFQJhlRiySP0z9wHDBTlyHvNy3CneKvgyJ7Lfob8NUiYbaurJepaC+JFynwshp59FGA==
dependencies:
- deepmerge "^4.2.2"
- flatted "^3.0.5"
-
-vuex-persistedstate@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/vuex-persistedstate/-/vuex-persistedstate-4.1.0.tgz#127165f85f5b4534fb3170a5d3a8be9811bd2a53"
- integrity sha512-3SkEj4NqwM69ikJdFVw6gObeB0NHyspRYMYkR/EbhR0hbvAKyR5gksVhtAfY1UYuWUOCCA0QNGwv9pOwdj+XUQ==
- dependencies:
- deepmerge "^4.2.2"
- shvl "^2.0.3"
+ flatted "^2.0.0"
+ lodash "^4.17.19"
vuex@^3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
-vuvuzela@1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b"
- integrity sha1-O+FF5YJxxzylUnndhR8SpoIRSws=
-
w3c-hr-time@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
@@ -10758,13 +10278,6 @@ write-file-atomic@^3.0.0:
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
-write-stream@~0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/write-stream/-/write-stream-0.4.3.tgz#83cc8c0347d0af6057a93862b4e3ae01de5c81c1"
- integrity sha1-g8yMA0fQr2BXqThitOOuAd5cgcE=
- dependencies:
- readable-stream "~0.0.2"
-
ws@^7.4.6:
version "7.5.6"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b"
@@ -10797,7 +10310,7 @@ xmlchars@^2.2.0:
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
-xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1:
+xtend@~4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
diff --git a/config/galaxy.yml.interactivetools b/config/galaxy.yml.interactivetools
index 48909a654c2..bb7f3621fe7 100644
--- a/config/galaxy.yml.interactivetools
+++ b/config/galaxy.yml.interactivetools
@@ -1,54 +1,19 @@
-uwsgi:
-
- http: localhost:8080
-
- threads: 8
-
- http-raw-body: True
-
- offload-threads: 8
-
- master: true
-
- module: galaxy.webapps.galaxy.buildapp:uwsgi_app()
-
- interactivetools_map: database/interactivetools_map.sqlite
- python-raw: scripts/interactivetools/key_type_token_mapping.py
- route-host: ^([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)-([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\.([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\.(interactivetool\.localhost:8080)$ goto:itdomain
- route-run: goto:itdomainend
- route-label: itdomain
- route-host: ^([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)-([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\.([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\.(interactivetool\.localhost:8080)$ rpcvar:TARGET_HOST rtt_key_type_token_mapper_cached $1 $3 $2 $4 $0 5
- route-if-not: empty:${TARGET_HOST} httpdumb:${TARGET_HOST}
- route: .* break:404 Not Found
- route-label: itdomainend
- # Path-based is currently less functional and less tested than domain-based
- route: ^(/interactivetool/access/)([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)/([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)/([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)(()|(/.*)*)$ goto:itpath
- route-run: goto:itpathend
- route-label: itpath
- route: ^/interactivetool/access/([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)/([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)/([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)(()|/.*)$ rpcvar:TARGET_HOST rtt_key_type_token_mapper_cached $2 $1 $3 $4 $0 5
- route-if: empty:${TARGET_HOST} goto:itpathfail
- route: ^/interactivetool/access/([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)/([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)/([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)((()|/.*)*)$ rewrite:$4
- route-if: empty:${PATH_INFO} addvar:PATH_INFO=/
- route-run: seturi:${PATH_INFO}
- route-if-not: empty:${QUERY_STRING} seturi:${PATH_INFO}?${QUERY_STRING}
- route-if-not: empty:${TARGET_HOST} httpdumb:${TARGET_HOST}
- route-label: itpathfail
- route: .* break:404 Not Found
- route-label: itpathend
-
-
+gravity:
+ gx_it_proxy:
+ enable: true
+ proxy_port: 4002
galaxy:
interactivetools_enable: true
# outputs_to_working_directory will provide you with a better level of isolation. It is highly recommended to set
# this parameter with InteractiveTools.
outputs_to_working_directory: true
- interactivetools_prefix: interactivetool
interactivetools_map: database/interactivetools_map.sqlite
- # If you develop InteractiveTools locally and do not have a full FQDN you can
- # use an arbritrary one, e.g. 'my-hostname' here, if you set this hostname in your
- # job_conf.xml as well (see the corresponding comment). If running mac OS X, do not match the
- # "http://host.docker.internal:8080" used at galaxy_infrastructure_url in the galaxy.yml file,
- # and use an arbitrary name here instead.
- # Please make sure that in the local development case you use https://localhost:8080 to access
- # your Galaxy. http://my-hostname:8080 will not work.
- # galaxy_infrastructure_url: http://my-hostname:8080
+ # `galaxy_infrastructure_url` needs to be reachable from IT containers.
+ # For local development you can map arbitrary hostnames. See `job_conf.xml.interactivetools`
+ # for an example.
+ # In the local development case you should use the `http` protocol (e.g http://localhost:8080) to access
+ # your Galaxy, so saving notebooks doesn't fail due to invalid certificates.
+ galaxy_infrastructure_url: http://localhost:8080
+ # Do not set the following 2 options if you are using an upstream proxy server like nginx
+ interactivetools_upstream_proxy: false
+ interactivetools_proxy_host: localhost:4002
diff --git a/config/job_conf.xml.interactivetools b/config/job_conf.xml.interactivetools
index 5daf8f054e5..f422ca36799 100644
--- a/config/job_conf.xml.interactivetools
+++ b/config/job_conf.xml.interactivetools
@@ -6,7 +6,6 @@
-
true
@@ -21,21 +20,16 @@
If you develop interactive tools on your 'localhost' and don't have a proper domain name
you need to tell all Docker containers a hostname where Galaxy is running.
This can be done via the add-host parameter during the `docker run` command.
- 'my-hostname' here is an arbritrary hostname that matches the IP address of your
- Galaxy host. Make sure this hostname ('my-hostname') is also set in your galaxy.yml file, e.g.
- `galaxy_infrastructure_url: http://my-hostname:8080`.
- Note: XML does not allow double hyphens in comments, hence the line below has them escaped as -
+ 'localhost' here is an arbitrary hostname that matches the IP address of your
+ Galaxy host. Make sure this hostname ('localhost') is also set in your galaxy.yml file, e.g.
+ `galaxy_infrastructure_url: http://localhost:8080`.
-->
-
-
+ --add-host localhost:host-gateway
-
docker_dispatch
docker_local
local
-
-
diff --git a/config/plugins/visualizations/jqplot/jqplot_bar/src/script.js b/config/plugins/visualizations/jqplot/jqplot_bar/src/script.js
index 99dbe854806..bec0b8b510a 100644
--- a/config/plugins/visualizations/jqplot/jqplot_bar/src/script.js
+++ b/config/plugins/visualizations/jqplot/jqplot_bar/src/script.js
@@ -3,7 +3,7 @@ import _ from "underscore";
import jqplot from 'jqplot-exported/jqplot';
import { LineRenderer } from 'jqplot-exported/LineRenderer';
import { BarRenderer } from 'jqplot-exported/plugins/BarRenderer';
-import { OHLCRenderer } from 'jqplot-exported/plugins/OHLCRenderer';
+import { OHLCRenderer } from 'jqplot-exported/plugins/OhlcRenderer';
import { EnhancedLegendRenderer } from 'jqplot-exported/plugins/EnhancedLegendRenderer';
import { getDomains, makeCategories, makeTickFormat, makeSeries, mapCategories } from "@galaxyproject/charts/lib/utilities/series";
diff --git a/config/plugins/webhooks/demo/tour_generator/__init__.py b/config/plugins/webhooks/demo/tour_generator/__init__.py
index c132aff0501..098d2cb52f3 100644
--- a/config/plugins/webhooks/demo/tour_generator/__init__.py
+++ b/config/plugins/webhooks/demo/tour_generator/__init__.py
@@ -163,7 +163,7 @@ class TourGenerator:
if name in test_inputs:
hid = self._hids[name]
dataset = self._test.inputs[name][0]
- step["content"] = "Select dataset: {}: {}".format(hid, dataset)
+ step["content"] = f"Select dataset: {hid}: {dataset}"
else:
step["content"] = "Select a dataset"
@@ -192,7 +192,7 @@ class TourGenerator:
if case_id in self._data_inputs.keys():
hid = self._hids[case_id]
dataset = self._test.inputs[tour_id][0]
- step_msg = "Select dataset: %s: %s" % (hid, dataset)
+ step_msg = f"Select dataset: {hid}: {dataset}"
else:
case_params = ", ".join(self._test.inputs[tour_id])
step_msg = "Select parameter(s): " + "%s" % case_params
diff --git a/config/plugins/webhooks/gtn/script.js b/config/plugins/webhooks/gtn/script.js
index bcd2223ee86..b0ea7c9db9b 100644
--- a/config/plugins/webhooks/gtn/script.js
+++ b/config/plugins/webhooks/gtn/script.js
@@ -1,6 +1,8 @@
(function () {
var gtnWebhookLoaded = false;
var lastUpdate = 0;
+ var urlParams = new URLSearchParams(document.location.search);
+ var autoLoadTutorial = urlParams.get('autoload_gtn_tutorial') === null ? "" : urlParams.get('autoload_gtn_tutorial');
function removeOverlay() {
const container = document.getElementById("gtn-container");
@@ -58,7 +60,7 @@
.then((response) => {
if (!response.ok) {
url =
- "https://training.galaxyproject.org/training-material/?utm_source=webhook&utm_medium=noproxy&utm_campaign=gxy";
+ `https://training.galaxyproject.org/training-material/${autoLoadTutorial}?utm_source=webhook&utm_medium=noproxy&utm_campaign=gxy`;
message = `
Click to run unavailable.
@@ -75,7 +77,7 @@
onloadscroll = storedLocation.split(" ")[0];
url = storedLocation.split(" ")[1];
} else {
- url = "/training-material/?utm_source=webhook&utm_medium=proxy&utm_campaign=gxy";
+ url = `/training-material/${autoLoadTutorial}?utm_source=webhook&utm_medium=proxy&utm_campaign=gxy`;
}
message = "";
}
@@ -181,6 +183,9 @@
showOverlay();
}
});
+ if(autoLoadTutorial){
+ clean.click();
+ }
});
// Remove the overlay on escape button click
diff --git a/contrib/galaxy.debian-init b/contrib/galaxy.debian-init
deleted file mode 100644
index 1de8ffc83fb..00000000000
--- a/contrib/galaxy.debian-init
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/bash
-
-# Author: James Casbon, 2009
-
-### BEGIN INIT INFO
-# Provides: galaxy
-# Required-Start: $network $local_fs $mysql
-# Required-Stop:
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Galaxy
-### END INIT INFO
-
-. /lib/lsb/init-functions
-
-USER="galaxy"
-GROUP="nogroup"
-GALAXY_DIR="/home/galaxy/galaxy_dist/"
-# Galaxy releases >= 16.01 installs dependencies by default into a virtualenv in /.venv
-# A simple way to activate this virtualenv is to use the python interpreter in /.venv
-# See https://galaxyproject.org/news/2016-01-galaxy-release/ and
-# https://github.com/galaxyproject/galaxy/blob/dev/doc/source/admin/framework_dependencies.rst
-PYTHON="/home/galaxy/galaxy_dist/.venv/bin/python"
-OPTS="./scripts/paster.py serve --log-file /home/galaxy/galaxy.log config/galaxy.ini"
-PIDFILE="/var/run/galaxy.pid"
-
-case "${1:-''}" in
- 'start')
- log_daemon_msg "Starting Galaxy"
- if start-stop-daemon --chuid $USER --group $GROUP --start --make-pidfile \
- --pidfile $PIDFILE --background --chdir $GALAXY_DIR --exec $PYTHON -- $OPTS; then
- log_end_msg 0
- else
- log_end_msg 1
- fi
-
- ;;
- 'stop')
- log_daemon_msg "Stopping Galaxy"
- if start-stop-daemon --stop --pidfile $PIDFILE; then
- log_end_msg 0
- else
- log_end_msg 1
- fi
- ;;
- 'restart')
- # restart commands here
- $0 stop
- $0 start
-
- ;;
- *) # no parameter specified
- echo "Usage: $SELF start|stop|restart|reload|force-reload|status"
- exit 1
- ;;
-esac
-
-
-
diff --git a/contrib/galaxy.solaris-smf.xml b/contrib/galaxy.solaris-smf.xml
deleted file mode 100644
index c44d73d6e0b..00000000000
--- a/contrib/galaxy.solaris-smf.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Galaxy
-
-
-
-
-
-
-
-
-
-
diff --git a/create_db.sh b/create_db.sh
index 3c34dd6c3e5..690d0c6f8c8 100755
--- a/create_db.sh
+++ b/create_db.sh
@@ -1,5 +1,21 @@
#!/bin/sh
+#######
+# Use this script to verify the state of the Galaxy and Tool Shed Install
+# database(s). If the database does not exist or is empty, it will be created
+# and initialized.
+# (Use create_toolshed_db.sh to create and initialize a new
+# Tool Shed database.)
+#
+# To pass a galaxy config file, use `--galaxy-config`
+#
+# You may also override the galaxy database url and/or the
+# tool shed install database url, as well as the database_template
+# and database_encoding configuration options with env vars:
+# GALAXY_CONFIG_OVERRIDE_DATABASE_CONNECTION=my-db-url ./create_db.sh
+# GALAXY_INSTALL_CONFIG_OVERRIDE_DATABASE_CONNECTION=my-other-db-url ./create_db.sh
+#######
+
cd "$(dirname "$0")"
. ./scripts/common_startup_functions.sh
diff --git a/create_toolshed_db.sh b/create_toolshed_db.sh
new file mode 100755
index 00000000000..3d266a3c767
--- /dev/null
+++ b/create_toolshed_db.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+#######
+# Use this script to verify the state of the Tool Shed database.
+# If the database does not exist or is empty, it will be created
+# and initialized.
+# (For Galaxy and Tool Shed Install databases, use create_db.sh).
+#######
+
+cd "$(dirname "$0")"
+
+. ./scripts/common_startup_functions.sh
+
+setup_python
+
+python ./scripts/create_toolshed_db.py "$@" tool_shed
diff --git a/doc/source/_static/22.01-colour.mp4 b/doc/source/_static/22.01-colour.mp4
new file mode 120000
index 00000000000..ac9575e09d3
--- /dev/null
+++ b/doc/source/_static/22.01-colour.mp4
@@ -0,0 +1 @@
+../releases/images/22.01-colour.mp4
\ No newline at end of file
diff --git a/doc/source/_static/22.01-export.mp4 b/doc/source/_static/22.01-export.mp4
new file mode 120000
index 00000000000..dc52335e958
--- /dev/null
+++ b/doc/source/_static/22.01-export.mp4
@@ -0,0 +1 @@
+../releases/images/22.01-export.mp4
\ No newline at end of file
diff --git a/doc/source/admin/_inc_proxy_serving_root.rst b/doc/source/admin/_inc_proxy_serving_root.rst
index fe043fa0243..605118beef7 100644
--- a/doc/source/admin/_inc_proxy_serving_root.rst
+++ b/doc/source/admin/_inc_proxy_serving_root.rst
@@ -1,10 +1,11 @@
This configuration assumes that Galaxy will be the only site on your server using the given hostname (e.g.
``https://galaxy.example.org``).
-Beginning with Galaxy Release 18.01, the default application server that Galaxy runs under is uWSGI. Because of this,
-the native high performance uWSGI protocol should be used for communication between |PROXY| and Galaxy, rather
-than HTTP. Legacy instructions for proxying via HTTP can be found in the `Galaxy Release 17.09 proxy documentation`_.
+Beginning with Galaxy Release 22.01, the default application server that Galaxy runs under is Gunicorn. Because of this,
+the HTTP protocol should be used for communication between |PROXY| and Galaxy, rather
+than the uWSGI protocol used in earlier version of this document.
+Legacy instructions for proxying via uWSGI can be found in the `Galaxy Release 21.09 proxy documentation`_.
-Since |PROXY| is more efficient than uWSGI at serving static content, it is best to serve it directly, reducing the load
+Since |PROXY| is more efficient than Gunicorn at serving static content, it is best to serve it directly, reducing the load
on the Galaxy process and allowing for more effective compression (if enabled), caching, and pipelining. Directives to
do so are included in the example below.
diff --git a/doc/source/admin/apache.md b/doc/source/admin/apache.md
index 40370e9ceec..f44c0e0352c 100644
--- a/doc/source/admin/apache.md
+++ b/doc/source/admin/apache.md
@@ -27,28 +27,21 @@ also available.
### Apache Proxy Prerequisites
-Currently, the only recommended way to proxy Galaxy with Apache is using `mod_rewrite`, `mod_proxy`, and
-`mod_proxy_uwsgi`. These modules must be enabled in the Apache config. The main proxy directives, `ProxyRequests` and
-`ProxyVia` do **not** need to be enabled.
+Currently, the only recommended way to proxy Galaxy with Apache is using `mod_rewrite` and `mod_proxy`.
+These modules must be enabled in the Apache config. The main proxy directives, `ProxyRequests` and `ProxyVia` do **not** need to be enabled.
Additionally, these directions are written for Apache 2.4+. Apache 2.4 for EL 6 can be obtained from the [CentOS SCLo
-SIG Repo][sclo-sig-repo]. Otherwise, your system package manager's version of Apache should be suitable. On EL, you will
-need to enable the [EPEL][epel] repository to obtain the `mod_proxy_uwsgi` package.
+SIG Repo][sclo-sig-repo]. Otherwise, your system package manager's version of Apache should be suitable.
-```eval_rst
-.. caution:: ``mod_uwsgi`` is not the same module as ``mod_proxy_uwsgi``. The former is the old and unsupported module.
- Be sure that you have installed ``mod_proxy_uwsgi``.
-```
-
-Ensure that the `mod_headers`, `mod_rewrite`, `mod_proxy`, and `mod_proxy_uwsgi` modules are loaded. Although not
+Ensure that the `mod_headers`, `mod_rewrite` and `mod_proxy`modules are loaded. Although not
required, the configuration examples also use `mod_deflate` and `mod_expires` for increased client/server performance,
so these should also be enabled.
On Debian you can install the necessary packages and enable the modules this with the following:
```shell-session
-# apt-get install apache2 libapache2-mod-proxy-uwsgi
-# a2enmod headers deflate expires rewrite proxy proxy_uwsgi
+# apt-get install apache2
+$ a2enmod headers deflate expires rewrite proxy
Enabling module headers.
Considering dependency filter for deflate:
Module filter already enabled
@@ -56,9 +49,6 @@ Module deflate already enabled
Enabling module expires.
Enabling module rewrite.
Enabling module proxy.
-Considering dependency proxy for proxy_uwsgi:
-Module proxy already enabled
-Enabling module proxy_uwsgi.
To activate the new configuration, you need to run:
service apache2 restart
```
@@ -66,12 +56,10 @@ To activate the new configuration, you need to run:
And on EL:
```shell-session
-# yum install httpd mod_proxy_uwsgi
-# echo "LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so" > /etc/httpd/conf.modules.d/10-proxy-uwsgi.conf
+# yum install httpd
```
[sclo-sig-repo]: https://wiki.centos.org/SpecialInterestGroup/SCLo/CollectionsList
-[epel]: https://fedoraproject.org/wiki/EPEL
## Basic configuration
@@ -83,7 +71,7 @@ And on EL:
```eval_rst
.. include:: _inc_proxy_serving_root.rst
-.. _Galaxy Release 17.09 Proxy Documentation: https://docs.galaxyproject.org/en/release_17.09/admin/special_topics/apache.html
+.. _Galaxy Release 21.09 Proxy Documentation: https://docs.galaxyproject.org/en/release_21.09/admin/apache.html
```
The following configuration is not exhaustive, only the portions most relevant to serving Galaxy are shown, these should
@@ -138,15 +126,15 @@ SSLStaplingCache shmcb:/var/run/ocsp(128000)
# Galaxy needs to know that this is https for generating URLs
- RequestHeader set X-URL-SCHEME "%{REQUEST_SCHEME}e"
+ RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
# allow up to 3 minutes for Galaxy to respond to slow requests before timing out
ProxyTimeout 180
- # proxy all requests not matching other locations to uWSGI
- ProxyPass / unix:///srv/galaxy/var/uwsgi.sock|uwsgi://
- # or uWSGI on a TCP socket
- #ProxyPass / uwsgi://127.0.0.1:4001/
+ # proxy all requests not matching other locations to Gunicorn
+ ProxyPass / unix:/srv/galaxy/var/gunicorn.sock|http://localhost/
+ # or Gunicorn on a TCP socket
+ # ProxyPass / http://localhost:4001/
# serve framework static content
RewriteEngine On
@@ -170,8 +158,7 @@ SSLStaplingCache shmcb:/var/run/ocsp(128000)
```
Be sure to set `galaxy_root` to the path to your copy of Galaxy and modify the value of `ProxyPass /` to match your
-uWSGI socket path. With the default configuration, uWSGI will bind to a random TCP socket, so you will need to set it to
-a fixed value as described in the [Scaling and Load Balancing](scaling.md) documentation. If using a UNIX domain
+Gunicorn socket path. With the default configuration, Gunicorn will bind to a TCP socket, so you will need Gunicorn to bind to a UNIX domain socket as described in the [Scaling and Load Balancing](scaling.md) documentation. If using a UNIX domain
socket, be sure to pay particular attention to the discussion of users and permissions.
### Additional Notes
@@ -183,8 +170,8 @@ socket, be sure to pay particular attention to the discussion of users and permi
disable it by commenting its `` or preventing its inclusion (under Debian this is done by removing its
symlink from `/etc/apache2/sites-enabled`).
- `ProxyTimeout` can be adjusted as appropriate for your site. This is the amount of time allowed for communication
- between Apache and uWSGI to block while waiting for a response from Galaxy, and is useful for holding client (browser)
- connections while uWSGI is restarting Galaxy subprocesses or Galaxy is performing a slow operation.
+ between Apache and Gunicorn to block while waiting for a response from Galaxy, and is useful for holding client (browser)
+ connections while Gunicorn is restarting Galaxy subprocesses or Galaxy is performing a slow operation.
- If your Apache server is set up to use `mod_security`, you may need to modify the value of the `SecRequestBodyLimit`.
The default value on some systems will limit uploads to only a few kilobytes.
- Some Galaxy URLs contain encoded slashes (%2F) in the path and Apache will not serve these URLs by default, which is
@@ -195,6 +182,7 @@ socket, be sure to pay particular attention to the discussion of users and permi
- If the proxy works but you are getting 404 errors for Galaxy's static content, be sure that the user that Apache runs
as has access to Galaxy's `static/` directory (and all its parent directories) on the filesystem. You can test this on
the command line with e.g. `sudo -u www-data ls /srv/galaxy/server/static`.
+- A sample configuration for this setup is available [here](https://github.com/mvdbeek/galaxy_doc_examples/tree/main/apache).
### Serving Galaxy at a URL Prefix
@@ -207,10 +195,10 @@ previous section:
```apache
#...
- # proxy all requests not matching other locations to uWSGI
- ProxyPass /galaxy unix:///srv/galaxy/var/uwsgi.sock|uwsgi://
- # or uWSGI on a TCP socket
- #ProxyPass /galaxy uwsgi://127.0.0.1:4001/
+ # proxy all requests not matching other locations to Gunicorn
+ ProxyPass /galaxy unix:///srv/galaxy/var/gunicorn.sock|http://localhost/galaxy
+ # or Gunicorn on a TCP socket
+ #ProxyPass /galaxy http://127.0.0.1:4001/galaxy
# serve framework static content
RewriteEngine On
@@ -221,16 +209,18 @@ previous section:
```
2. The Galaxy application needs to be aware that it is running with a prefix (for generating URLs in dynamic pages).
- This is accomplished by configuring uWSGI (the `uwsgi` section in `config/galaxy.yml`) like so and restarting Galaxy:
+ This is accomplished by configuring Galaxy and Gunicorn in your `config/galaxy.yml` file like so and restarting Galaxy:
```yaml
- uwsgi:
- #...
- socket: /srv/galaxy/var/uwsgi.sock
- mount: /galaxy=galaxy.webapps.galaxy.buildapp:uwsgi_app()
- manage-script-name: true
- # `module` MUST NOT be set when `mount` is in use
- #module: galaxy.webapps.galaxy.buildapp:uwsgi_app()
+ gravity:
+ gunicorn:
+ # ...
+ bind: /srv/galaxy/var/gunicorn.sock
+ gunicorn_extra_args: '--forwarded-allow-ips="*"'
+ galaxy:
+ # ...
+ galaxy_url_prefix: /galaxy
+ # ...
```
```eval_rst
@@ -239,8 +229,7 @@ previous section:
overrides the automatic setting. If you have this option set, unset it unless you know what you're doing.
```
- Be sure to consult the [Scaling and Load Balancing](scaling.md) documentation, other options unrelated to proxying
- should also be set in the `uwsgi` section of the config.
+ Be sure to consult the [Scaling and Load Balancing](scaling.md) documentation.
## Advanced Configuration Topics
diff --git a/doc/source/admin/cluster.md b/doc/source/admin/cluster.md
index 7f9060a9cbe..37c0e047756 100644
--- a/doc/source/admin/cluster.md
+++ b/doc/source/admin/cluster.md
@@ -330,7 +330,12 @@ Since this is a complex problem, the current solution does have some caveats:
### Configuration
-You'll need to ensure that all datasets are stored on the filesystem such that they are readable by all users that will use Galaxy: either made readable by a group, or world-readable. If using a group, set your `umask(1)` to `027` or for world-readable, use `022` Setting the umask assumes your underlying filesystem uses POSIX permissions, so if this is not the case, your environment changes may be different. For uWSGI setups (which are the default since release 19.01) the default umask is set in the `uwsgi:` section of `galaxy.yml` .
+You'll need to ensure that all datasets are stored on the filesystem such that they are readable by all users that will use Galaxy: either made readable by a group, or world-readable. If using a group, set your `umask(1)` to `027` or for world-readable, use `022` Setting the umask assumes your underlying filesystem uses POSIX permissions, so if this is not the case, your environment changes may be different. For [gravity](https://github.com/galaxyproject/gravity/) setups (which are the default since release 22.01) the default umask can be set in the `gravity:` section of `galaxy.yml`:
+
+```yaml
+gravity:
+ umask: 027
+```
The directory specified in `new_file_path` in the Galaxy config should be world-writable, cluster-accessible (via the same absolute path) and have its sticky bit (+t) set. This directory should also be cleaned regularly using a script or program as is appropriate for your site, since temporary files created here may not always be cleaned up under certain conditions.
diff --git a/doc/source/admin/config.rst b/doc/source/admin/config.rst
index dd628554a2d..0d95c1595a2 100644
--- a/doc/source/admin/config.rst
+++ b/doc/source/admin/config.rst
@@ -93,22 +93,17 @@ Configuration Basics
----------------------------
- Edit ``config/galaxy.yml`` (copy it from ``config/galaxy.yml.sample`` if it does not exist) to make configuration
- changes. This is a `uWSGI YAML configuration file`_ and should contain two sections, one named ``uwsgi`` for uWSGI and
- one named ``galaxy`` for Galaxy.
+ changes. This is a `YAML configuration file`_ and should contain one or two sections, one named ``gravity`` for
+ process management via `Gravity`_ (optional) and one named ``galaxy`` for Galaxy (required).
- - The default port for the Galaxy web server is ``8080``, and it only binds to localhost by default. To configure
- uWSGI to listen on all available network addresses, set ``http`` to ``0.0.0.0:`` (e.g. ``http:
- 0.0.0.0:8080``).
- - Some uWSGI options are required for uWSGI to run Galaxy properly and will be added to the ``uwsgi`` command line
- by ``run.sh`` if not specified in ``galaxy.yml``.
- - uWSGI has a `large number of options`_. The Galaxy documentation refers to some of them, but many additional
- advanced deployment scenarios are available.
+ - The `gravity` section contain several important options about how to
+ launch Galaxy web workers and job handlers, which are documented in the
+ :doc:`Scaling and Load Balancing ` documentation.
- Run Galaxy with ``sh run.sh``
- Use a web browser and go to the address you configured in ``galaxy.yml`` (defaults to http://localhost:8080/)
-.. _uWSGI YAML configuration file: https://uwsgi-docs.readthedocs.io/en/latest/Configuration.html
-.. _large number of options: https://uwsgi-docs.readthedocs.io/en/latest/Options.html
+.. _Gravity: https://github.com/galaxyproject/gravity
----------------------------
Configuration Options
diff --git a/doc/source/admin/config_logging.rst b/doc/source/admin/config_logging.rst
index db3e9fc5073..e5730056d33 100644
--- a/doc/source/admin/config_logging.rst
+++ b/doc/source/admin/config_logging.rst
@@ -10,18 +10,9 @@ There are two ways in which you can configure logging for Galaxy servers:
2. More complex configuration using the Python :mod:`logging` module's :func:`logging.config.dictConfig` or :func:`logging.config.fileConfig`.
By default, Galaxy logs all messages to standard output at the ``DEBUG`` logging level, unless the ``--daemon`` argument
-is passed to ``run.sh``, in which case, output is logged to the file ``galaxy.log`` in the current directory.
+is passed to ``run.sh``, in which case, output is logged to a location configured in `gravity`_.
-The way in which you configure logging depends on whether you are using a YAML or INI configuration file, and also on
-whether you are using the uWSGI application server, or Python Paste. Galaxy servers that were created starting with
-Galaxy Release 18.01 or later use a YAML configuration file with uWSGI. Galaxy servers that were created with 17.09 or
-older use an INI configuration file, and Python Paste by default, but they could be configured to run under uWSGI (and
-this was the recommendation for production servers). If you upgrade a pre-18.01 server running under Paste to 18.01 or
-later but do not convert your INI config (``galaxy.ini``) to a YAML config (``galaxy.yml``), the INI config and Paste
-will still be used.
-
-uWSGI, Paste, and related terminology are explained in detail in the :doc:`Scaling and Load Balancing `
-documentation.
+Gravity and related terminology are explained in detail in the :doc:`Scaling and Load Balancing ` documentation.
Basic Configuration
----------------------------
@@ -32,9 +23,8 @@ is controlled by the ``log_level`` configuration option.
If not set, Galaxy logs all messages at the ``DEBUG`` level (versions prior to 18.01 defaulted to ``INFO`` if unset, but
the default config file shipped with ``log_level`` explicitly set to ``DEBUG`` for development purposes).
-Galaxy logs all messages to standard output by default if running in the foreground. If running in the background (``sh
-run.sh --daemon``) under uWSGI, the log is written to ``galaxy.log`` in the current directory. If running in the
-background under Paste, the log is written to ``paster.log``.
+Galaxy logs all messages to standard output by default if running in the foreground. If running in the background, the
+log is written to a location configured in `gravity`_.
**Setting the log level:**
@@ -45,15 +35,6 @@ In ``galaxy.yml``, set ``log_level``:
galaxy:
log_level: LEVEL
-
-Or if using ``galaxy.ini``:
-
-.. code-block:: ini
-
- [app:main]
- log_level = LEVEL
-
-
Where ``LEVEL`` is one of the `logging levels`_ documented in the :mod:`logging` module.
**Logging to a file:**
@@ -68,7 +49,7 @@ To change the log file name or location, use the ``$GALAXY_LOG`` environment var
Advanced Configuration
----------------------------
-For more useful and manageable logging when running Galaxy with forking application stacks (e.g. uWSGI) where multiple
+For more useful and manageable logging when running Galaxy with forking application stacks where multiple
Galaxy server processes are forked after the Galaxy application is loaded, some extensions to standard Python
:mod:`logging` are available in Galaxy:
@@ -98,145 +79,5 @@ The default as of this Galaxy release can be found (in Python syntax) in the
.. include:: config_logging_default_yaml.rst
-Split Logfiles
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Using ``run.sh --daemon`` causes Galaxy to log to ``galaxy.log``, but this is done using uWSGI's logging functionality
-and does not allow for splitting logging in to multiple files. The following logging definition uses the
-``filename_template`` custom handler configuration option to split logging in to the files ``galaxy_web_0.log`` (the
-combined messages of all web workers) and ``galaxy_job-handlers_N.log`` where ``N`` is the instance ID of the server
-process in its pool (aka the mule's position in its farm argument). In addition to the split file logging, the combined
-output is also still logged to standard error.
-
-.. code-block:: yaml
-
- galaxy:
- logging:
- filters:
- stack:
- (): galaxy.web.stack.application_stack_log_filter
- formatters:
- stack:
- (): galaxy.web.stack.application_stack_log_formatter
- handlers:
- console:
- class: logging.StreamHandler
- filters:
- - stack
- formatter: stack
- level: DEBUG
- stream: ext://sys.stderr
- files:
- class: logging.FileHandler
- filters:
- - stack
- level: DEBUG
- formatter: stack
- filename: galaxy_default.log
- filename_template: galaxy_{pool_name}_{server_id}.log
- loggers:
- galaxy:
- handlers:
- - console
- - files
- level: DEBUG
- propagate: 0
- qualname: galaxy
- paste.httpserver.ThreadPool:
- level: WARN
- qualname: paste.httpserver.ThreadPool
- routes.middleware:
- level: WARN
- qualname: routes.middleware
- root:
- handlers:
- - console
- - files
- level: INFO
- version: 1
-
-The list of available template facts for use in ``filename_template`` with all Galaxy application server types, and
-their values under the various possible :doc:`server deployment scenarios ` are given below:
-
-+-------------------+-----------------------------------------------------------------------------------------------+
-| Fact | Application server |
-+-------------------+-------------------------------+-------------------------------+-------------------------------+
-| | Paste/webless | uWSGI web worker | uWSGI mule |
-+===================+===============================+===============================+===============================+
-| ``server_name`` | ``NAME`` for | ``main``, but can be modified with ``server_name`` in |
-| | ``[server:]`` in | ``galaxy.yml`` |
-| | ``galaxy.ini`` | |
-+-------------------+-------------------------------+-------------------------------+-------------------------------+
-| ``server_id`` | ``None`` | 1-indexed worker ID | 1-indexed mule ID |
-+-------------------+-------------------------------+-------------------------------+-------------------------------+
-| ``pool_name`` | ``None`` | ``web`` | Mule's farm name |
-+-------------------+-------------------------------+-------------------------------+-------------------------------+
-| ``instance_id`` | ``None`` | Same as ``server_id`` | Mule's 1-indexed position in |
-| | | | its defined farm |
-+-------------------+-------------------------------+-------------------------------+-------------------------------+
-| ``fqdn`` | Fully-qualified domain name of the host on which Galaxy is running |
-+-------------------+-----------------------------------------------------------------------------------------------+
-| ``hostname`` | "Short" hostname (with domain portion stripped) of the host on which Galaxy is running |
-+-------------------+-----------------------------------------------------------------------------------------------+
-
-The log message format can be customized by adding a (or modifying the default) formatter as in the following (partial)
-example. Note that in addition to the new format, the value of ``formatter`` in the ``console`` handler has been
-changed:
-
-.. code-block:: yaml
-
- galaxy:
- logging:
- formatters:
- myformat:
- (): '%(name)s %(levelname)s %(asctime)s [p:%(process)s,w:%(worker_id)s,m:%(mule_id)s] [%(threadName)s] %(message)s'
- handlers:
- console:
- class: logging.StreamHandler
- filters:
- - stack
- formatter: myformat
- level: DEBUG
- stream: ext://sys.stderr
-
-INI
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-With an INI Galaxy configuration, it is possible to use Python's :func:`logging.config.fileConfig` configuration method for
-advanced logging configuration. For example:
-
-.. code-block:: ini
-
- [loggers]
- keys = root, galaxy
-
- [handlers]
- keys = console
-
- [formatters]
- keys = generic
-
- [logger_root]
- level = INFO
- handlers = console
-
- [logger_galaxy]
- level = DEBUG
- handlers = console
- qualname = galaxy
- propagate = 0
-
- [handler_console]
- class = StreamHandler
- args = (sys.stderr,)
- level = DEBUG
- formatter = generic
-
- [formatter_generic]
- format = %(name)s %(levelname)-5.5s %(asctime)s [p:%(process)s,w:%(worker_id)s,m:%(mule_id)s] [%(threadName)s] %(message)s
-
-While Galaxy's custom log format fields can be used (as seen in the example), the ``filename_template`` handler
-configuration extension is only available in the YAML format configuration file.
-
.. _logging levels: https://docs.python.org/library/logging.html#logging-levels
.. _fileConfig file format: https://docs.python.org/library/logging.config.html#configuration-file-format
diff --git a/doc/source/admin/framework_dependencies.rst b/doc/source/admin/framework_dependencies.rst
index 8d7bb7aafcb..383a6dbc5b9 100644
--- a/doc/source/admin/framework_dependencies.rst
+++ b/doc/source/admin/framework_dependencies.rst
@@ -77,15 +77,6 @@ source code has been cloned to ``/srv/galaxy/server``.
$ . /srv/galaxy/venv/bin/activate
(venv)$
-Next, in ``galaxy.yml``, set the ``virtualenv`` option in the ``uwsgi`` section to point to your new virtualenv:
-
-.. code-block:: yaml
-
- ---
- uwsgi:
- #...
- virtualenv: /srv/galaxy/venv
-
Install dependencies
^^^^^^^^^^^^^^^^^^^^
@@ -190,89 +181,26 @@ Galaxy can create a virtualenv using the adapted virtualenv package. Once a vali
.. _conda-forge: https://conda-forge.org/
.. _Bioconda: https://bioconda.github.io/
-uWSGI
-^^^^^
-
-``run.sh`` should automatically set ``--virtualenv`` on uWSGI's command line. However, you can override this using the
-``virtualenv`` option in the ``uwsgi`` section of ``galaxy.yml`` as described in the `Managing dependencies manually`_
-section.
-
-Unpinned dependencies
-^^^^^^^^^^^^^^^^^^^^^
-
-.. danger::
-
- Unpinned dependencies may be useful for development but should not be used in production. Please do not install
- unpinned dependencies unless you know what you're doing. While the :doc:`Galaxy Committers `
- will do their best to keep dependencies updated, they cannot provide support for problems arising from unpinned
- dependencies.
-
-Galaxy's dependencies can be installed either "pinned" (they will be installed at exact versions specified for your
-Galaxy release) or "unpinned" (the latest versions of all dependencies will be installed unless there are known
-incompatibilities with new versions). By default, the release branches of Galaxy use pinned versions for three reasons:
-
-1. Using pinned versions insures that the prebuilt wheels will be installed, and no
- compilation will be necessary.
-
-2. Galaxy releases are tested with the pinned versions and this allows us to give as much assurance as possible that the
- pinned versions will work with the given Galaxy release (especially as time progresses and newer dependency versions
- are released while the Galaxy release receives fewer updates.
-
-3. Pinning furthers Galaxy's goal of reproducibility as differing dependency versions could result in non-reproducible
- behavior.
-
-If you would like to install unpinned versions of Galaxy's dependencies, install dependencies using the `unpinned
-requirements file`_, and then instruct Galaxy to start without attempting to fetch wheels:
-
-.. code-block:: console
-
- (venv)$ pip install -r lib/galaxy/dependencies/requirements.txt
- (venv)$ deactivate
- $ sh run.sh --no-create-venv --skip-wheels
-
-You may be able to save yourself some compiling by adding the argument ``--index-url
-https://wheels.galaxyproject.org/simple/`` to ``pip install``, but it is possible to install all of Galaxy's
-dependencies directly from PyPI_.
-
-.. _unpinned requirements file: https://github.com/galaxyproject/galaxy/blob/dev/lib/galaxy/dependencies/requirements.txt
-.. _PyPI: https://pypi.org
-
Adding additional Galaxy dependencies
-------------------------------------
-New packages can be added to Galaxy, or the versions of existing packages can be updated, using `pipenv`_ and `Starforge`_, Galaxy's Docker-based build system.
+New packages can be added to Galaxy, or the versions of existing packages can be updated, using `poetry`_ and `Starforge Recipes`_, Galaxy's Docker-based build system.
-The process is still under development and will be streamlined and automated over time. For the time being, please use
-the following process to add new packages and have their wheels built:
+The process is still under development and will be streamlined and automated over time.
+If wheels exist on PyPI for all supported platforms and python versions you can skip
+to step 3 in the process below.
-1. Install `Starforge`_ (e.g. with ``pip install starforge`` or ``python setup.py install`` from the source). You will
- also need to have Docker installed on your system.
+1. Clone https://github.com/galaxyproject/starforge-recipes/ and add or edit the wheel you would like to build under the wheels/ directory.
-2. Obtain `wheels.yml`_ (this file will most likely be moved in to Galaxy in the future) and add/modify the wheel
- definition.
+2. Submit a pull request to `Starforge Recipes`_.
-3. Use ``starforge wheel --wheels-config=wheels.yml `` to build the wheel. If the wheel includes C
- extensions, you will probably want to also use the ``--no-qemu`` flag to prevent Starforge from attempting to build
- on Mac OS X using QEMU/KVM.
+3. Add the new dependency to the `[tool.poetry.dependencies]` (or to `[tool.poetry.dev-dependencies]` if only needed for Galaxy development) section of `pyproject.toml` .
+4. Run `make update-dependencies` to update the requirements file in `lib/galaxy/dependencies`_.
+5. Submit a pull request to Galaxy with your changes.
-4. If the wheel build is successful, submit a pull request to `Starforge`_ with your changes to `wheels.yml`_.
-
-5. A :doc:`Galaxy Committers group ` member will need to trigger an automated build of the wheel
- changes in your pull request. Galaxy's Jenkins_ service will build these changes using Starforge.
-
-6. If the pull request is merged, submit a pull request to Galaxy modifying the files in `lib/galaxy/dependencies`_ as
- appropriate.
-
-You may attempt to skip directly to step 4 and let the Starforge wheel PR builder build your wheels for you. This is
-especially useful if you are simply updating an existing wheel's version. However, if you are adding a new C extension
-wheel that is not simple to build, you may need to go through many iterations of updating the PR and having a
-:doc:`Galaxy Committers group ` member triggering builds
-before wheels are successfully built. You can avoid this cycle by performing
-steps 1-3 locally.
-
-.. _pipenv: https://pipenv.readthedocs.io/
-.. _Starforge: https://github.com/galaxyproject/starforge/
+.. _poetry: https://python-poetry.org/
+.. _Starforge Recipes: https://github.com/galaxyproject/starforge-recipes/
.. _Pull Request #4891: https://github.com/galaxyproject/galaxy/pull/4891
.. _wheels.yml: https://github.com/galaxyproject/starforge/blob/master/wheels/build/wheels.yml
.. _Jenkins: https://jenkins.galaxyproject.org/
diff --git a/doc/source/admin/galaxy_options.rst b/doc/source/admin/galaxy_options.rst
index 1db75278308..6855a2167f0 100644
--- a/doc/source/admin/galaxy_options.rst
+++ b/doc/source/admin/galaxy_options.rst
@@ -1707,13 +1707,25 @@
:Type: bool
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``interactivetools_upstream_proxy``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:Description:
+ Set this to false to redirect users of Interactive tools directly
+ to the Interactive tools proxy. `interactivetools_upstream_proxy`
+ should only be set to false in development.
+:Default: ``true``
+:Type: bool
+
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``interactivetools_proxy_host``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Description:
- Proxy host - assumed to just be hosted on the same hostname and
- port as Galaxy by default.
+ Hostname and port of Interactive tools proxy. It is assumed to be
+ hosted on the same hostname and port as Galaxy by default.
:Default: ``None``
:Type: str
@@ -1918,13 +1930,12 @@
:Description:
URL (with schema http/https) of the Galaxy instance as accessible
- within your local network - if specified used as a default by
- pulsar file staging and Jupyter Docker container for communicating
+ within your local network. This URL is used as a default by pulsar
+ file staging and Interactive Tool containers for communicating
back with Galaxy via the API.
- If you are attempting to set up GIEs on Mac OS X with Docker
- Desktop for Mac and your Galaxy instance runs on port 8080 this
- should be 'http://host.docker.internal:8080'. For more details
- see https://docs.docker.com/docker-for-mac/networking/
+ If you plan to run Interactive Tools make sure the docker
+ container can reach this URL. For more details see
+ `job_conf.xml.interactivetools`.
:Default: ``http://localhost:8080``
:Type: str
@@ -2310,6 +2321,18 @@
:Type: str
+~~~~~~~~~~~~~~~~~~~~
+``tus_upload_store``
+~~~~~~~~~~~~~~~~~~~~
+
+:Description:
+ The upload store is a temporary directory in which files uploaded
+ by the tus middleware or server will be placed. Defaults to
+ new_file_path if not set.
+:Default: ``None``
+:Type: str
+
+
~~~~~~~~~~~~~~~~~~~~~
``chunk_upload_size``
~~~~~~~~~~~~~~~~~~~~~
@@ -2670,11 +2693,6 @@
use_printdebug. It also causes the files used by PBS/SGE
(submission script, output, and error) to remain on disk after the
job is complete.
- In addition, this will set uWSGI's `honour-stdin` option to
- `true`; thus, preventing uWSGI from remapping stdin to `/dev/null`
- and enabling debugging with tools like pdb. To keep uWSGI's
- default setting, set `honor-stdin` to `false` in the `uwsgi`
- section of this configuration file.
:Default: ``false``
:Type: bool
@@ -2721,9 +2739,7 @@
are responsible for preparing/submitting and collecting/finishing
jobs, and which can cause job errors if not shut down cleanly. If
using supervisord, consider also increasing the value of
- `stopwaitsecs`. If using job handler mules, consider also setting
- the `mule-reload-mercy` uWSGI option. See the Galaxy Admin
- Documentation for more.
+ `stopwaitsecs`. See the Galaxy Admin Documentation for more.
:Default: ``30``
:Type: int
@@ -2747,8 +2763,7 @@
:Description:
Control the period (in seconds) between dumps. Use -1 to disable.
Regardless of this setting, if use_heartbeat is enabled, you can
- send a Galaxy process (unless running with uWSGI) SIGUSR1 (`kill
- -USR1`) to force a dump.
+ send a Galaxy process SIGUSR1 (`kill -USR1`) to force a dump.
:Default: ``20``
:Type: int
@@ -4782,4 +4797,14 @@
:Type: str
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``display_builtin_converters``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:Description:
+ Display built-in converters in the tool panel.
+:Default: ``true``
+:Type: bool
+
+
diff --git a/doc/source/admin/index.rst b/doc/source/admin/index.rst
index 79e79215658..efeebf35776 100644
--- a/doc/source/admin/index.rst
+++ b/doc/source/admin/index.rst
@@ -24,3 +24,4 @@ This documentation is in the midst of being ported and unified based on resource
reports
useful_scripts
options
+ migrating_to_gunicorn
diff --git a/doc/source/admin/jobs.md b/doc/source/admin/jobs.md
index 936d7e093e4..513fd5dc713 100644
--- a/doc/source/admin/jobs.md
+++ b/doc/source/admin/jobs.md
@@ -128,25 +128,25 @@ tool using a ```` tag in the ```` section.
### Running jobs on a Kubernetes cluster via Pulsar
-In order to dispatch jobs to a Kubernetes (K8s) cluster via Pulsar,
-Pulsar implements a "two-container" architecture per pod, where
+In order to dispatch jobs to a Kubernetes (K8s) cluster via Pulsar,
+Pulsar implements a "two-container" architecture per pod, where
one container stages job execution environment (`pulsar-container`)
and another container encompasses tool's executables (`tool-container`).
-Note that this architecture is experimental and under active development,
+Note that this architecture is experimental and under active development,
it is increasingly improved and it will soon be production-grade ready.
-In order to setup Galaxy to use the "two-container" architecture, you may
-take the following steps:
+In order to setup Galaxy to use the "two-container" architecture, you may
+take the following steps:
1. In the `galaxy.yml` set the following attributes:
- `job_config_file: job_conf.yml`
-- Appropriately configure `galaxy_infrastructure_url`; for example,
-set it as the following on macOS:
-`galaxy_infrastructure_url: 'http://host.docker.internal:$UWSGI_PORT'`
+- Appropriately configure `galaxy_infrastructure_url`; for example,
+set it as the following on macOS:
+`galaxy_infrastructure_url: 'http://host.docker.internal:$GALAXY_WEB_PORT'`
-2. In the `job_conf.yml` set the following runners and execution attributes appropriately:
+2. In the `job_conf.yml` set the following runners and execution attributes appropriately:
```yaml
runners:
@@ -361,7 +361,6 @@ The following example assumes the existence of a job destination with ids `short
...
```
-
With these if place, the following `default_runner` rule function will route all tools with id containing `mothur` to the `long_pbs` destination defined `jobs_conf.xml` and all other tools to the `short_pbs` destination:
```python
diff --git a/doc/source/admin/migrating_to_gunicorn.md b/doc/source/admin/migrating_to_gunicorn.md
new file mode 100644
index 00000000000..f5ed9566f40
--- /dev/null
+++ b/doc/source/admin/migrating_to_gunicorn.md
@@ -0,0 +1,45 @@
+# Migrating from uWSGI to Gunicorn and FastAPI
+
+## Why do we migrate away from uWSGI
+
+Starting with Galaxy release 22.01 the default application webserver is [Gunicorn](https://gunicorn.org/), which replaces [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/). We will remove support for running Galaxy under uWSGI in Galaxy release 22.05.
+We have made this move because uWSGI support for newer Python versions has been problematic and because
+we have modernized the API portion of our backend. The Galaxy web application is now an ASGI application
+driven by [FastAPI](https://fastapi.tiangolo.com/) and [Starlette](https://www.starlette.io/).
+This will enable numerous important features in the future that would not be possible (or would be more complicated to set up)
+otherwise. Importantly, [FastAPI's documentation](https://fastapi.tiangolo.com/tutorial/) is very good and
+should increase developer productivity.
+
+The main advantage for our users today is that Galaxy hosts documentation for its API as an [OpenAPI](https://www.openapis.org/)
+document that is directly generated from Galaxy's source code, and so will never be out of date or differ
+from the actual implementation.
+Note that not all API endpoints have been modernized as of yet, this is an ongoing process.
+
+To see the API documentation for your Galaxy server you can go to `/api/docs`.
+Another immediate advantage is that parameters to all incoming API requests are validated against a [Pydantic](https://pydantic-docs.helpmanual.io/) schema.
+This will lead to fewer subtle bugs and make it easier to interface with Galaxy's API.
+
+In the future we are going to use Websockets and asynchronous programming to increase the reactivity
+of the Galaxy user interface. This would not be as simple under uWSGI.
+
+## How do I upgrade my instance to use Gunicorn
+
+If you are using `run.sh` to start Galaxy and have not set up job handling via uWSGI mules,
+you do not need to do anything to start Galaxy under Gunicorn.
+
+If you are using uWSGI mules, please read the [Scaling and Load Balancing documentation](scaling.md).
+You will most likely want to set up the **Gunicorn + Webless** strategy.
+
+If you are using an upstream proxy server such as NGINX or Apache and you've been
+using the uWSGI protocol, you need to replace `uwsgi_pass` and `mod_proxy_uwsgi`.
+You can find detailed documentation in the [NGINX](nginx.md) and [Apache](apache.md)
+documentation.
+
+If you are managing your Galaxy server via Ansible, you can continue to run Galaxy
+under uWSGI while we are working on updating the Ansible roles for installing Galaxy.
+We will update instructions here and on the [Galaxy Training Network](https://training.galaxyproject.org/).
+
+If you are starting Web and Job Handlers using an external process manager like
+systemd or supervisor, please read the [Scaling and Load Balancing documentation](scaling.md).
+In particular, you can use [gravity](https://github.com/galaxyproject/gravity) to generate supervisor configuration files
+that you can either use directly or as a basis to update your existing configuration.
diff --git a/doc/source/admin/nginx.md b/doc/source/admin/nginx.md
index 1a8e8c1f774..e9e45926ce9 100644
--- a/doc/source/admin/nginx.md
+++ b/doc/source/admin/nginx.md
@@ -28,9 +28,7 @@ Instructions for [proxying with Apache](apache.md) are also available.
### NGINX Proxy Prerequisities
-If you plan to use nginx to handle your file uploads, you will (most likely) not be able to use your package manager's
-version of nginx. The [Receiving Files With NGINX](#receiving-files-with-nginx) section explains this in detail and
-provides some options for installing *nginx + upload module* packages maintained by the Galaxy Committers Team.
+If you are **not** planning to use the recommended [tus.io method](#receiving-files-via-the-tus-protocol) to handle file uploads but want to use nginx to handle uploads, you will (most likely) not be able to use your package manager's version of nginx. The [Receiving Files With NGINX](#receiving-files-with-nginx) section explains this in detail and provides some options for installing *nginx + upload module* packages maintained by the Galaxy Committers Team.
Otherwise, your system package manager's version of nginx should be suitable. Under Debian, the
[nginx-light][nginx-light] package contains all the necessary modules used in this guide. On EL, the [EPEL][epel]
@@ -49,11 +47,9 @@ version of nginx is suitable.
```eval_rst
.. include:: _inc_proxy_serving_root.rst
-.. _Galaxy Release 17.09 Proxy Documentation: https://docs.galaxyproject.org/en/release_17.09/admin/special_topics/nginx.html
+.. _Galaxy Release 21.09 Proxy Documentation: https://docs.galaxyproject.org/en/release_21.09/admin/nginx.html
```
-uWSGI protocol support is built in to nginx, so (unlike Apache) no extra modules or recompiling should be required.
-
The following configuration is not exhaustive, only the portions most relevant to serving Galaxy are shown, these should
be incorporated with your existing/default nginx config as is appropriate for your server. Notably, the nginx package
you installed most likely has a multi-file config layout. If you are not already familiar with that layout and where
@@ -75,7 +71,7 @@ http {
gzip_buffers 16 8k;
# allow up to 3 minutes for Galaxy to respond to slow requests before timing out
- uwsgi_read_timeout 180;
+ proxy_read_timeout 180;
# maximum file upload size
client_max_body_size 10g;
@@ -122,11 +118,13 @@ http {
# Enable HSTS
add_header Strict-Transport-Security "max-age=15552000; includeSubdomains";
- # proxy all requests not matching other locations to uWSGI
+ # proxy all requests not matching other locations to Gunicorn
location / {
- uwsgi_pass unix:///srv/galaxy/var/uwsgi.sock;
- uwsgi_param UWSGI_SCHEME $scheme;
- include uwsgi_params;
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_pass http://unix:/srv/galaxy/var/gunicorn.sock;
}
# serve framework static content
@@ -152,9 +150,8 @@ http {
}
```
-Be sure to set `$galaxy_root` to the path to your copy of Galaxy and modify the value of `uwsgi_pass` to match your
-uWSGI socket path. With the default configuration, uWSGI will bind to a random TCP socket, so you will need to set it to
-a fixed value as described in the [Scaling and Load Balancing](scaling.md) documentation. If using a UNIX domain
+Be sure to set `$galaxy_root` to the path to your copy of Galaxy and modify the value of `proxy_pass` to match your
+Gunicorn socket path. With the default configuration, gunicorn will bind to a TCP socket, so you will need to Gunicorn to bind to a UNIX domain socket as described in the [Scaling and Load Balancing](scaling.md) documentation. If using a UNIX domain
socket, be sure to pay particular attention to the discussion of users and permissions.
### Additional Notes
@@ -165,9 +162,9 @@ socket, be sure to pay particular attention to the discussion of users and permi
- If your existing nginx configuration contains a line or included config file defining a default server, be sure to
disable it by commenting its `server {}` or preventing its inclusion (under Debian this is done by removing its
symlink from `/etc/nginx/sites-enabled`).
-- `uwsgi_read_timeout` can be adjusted as appropriate for your site. This is the amount of time allowed for
- communication between nginx and uWSGI to block while waiting for a response from Galaxy, and is useful for holding
- client (browser) connections while uWSGI is restarting Galaxy subprocesses or Galaxy is performing a slow operation.
+- `proxy_read_timeout` can be adjusted as appropriate for your site. This is the amount of time allowed for
+ communication between nginx and Gunicorn to block while waiting for a response from Galaxy, and is useful for holding
+ client (browser) connections while Gunicorn is restarting Galaxy subprocesses or Galaxy is performing a slow operation.
- The parameter `client_max_body_size` specifies the maximum upload size that can be handled by POST requests through
nginx. You should set this to the largest file size that you wish to allow for upload and that could be reasonably
handled by your site. It defaults to 1MB, so it will need to be increased if you are dealing with genome sized
@@ -191,11 +188,13 @@ previous section:
```nginx
#...
- # proxy all requests not matching other locations to uWSGI
+ # proxy all requests not matching other locations to Gunicorn
location /galaxy {
- uwsgi_pass unix:///srv/galaxy/var/uwsgi.sock
- uwsgi_param UWSGI_SCHEME $scheme;
- include uwsgi_params;
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_pass http://unix:/srv/galaxy/var/gunicorn.sock:/galaxy;
}
# serve framework static content
@@ -211,16 +210,19 @@ previous section:
```
2. The Galaxy application needs to be aware that it is running with a prefix (for generating URLs in dynamic pages).
- This is accomplished by configuring uWSGI (the `uwsgi` section in `config/galaxy.yml`) like so and restarting Galaxy:
+ This is accomplished by configuring Galaxy in your `config/galaxy.yml` file like so and restarting Galaxy:
```yaml
- uwsgi:
- #...
- socket: /srv/galaxy/var/uwsgi.sock
- mount: /galaxy=galaxy.webapps.galaxy.buildapp:uwsgi_app()
- manage-script-name: true
- # `module` MUST NOT be set when `mount` is in use
- #module: galaxy.webapps.galaxy.buildapp:uwsgi_app()
+ gravity:
+ gunicorn:
+ # ...
+ bind: /srv/galaxy/var/gunicorn.sock
+ gunicorn_extra_args: '--forwarded-allow-ips="*"'
+ # ...
+ galaxy:
+ # ...
+ galaxy_url_prefix: /galaxy
+ # ...
```
```eval_rst
@@ -229,8 +231,7 @@ previous section:
overrides the automatic setting. If you have this option set, unset it unless you know what you're doing.
```
- Be sure to consult the [Scaling and Load Balancing](scaling.md) documentation, other options unrelated to proxying
- should also be set in the `uwsgi` section of the config.
+ Be sure to consult the [Scaling and Load Balancing](scaling.md) documentation.
## Advanced Configuration Topics
@@ -488,8 +489,6 @@ subject](http://galacticengineer.blogspot.com/2015/06/exposing-galaxy-reports-vi
After successfully following the blog post, Galaxy reports should be available at e.g. `https://galaxy.example.org/reports`.
To secure this page to only Galaxy administrators, adjust your nginx config accordingly:
-**TODO:** This is not valid for the uWSGI proxy method and needs to be updated. -nate 2018-01-11
-
```nginx
location /reports {
#...
diff --git a/doc/source/admin/python.md b/doc/source/admin/python.md
index c323c96b9fc..23870548c8e 100644
--- a/doc/source/admin/python.md
+++ b/doc/source/admin/python.md
@@ -1,6 +1,6 @@
# Supported Python versions
-Galaxy's core functionality is currently supported on Python **>=3.6** .
+Galaxy's core functionality is currently supported on Python **>=3.7** .
If Galaxy complains about the version of Python you are using:
diff --git a/doc/source/admin/reports.rst b/doc/source/admin/reports.rst
index 91d10028d6a..2ce8843f375 100644
--- a/doc/source/admin/reports.rst
+++ b/doc/source/admin/reports.rst
@@ -41,7 +41,7 @@ following (and more):
Configuration
----------------------------
-- Configure ``config/reports.yml`` in the same manner as your main galaxy instance (i.e., same database connection, but different web server port). This is a uWSGI YAML configuration file and should contain a ``reports`` section with app-specific configuration (options described below).
+- Configure ``config/reports.yml`` in the same manner as your main galaxy instance (i.e., same database connection, but different web server port). This is a YAML configuration file and should contain a ``reports`` section with app-specific configuration (options described below).
- The default port for the reports application is ``9001``, and like Galaxy it only binds to localhost by default.
- ``database_connection`` should match the value used in your Galaxy configuration
@@ -49,7 +49,7 @@ Configuration
experimental support for MySQL is available but SQLite is not supported
at all.
-- Run reports in a uWSGI server with ``sh run_reports.sh``
+- Run reports in a Gunicorn server with ``sh run_reports.sh``
- Use a web browser and go to the address you configured in ``reports.yml`` (defaults to http://localhost:9001/)
- If you'd like the report tool to persist between sessions then use
``sh run_reports.sh --daemon`` to run it as a background process. As with
diff --git a/doc/source/admin/scaling.md b/doc/source/admin/scaling.md
index 26a6d41442e..550f0bbcd22 100644
--- a/doc/source/admin/scaling.md
+++ b/doc/source/admin/scaling.md
@@ -9,9 +9,8 @@ more thorough explanation of this problem and why you will almost surely want to
configuration if running for more than a small handful of users, see the [production configuration](production.md)
page.
-Just to be clear: increasing the values of `threadpool_workers` in `galaxy.yml` or the number of plugin workers in
-`job_conf.xml` will not make you Galaxy server much more responsive. The key to scaling Galaxy is the ability to run
-*multiple* Galaxy servers which co-operatively work on the same database.
+Just to be clear: Increasing the number of plugin workers in `job_conf.xml` will not make your Galaxy server much more responsive.
+The key to scaling Galaxy is the ability to run *multiple* Galaxy servers which co-operatively work on the same database.
## Terminology
@@ -22,40 +21,21 @@ Just to be clear: increasing the values of `threadpool_workers` in `galaxy.yml`
mapped to a handler tag such that all executions of that tool are handled by the tagged handler(s).
* **default** - Any handlers without defined tags - aka "untagged handlers" - will handle executions of all tools
not mapped to a specific handler ID or tag.
-* **[uWSGI][uwsgi]** - Powerful application server written in C that implements the HTTP and Python WSGI protocols
- * **[Mules][uwsgi-mules]** - uWSGI processes started after the main application (Galaxy) that can run separate code
- and receive messages from uWSGI web workers
- * **[Zerg Mode][uwsgi-zerg-mode]** - uWSGI configuration where multiple copies of the same application can be started
- simultaneously in order to maintain availability during application restarts
-* **Webless Galaxy application** - The Galaxy application run as a standalone Python application with no web/WSGI server
-
-[uwsgi]: https://uwsgi-docs.readthedocs.io/
-[uwsgi-mules]: https://uwsgi-docs.readthedocs.io/en/latest/Mules.html
-[uwsgi-zerg-mode]: https://uwsgi-docs.readthedocs.io/en/latest/Zerg.html
+* **Webless Galaxy application** - The Galaxy application run as a standalone Python application with no web/ASGI server
## Application Servers
It is possible to run the Galaxy server in many different ways, including under different web application frameworks, or
-as a standalone server with no web stack. For most of its modern life, prior to the 18.01 release, Galaxy (by default)
-used the [Python Paste][paste] web stack, and ran in a single process.
+as a standalone server with no web stack. Prior to the 18.01 release, Galaxy (by default)
+used the [Python Paste][paste] web stack, and ran in a single process. Between the 18.01 release and the 22.01 release
+[uWSGI](https://uwsgi-docs.readthedocs.io/) was used as the default application server. Starting with the 22.01 release the default application server is
+[Gunicorn][Gunicorn]. For information about uWSGI in the Galaxy context please consult the version of this document that is
+appropriate to your Galaxy release.
-Beginning with Galaxy release 18.01, the default application server for new installations of Galaxy is [uWSGI][uwsgi].
-Prior to 18.01, it was possible (and indeed, recommended for production Galaxy servers) to run Galaxy under uWSGI, but
-it was necessary to install and configure uWSGI separately from Galaxy. uWSGI is now provided with Galaxy as a Python
-Wheel and installed in to its virtualenv, as described in detail in the [Framework
-Dependencies](framework_dependencies) documentation.
-
-uWSGI has numerous benefits over Python Paste for our purposes:
-
-* Written in C and designed to be high performance
-* Easily runs multiple processes by increasing `processes` config option
-* Load balances multiple processes internally rather than requiring load balancing in the proxy server
-* Offload engine for serving static content
-* Speaks high performance native protocol between uWSGI and proxy server
-* Can speak HTTP and HTTPS protocols without proxy server
-* Incredibly featureful, supports a wide array of deployment scenarios
-* Supports WebSockets, which enable Galaxy Interactive Environments out-of-the-box without a proxy server or Node.js
+Gunicorn is able to serve ASGI applications. Galaxy can act as an ASGI web application since release 21.01,
+and we will drop support for being run as a WSGI application via uWSGI in Galaxy release 22.05.
+[Gunicorn]: https://gunicorn.org/
[paste]: https://paste.readthedocs.io/
## Deployment Options
@@ -64,61 +44,26 @@ There are multiple deployment strategies for the Galaxy application that you can
the configuration of the infrastructure on which you are deploying. In all cases, all Galaxy job features such as
[running on a cluster](cluster.md) are supported.
-Although uWSGI implements nearly all the features that were previously the responsibility of an upstream proxy server,
-at this time, it is still recomended to place a proxy server in front of uWSGI and utilize it for all of its traditional
+Although Gunicorn implements many features that were previously the responsibility of an upstream proxy server,
+it is recommended to place a proxy server in front of Gunicorn and utilize it for all of its traditional
roles (serving static content, serving dataset downloads, etc.) as described in the [production
configuration](production.md) documentation.
-When using uWSGI with a proxy server, it is recommended that you use the native high performance uWSGI protocol
-(supported by both [Apache](apache.md) and [nginx](nginx.md)) between uWSGI and the
-proxy server, rather than HTTP.
+### Gunicorn with jobs handled by web workers (default configuration)
-### uWSGI with jobs handled by web workers (default configuration)
-
-Referred to in this documentation as the **uWSGI all-in-one** strategy.
+Referred to in this documentation as the **all-in-one** strategy.
* Job handlers and web workers are the same processes and cannot be separated
-* The web worker that receives the job request from the UI/API will be the job handler for that job
+* A random web worker will be the job handler for that job
-Under this strategy, jobs will be handled by uWSGI web workers. Having web processes handle jobs will negatively impact
+Under this strategy, jobs will be handled by Gunicorn workers. Having web processes handle jobs will negatively impact
UI/API performance.
-This is the default out-of-the-box configuration as of Galaxy Release 18.01 and will be deprecated in Galaxy Release 21.09
-in favor of running separate processes for handling web requests (gunicorn serving a fastAPI instance), for handling jobs and
-workflows (using the current webless job handling code) and Celery workers for running long-running and/or CPU-intensive tasks.
+This is the default out-of-the-box configuration.
-### uWSGI for web serving with Mules as job handlers
+### Gunicorn for web serving and Webless Galaxy applications as job handlers
-Referred to in this documentation as the **uWSGI + Mules** strategy.
-
-* Job handlers run as children of the uWSGI process
-* Jobs are dispatched from web workers to job handlers via native *mule messaging*
-* Jobs can only be dispatched to mules on the same host
-* Trivially easy to enable (disabled by default for simplicity reasons)
-
-Under this strategy, job handling is offloaded to dedicated non-web-serving processes that are started and stopped
-directly by the master uWSGI process. As a benefit of using mule messaging, only job handlers that are alive will be
-selected to run jobs.
-
-This was the recommended deployment strategy until Galaxy release 21.01. This deployment strategy will be supported
-until Galaxy release 21.05 and will be deprecated in Galaxy release 21.09.
-
-```eval_rst
-.. important::
-
- If using **Zerg Mode** or running more than one uWSGI *master* process, do not use **uWSGI + Mules**. Doing so can
- can cause jobs to be executed by mutiple handlers when recovering unassigned jobs at Galaxy server startup.
-
- Multiple master processes is a rare configuration and is typically only used in the case of load balancing the web
- application across multiple hosts. Note that multiple master proceses is not the same thing as the ``processess``
- uWSGI configuration option, which is perfectly safe to set when using job handler mules.
-
- For these scenarios, **uWSGI + Webless** is the recommended deployment strategy.
-```
-
-### uWSGI for web serving and Webless Galaxy applications as job handlers
-
-Referred to in this documentation as the **uWSGI + Webless** strategy.
+Referred to in this documentation as the **Gunicorn + Webless** strategy.
* Job handlers are started as standalone Python applications with no web stack
* Jobs are dispatched from web workers to job handlers via the Galaxy database
@@ -126,73 +71,52 @@ Referred to in this documentation as the **uWSGI + Webless** strategy.
* Additional job handlers can be added dynamically without reconfiguring/restarting Galaxy (19.01 or later)
* The recommended deployment strategy for production Galaxy instances
-Like mules, under this strategy, job handling is offloaded to dedicated non-web-serving processes, but those processes
-are [managed by the administrator](#starting-and-stopping).
-
By default, handler assignment will occur using the **Database Transaction Isolation** or **Database SKIP LOCKED**
-methods (see below). However, if the database used does not support this mechanism (in practice this should only apply
-to sqlite before version 3.25, which is not at all recommended for production Galaxy server) a handler is randomly
-assigned by the web worker when the job is submitted via the UI/API, meaning that jobs may be assigned to dead handlers.
+methods (see below).
-This is the recommended deployment strategy when **Zerg Mode** is used, for Galaxy servers that run web servers and
-job handlers **on different hosts**, and for deployments where dynamic handler addition is desired.
+### uWSGI for web serving with Mules as job handlers
-Beginning with Galaxy release 19.01, it is also possible to use a combination of both **uWSGI + Mules** and **uWSGI +
-Webless**, referred to in the documentation as **uWSGI + Hybrid**.
+This strategy is deprecated and will be removed in Galaxy release 22.05.
+You can consult the documentation for older versions of Galaxy for details.
-### Legacy
-
-Other deployment strategies were commonly used in older versions of Galaxy and can be found in previous versions of the
-documentation, but these are deprecated and should no longer be used.
+If you're upgrading Galaxy to release 22.01 or newer we recommend you set up the
+**Gunicorn + Webless** strategy above.
## Job Handler Assignment Methods
-Job handler assignment methods configurable with the `assign_with`
+Job handler assignment methods are configurable with the `assign_with`
attribute on the `` tag in `job_conf.xml`. The available methods are:
-- **Database Transaction Isolation** (`db-transaction-isolation`, new in 19.01) - Jobs are assigned a handler by handlers selecting the unassigned
+* **Database Transaction Isolation** (`db-transaction-isolation`, new in 19.01) - Jobs are assigned a handler by handlers selecting the unassigned
job from the database using SQL transaction isolation, which uses database locks to guarantee that only one handler
can select a given job. This occurs by the web worker that receives the tool execution request (via the UI or API)
setting a new job's 'handler' column in the database to the configured tag/default (or `_default_` if no tag/default
is configured). Handlers "listen" for jobs by selecting jobs from the database that match the handler tag(s) for which
- they are configured. This is the default if no handlers are defined, or handlers are defined but no assign_with attribute is set
- on the `handlers` tag and *Database SKIP LOCKED* is not available and no uwsgi-mule-messaging is set up.
+ they are configured. `db-transaction-isolation` is the default assignment method if no handlers are defined,
+ or handlers are defined but no `assign_with` attribute is set on the `handlers` tag and *Database SKIP LOCKED* is not available.
-- **Database SKIP LOCKED** (`db-skip-locked`, new in 19.01) - Jobs are assigned a handler by handlers selecting the unassigned job from
+* **Database SKIP LOCKED** (`db-skip-locked`, new in 19.01) - Jobs are assigned a handler by handlers selecting the unassigned job from
the database using `SELECT ... FOR UPDATE SKIP LOCKED` on databases that support this query (see the next section for
details). This occurs via the same process as *Database Transaction Isolation*, the only difference is the way in
- which handlers query the database. This is the default if no handlers are defined, or handlers are defined but no assign_with attribute is set
- on the `handlers` tag and *Database SKIP LOCKED* is available and no uwsgi-mule-messaging is set up.
+ which handlers query the database. This is the default if no handlers are defined, or handlers are defined but no `assign_with` attribute is set
+ on the `handlers` tag and *Database SKIP LOCKED* is available.
-- **Database Self Assignment** (`db-self`) - Like *In-memory Self Assignment* but assignment occurs by setting a new job's 'handler'
+* **Database Self Assignment** (`db-self`) - Like *In-memory Self Assignment* but assignment occurs by setting a new job's 'handler'
column in the database to the process that created the job at the time it is created. Additionally, if a tool is
configured to use a specific handler (ID or tag), that handler is assigned (tags by *Database Preassignment*). This is
- the default if no handlers are defined and no `job-handlers` uWSGI Farm is present and the database does not support
- *Database SKIP LOCKED* or *Database Transaction Isolation*.
+ the default fallback if no handlers are defined and the database does not support *Database SKIP LOCKED* or *Database Transaction Isolation*.
-- **In-memory Self Assignment** (`mem-self`) - Jobs are assigned to the web worker that received the tool execution request from the
+* **In-memory Self Assignment** (`mem-self`) - Jobs are assigned to the web worker that received the tool execution request from the
user via an internal in-memory queue. If a tool is configured to use a specific handler, that configuration is
ignored; the process that creates the job *always* handles it. This can be slightly faster than **Database Self
Assignment** but only makes sense in single process environments without dedicated job handlers. This option
- supercedes the former `track_jobs_in_database` option in `galaxy.yml` and corresponds to setting that option to
- `false`. Will be removed from Galaxy in release 21.09.
+ supersedes the former `track_jobs_in_database` option in `galaxy.yml` and corresponds to setting that option to
+ `false`.
-- **Database Preassignment** (`db-preassign`) - Jobs are assigned a handler by selecting one at random from the configured tag or default
+* **Database Preassignment** (`db-preassign`) - Jobs are assigned a handler by selecting one at random from the configured tag or default
handlers at the time the job is created. This occurs by the web worker that receives the tool execution request (via
the UI or API) setting a new job's 'handler' column in the database to the randomly chose handler ID (hence
- "preassignment"). This is the default if handlers are defined and no `job-handlers` uWSGI Farm is present
- and the database does not support *Database SKIP LOCKED* or *Database Transaction Isolation*.
-
-- **uWSGI Mule Messaging** (`uwsgi-mule-message`) - Jobs are assigned a handler via uWSGI mule messaging. A mule in the `job-handlers` (for
- default/untagged tool-to-handler mappings) or `job-handlers.` farm will receive the message and assign itself.
- This the default if a `job-handlers` uWSGI Farm is present and no handlers are configured.
- Will be removed in Galaxy release 21.09.
-
-In the event that both a `job-handlers` uWSGI Farm is present and handlers are configured, the default is *uWSGI Mule
-Messaging* followed by *Database SKIP LOCKED* or *Database Transaction Isolation* or *Database Preassignment*, depending on which method
-is supported by the database in use. At present, only *uWSGI Mule Messaging* is capable of deferring handler
-assignment to a later method (which would occur in the event that a tool is configured to use a tag for which there is
-not a matching farm).
+ "preassignment"). This is the default only if handlers are defined and the database does not support *Database SKIP LOCKED* or *Database Transaction Isolation*.
In all cases, if a tool is configured to use a specific handler (by ID, not tag), configured assignment methods are
ignored and that handler is directly assigned in the job's 'handler' column at job creation time.
@@ -203,33 +127,24 @@ assignment method.
### Choosing an Assignment Method
Prior to Galaxy 19.01, the most common deployment strategies (e.g. **uWSGI + Webless**) assigned handlers using what is
-now (since 19.01) referred to as *Database Preassignment*. Although still the default in many cases (until the new
-methods mature), preassignment has a few drawbacks:
+now (since 19.01) referred to as *Database Preassignment*. Although still a fallback option when the database
+does not support *Database SKIP LOCKED* or *Database Transaction Isolation*, preassignment has a few drawbacks:
-- Web workers do not have a way to know whether a particular handler is alive when assigning that handler
-- Jobs are not load balanced across handlers
-- Changing the number of handlers requires changing `job_conf.xml` and restarting *all* Galaxy processes
+* Web workers do not have a way to know whether a particular handler is alive when assigning that handler
+* Jobs are not load balanced across handlers
+* Changing the number of handlers requires changing `job_conf.xml` and restarting *all* Galaxy processes
-The new "database locking" methods (*Database SKIP LOCKED* and *Database Transaction Isolation*) were created to solve
-these issues. The preferred method between the two new options is *Database SKIP LOCKED*, but it requires PostgreSQL 9.5
-or newer, MySQL 8.0 or newer (untested), or MariaDB 10.3 or newer (untested). If using an older database version, use
-*Database Transaction Isolation* instead. A detailed explanation of these database locking methods in PostgreSQL can be
+The "database locking" methods (*Database SKIP LOCKED* and *Database Transaction Isolation*) were created to solve
+these issues. The preferred method between the two options is *Database SKIP LOCKED*, but it requires PostgreSQL 9.5
+or newer, SQLite 3.25 or newer or MySQL 8.0 or newer (untested), or MariaDB 10.3 or newer (untested).
+If using an older database version, use *Database Transaction Isolation* instead. A detailed explanation of these database locking methods in PostgreSQL can be
found in the excellent [What is SKIP LOCKED for in PostgreSQL 9.5?][2ndquadrant-skip-locked] entry on the [2ndQuadrant
PostgreSQL Blog][2ndquadrant-blog].
-The preferred method depends on your deployment strategy:
+The preferred assignment method is *Database SKIP LOCKED* or *Database Transaction Isolation*.
-- **uWSGI + Mules** - Either *Database SKIP LOCKED* or *Database Transaction Isolation* is preferred.
-- **uWSGI + Webless** - Either *Database SKIP LOCKED* or *Database Transaction Isolation* is preferred.
-- **uWSGI + Hybrid** - Either *Database SKIP LOCKED* or *Database Transaction Isolation* is preferred. If your mule and
- webless handlers are in non-overlapping pools (i.e. tags, or untagged), you can alternatively use both *uWSGI Mule
- Messaging* followed by either *Database SKIP LOCKED* or *Database Transaction Isolation*. If pools overlap, using
- *uWSGI Mule Messaging* would prevent any non-mule handlers in that pool from being assigned jobs.
-
-Handlers (as well as assignment methods) are not configurable when using **uWSGI all-in-one**.
-
-[2ndquadrant-skip-locked]: https://blog.2ndquadrant.com/what-is-select-skip-locked-for-in-postgresql-9-5/
-[2ndquadrant-blog]: https://blog.2ndquadrant.com/
+[2ndquadrant-skip-locked]: https://www.2ndquadrant.com/en/blog/what-is-select-skip-locked-for-in-postgresql-9-5/
+[2ndquadrant-blog]: https://www.2ndquadrant.com/en/blog/
```eval_rst
.. _scaling-configuration:
@@ -237,160 +152,126 @@ Handlers (as well as assignment methods) are not configurable when using **uWSGI
## Configuration
-### uWSGI
+### Gunicorn
-Although this document goes in to significant detail about uWSGI configuration, many more options are available, as well
-as additional documentation about options described here. Consult the uWSGI documentation for more:
+We will only outline a few of Gunicorn's options, consult the [Gunicorn documentation](https://docs.gunicorn.org/en/latest/settings.html) for more.
-* [Configuring uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/Configuration.html)
-* [uWSGI Options](https://uwsgi-docs.readthedocs.io/en/latest/Options.html)
-* [Quickstart for Python/WSGI applications](https://uwsgi-docs.readthedocs.io/en/latest/WSGIquickstart.html)
+Note that by default Galaxy will use [gravity](https://github.com/galaxyproject/gravity/) to create a [supervisor](http://supervisord.org/) configuration in Gravity's state directory.
+Gravity's state directory is located in `database/gravity`, and you can find the generated supervisor configuration in
+`database/gravity/supervisor`. The location of the state directory can be controlled using the `--state-dir` argument
+of `galaxyctl`, or using the `GRAVITY_STATE_DIR` environment variable.
+Configuration values for the supervisor configuration are read from the `gravity` section of your `galaxy.yml` file.
+This is the preferred and out-of-the box way of configuring Gunicorn for serving Galaxy.
+If you are not using `./run.sh` for starting Galaxy or you would like to use another process manager,
+all the Gunicorn configuration values can also directly be set on the command line.
-Configuration is performed in the `uwsgi` section of `galaxy.yml`. You will find that the default, if copied from
-`galaxy.yml.sample`, is commented out. The default configuration options are provided to uWSGI on the command line by
-Galaxy's `run.sh` script.
+Configuration is performed in the `gravity` section of `galaxy.yml`. You will find that the default, if copied from
+`galaxy.yml.sample`, is commented out. The default configuration options are provided to Gunicorn on the command line by
+using `gravity` within the `run.sh` script.
-Galaxy releases prior to 18.01 (or upgraded-to-18.01+ servers which have not migrated their configuration to the YAML
-format) used an INI-format configuration file, `galaxy.ini`.
+After making changes to the `gravity` section, you always need to activate Galaxy's virtualenv and run `galaxyctl update`,
+or one of the `start`, `stop`, `restart`, and `graceful` subcommands of the `galaxyctl` command, which will run the `update` command internally.
-Note that uWSGI's YAML parser is hand-coded and not actually conformant to the YAML standard. Specifically:
+#### Common Gunicorn configuration
-* Multiple identical keys with unique values can exist in the same dictionary/hash, as with `hook-master-start` in the
- example below.
-* Quoting values (with single or double quotes) is unncessary since the parser treats all values as strings. The parser
- does not correctly handle these quote characters, resulting in invalid values.
-
-If using `galaxy.ini`, the option names and values are the same but in INI format, for example:
-
-```ini
-[uwsgi]
-processes = 4
-socket = 127.0.0.1:4001
-...
-```
-
-#### Configuration common to all uWSGI deployment styles
-
-In `galaxy.yml`, define a `uwsgi` section. Shown below are the options common to all deployment strategies:
+In `galaxy.yml`, define a `gravity` section. Shown below are the options common to all deployment strategies:
```yaml
-uwsgi:
+gravity:
+ app_server: gunicorn
+ gunicorn:
+ # listening options
+ bind: '127.0.0.1:8080'
+ # performance options
+ workers: 1
+ # Other options that will be passed to gunicorn
+ gunicorn_extra_args:
- # required in order to start the galaxy application
- module: galaxy.webapps.galaxy.buildapp:uwsgi_app()
- virtualenv: .venv
- pythonpath: lib
-
- # performance options
- master: true
- enable-threads: true
- processes: 2
- threads: 4
- offload-threads: 1
-
- # fix up signal handling
- die-on-term: true
- hook-master-start: unix_signal:2 gracefully_kill_them_all
- hook-master-start: unix_signal:15 gracefully_kill_them_all
-
- # listening options
-
- # job handling options
```
-Some of these options warrant explanation:
+Some of these options deserve explanation:
-* `master`: Instructs uWSGI to first start a master process manager and then fork web workers, mules, http servers (if
- enabled), and any others from the master. This is required for certain operational modes such as daemonization, but
- can interfere with the use of `+` to shut down Galaxy when running in the foreground on the command line, and
- so is not enabled by default (except when `run.sh --daemon` is used). Its use is strongly recommended for all
- production deployments.
-* `processes`: Controls the number of Galaxy application processes uWSGI will spawn. Increased web performance can be
- attained by increasing this value.
-* `threads`: Controls the number of web worker threads each application process will spawn.
-* `offload-threads`: uWSGI can use a dedicated threadpool for serving static content and handling internal routing,
- setting this value automatically enables such offloading.
-
-Additional options are explained in the [uWSGI Minutiae](#uwsgi-minutiae) below.
+* `workers`: Controls the number of Galaxy application processes Gunicorn will spawn. Increased web performance can be
+ attained by increasing this value. If Gunicorn is the only application on the server, a good starting value is the number of CPUs * 2 + 1.
+4-12 workers should be able to handle hundreds if not thousands of requests per second.
+* `gunicorn_extra_args`: You can specify additional arguments to pass to gunicorn here.
Note that the performance option values given above are just examples and should be tuned per your specific needs.
However, as given, they are a good place to start.
-Due to the Python GIL, increasing the value of `threads` has diminishing returns on web performance while increasing the
-memory footprint of each application process. Increasing it is most useful on servers experiencing a high amount of IO
-waiting, but the greatest performance gain comes from increasing `processes` as appropriate for the hardware on which
-Galaxy is running.
-
#### Listening and proxy options
**With a proxy server:**
-To use the native uWSGI protocol, set the `socket` option:
+To use a socket for the communication between the proxy and Gunicorn, set the `bind` option to a path:
```yaml
- # listening options
- socket: /srv/galaxy/var/uwsgi.sock
+gravity:
+ app_server: gunicorn
+ gunicorn:
+ # listening options
+ bind: 'unix:/srv/galaxy/var/gunicorn.sock'
+ gunicorn_extra_args: '--forwarded-allow-ips="*"'
```
Here we've used a UNIX domain socket because there's less overhead than a TCP socket and it can be secured by filesystem
-permissions, but you can also listen on a port:
+permissions. Note that we've added `--forwarded-allow-ips="*"` to ensure that the domain socket is trusted as a source from which to proxy headers.
+
+You can also listen on a port:
```yaml
- # listening options
- socket: 127.0.0.1:4001
+ app_server: gunicorn
+ gunicorn:
+ # listening options
+ bind: '127.0.0.1:4001'
```
+If you are listening on a port do not set `--forwarded-allow-ips="*"`.
+
The choice of port 4001 is arbitrary, but in both cases, the socket location must match whatever socket the proxy server
is configured to communicate with. If using a UNIX domain socket, be sure that the proxy server's user has read/write
permission on the socket. Because Galaxy and the proxy server most likely run as different users, this is not likely to
be the case by default. One common solution is to add the proxy server's user to the Galaxy user's primary group.
-uWSGI's `chmod-socket` option can also help here.
+Gunicorn's `umask` option can also help here.
You can consult the Galaxy documentation for [Apache](apache.md) or [nginx](nginx.md)
for help with the proxy-side configuration.
-By setting the `socket` option, `run.sh` will no longer automatically serve Galaxy via HTTP (since it is assumed that
-you are setting a socket to serve Galaxy via a proxy server). If you wish to continue serving HTTP directly with uWSGI
-while `socket` is set, you can use the `http` option as shown in the directions below.
+By setting the `bind` option to a socket, `run.sh` will no longer automatically serve Galaxy via HTTP (since it is assumed that
+you are setting a socket to serve Galaxy via a proxy server). If you wish to continue serving HTTP directly with Gunicorn
+while using a socket, you can add an additional `--bind` argument via the `gunicorn_extra_args` option:
-**Without a proxy server** or with a proxy server that does not speak the uWSGI native protocol:
+```yaml
+gravity:
+ app_server: gunicorn
+ gunicorn:
+ # listening options
+ bind: 'unix:/srv/galaxy/var/gunicorn.sock'
+ gunicorn_extra_args: '--forwarded-allow-ips="*" --bind 127.0.0.1:8080'
+```
-uWSGI can be configured to serve HTTP and/or HTTPS directly:
+Note that this should only be used for debugging purposes due to `--forwarded-allow-ips="*"`.
+
+**Without a proxy server**:
+
+It is strongly recommended to use a proxy server.
+
+Gunicorn can be configured to serve HTTPS directly:
```yaml
# listening options
- http: :8080
- https: :8443,server.crt,server.key
- static-map: /static=static
+ gunicorn:
+ # listening options
+ bind: '0.0.0.0:443'
+ keyfile: server.key
+ certfile: server.crt
```
+See [Gunicorn's SSL documentation](https://docs.gunicorn.org/en/latest/settings.html#ssl) for more details.
+
To bind to ports < 1024 (e.g. if you want to bind to the standard HTTP/HTTPS ports 80/443), you must bind as the `root`
-user and drop privileges to the Galaxy user with a configuration such as:
-
-```yaml
- # listening options
- shared-socket: :80
- shared-socket: :443,server.crt,server.key
- http: =0
- https: =1
- uid: galaxy
- gid: galaxy
- static-map: /static=static
-```
-
-To redirect HTTP traffic to the HTTPS port rather than serving Galaxy over HTTP, change `http: =0` in the above example
-to `http-to-https: =0`.
-
-Because `run.sh` performs setup steps, **it should not be run as `root`**. Instead, you can run uWSGI directly as root
-with:
-
-```console
-# cd /srv/galaxy/server
-# ./.venv/bin/uwsgi --yaml config/galaxy.yml
-```
-
-You can run the startup-time setup steps as the galaxy user after upgrading Galaxy with `sh
-./scripts/common_startup.sh`.
+user and drop privileges to the Galaxy user. However you are strongly encouraged to setup a proxy server
+as described in the [production configuration](production.md) documentation.
### Job Handling
@@ -406,11 +287,23 @@ You can run the startup-time setup steps as the galaxy user after upgrading Gala
using an ``UPDATE`` query in the database and is only recommended for advanced Galaxy administrators.
```
-#### uWSGI all-in-one job handling
+#### all-in-one job handling
Ensure that no `` section exists in your `job_conf.xml` (or no `job_conf.xml` exists at all) and start Galaxy
normally. No additional configuration is required. To increase the number of web workers/job handlers, increase the
-value of `processes`. Jobs will be handled according to rules outlined above in [Job Handler Assignment Methods](#job-handler-assignment-methods).
+value of `workers` in the gunicorn section of your galaxy.yml file:
+
+```yaml
+gravity:
+ ...
+ gunicorn:
+ ...
+ # performance options
+ workers: 4
+ ...
+```
+
+Jobs will be handled according to rules outlined above in [Job Handler Assignment Methods](#job-handler-assignment-methods).
```eval_rst
.. note::
@@ -420,79 +313,6 @@ value of `processes`. Jobs will be handled according to rules outlined above in
handling, choose another deployment strategy.
```
-#### uWSGI + Mule job handling
-
-Ensure that no `` section exists in your `job_conf.xml` (or no `job_conf.xml` exists at all) and add the
-following to the `uwsgi` section of `galaxy.yml` to start a single job handler mule:
-
-```yaml
- # job handling options
- mule: lib/galaxy/main.py
- farm: job-handlers:1
-```
-
-Then start Galaxy normally. To add additional mule handlers, add additional `mule` options and add their ID(s), comma
-separated, to the `job-handlers` farm. For example, 3 handlers are defined like so:
-
-```yaml
- # job handling options
- mule: lib/galaxy/main.py
- mule: lib/galaxy/main.py
- mule: lib/galaxy/main.py
- farm: job-handlers:1,2,3
-```
-
-By default, a job will be handled by whatever mule currently has the lock on the mule message queue. After receiving a
-message, it will release the lock, giving other mules a chance to handle future jobs. Jobs can be explicitly mapped to
-specific mules as described in the [Galaxy Job Configuration](./jobs.md) documentation
-by using the handler IDs `main.job-handlers.N`, where `N` is the mule's position in the farm, starting at 1 and incrementing for each mule in the
-farm (this is not necessarily the mule ID, but it will be if you only define one farm and you add mules to that farm in
-sequential order). Each worker that you wish to explicitly map jobs to should be defined in the `` section
-of `job_conf.xml`. *Do not* define a default handler.
-
-For example, to have the 2nd mule in the three-mule job-handlers farm shown above handle the `test1` tool, you would set
-the following in `job_conf.xml` (irrelevant options are not shown):
-
-```xml
-
-
-
-
-
-
-
-
-```
-
-It is also possible to create separate pools for handler tags: the farm name for tags is simply `job-handlers.`.
-In the following example, all jobs will be handled by mules 1 and 2, except for executions of tool ``test1``: those jobs
-will be handled by mule 3.
-
-The `uwsgi` section in `galaxy.yml`:
-
-```yaml
- # job handling options
- mule: lib/galaxy/main.py
- mule: lib/galaxy/main.py
- mule: lib/galaxy/main.py
- farm: job-handlers:1,2
- farm: job-handlers.special:3
-```
-
-In `job_conf.xml`:
-
-```
-
-
-
-
-
-```
-
-#### uWSGI + Webless job handling
-
-Beginning with Galaxy release 19.01, webless handlers do not always need to be defined in `job_conf.xml`.
-
##### Statically defined handlers
In the `` section in `job_conf.xml`, define the webless handlers you plan to start. Tools can be mapped
@@ -525,8 +345,7 @@ to specific handlers, or to handler tags, as in the following example:
``handler3`` will *only* handle executions of tool ``test1``.
```
-`run.sh` will start the uWSGI process(es), but you will need to start the webless handler processes yourself. This is
-done on the command line like so:
+`run.sh` will start the gunicorn and job handler process(es), but if you are not using `run.sh` or the generated supervisor setup you will need to start the webless handler processes yourself. This is done on the command line like so:
```console
$ cd /srv/galaxy/server
@@ -535,9 +354,6 @@ $ ./scripts/galaxy-main -c config/galaxy.yml --server-name handler1 --daemonize
$ ./scripts/galaxy-main -c config/galaxy.yml --server-name handler2 --daemonize
```
-However, a better option to managing processes by hand is to use a process manager as documented in the [Starting and
-Stopping](#starting-and-stopping) section.
-
#### Dynamically defined handlers
In order to define handlers dynamically, you must be using one of the new "database locking" handler assignment methods
@@ -553,234 +369,151 @@ as explained in [Job Handler Assignment Methods](#job-handler-assignment-methods
```
-As with statically defined handlers, `run.sh` will start the uWSGI process(es), but you will need to start the webless
-handler processes yourself. This is done on the command line like so (note the addition of the `--attach-to-pool`
-option):
+Note that we have defined a `` section without any `` entries,
+and we have explicitly configured the assignment method with `assign_with="db-skip-locked"`.
+
+To let gravity know how many webless handler processes should be started set the number of processes to start in the `gravity:` section of galaxy.yml:
+
+```yaml
+gravity:
+ handlers:
+ handler:
+ processes: 3
+ pools:
+ - job-handler
+ - workflow-scheduler
+ special:
+ pools:
+ - job-handler.special
+```
+
+In this example 4 processes will be started in total:
+3 processes will act as job handler and workflow scheduler, and one process will be dedicated to handling jobs for the `special` tag only. With the `job_conf.xml` configuration above these would be jobs created by the `test1` tool.
+You can omit the `pools` argument, this will then default to:
+
+```yaml
+ ...
+ pools:
+ - job-handler
+ - workflow-scheduler
+ ...
+```
+
+If you omit the `processes` argument this will default to a single process.
+You can further customize the handler names using the `name_template` section,
+for a complete example see [this gravity test case](https://github.com/galaxyproject/gravity/blob/a00df1c671fdc01e3fbc42f64a851a45a37a1870/tests/test_process_manager.py#L28).
+
+If you are not using dynamic handlers please omit the `handlers` entry completely, as these will
+otherwise be idle and not handle jobs or workflows.
+
+As with statically defined handlers, `run.sh` will start the process(es), but if you are not using `run.sh` or the generated supervisor config you will need to start the webless handler processes yourself. This is done on the command line like so (note the addition of the `--attach-to-pool` option):
```console
$ cd /srv/galaxy/server
-$ ./scripts/galaxy-main -c config/galaxy.yml --server-name handler0 --attach-to-pool job-handlers --daemonize
-$ ./scripts/galaxy-main -c config/galaxy.yml --server-name handler1 --attach-to-pool job-handlers.special --daemonize
-$ ./scripts/galaxy-main -c config/galaxy.yml --server-name handler2 --attach-to-pool job-handlers --attach-to-pool job-handlers.special --daemonize
+./scripts/galaxy-main -c config/galaxy.yml --server-name handler_0 --attach-to-pool job-handlers --attach-to-pool workflow-scheduler --daemonize
+./scripts/galaxy-main -c config/galaxy.yml --server-name handler_1 --attach-to-pool job-handlers --attach-to-pool workflow-scheduler --daemonize
+./scripts/galaxy-main -c config/galaxy.yml --server-name handler_3 --attach-to-pool job-handlers --attach-to-pool workflow-scheduler --daemonize
+./scripts/galaxy-main -c config/galaxy.yml --server-name special_0 --attach-to-pool job-handlers.special --daemonize
```
In this example:
-- `handler0` and `handler2` will handle tool executions that are not explicitly mapped to handlers
-- `handler1` and `handler2` will handle tool executions that are mapped to the `special` handler tag
+* `handler_0`, `handler_1` and `handler2` will handle tool executions that are not explicitly mapped to handlers
+* `special_0` will handle tool executions that are mapped to the `special` handler tag
-#### uWSGI + Hybrid job handling
+## gravity & galaxyctl
-Follow the process for both **uWSGI + Mules** and **uWSGI + Webless**:
+[Gravity](https://github.com/galaxyproject/gravity) is a management tool for Galaxy servers,
+and is installed when you set up Galaxy.
-1. Define Mules as in **uWSGI + Mules**
-2. Define Webless handlers in `` as in **uWSGI + Webless** (when using static handlers)
-3. Configure Webless handlers to start as in **uWSGI + Webless**
+It provides two executables, `galaxyctl`, which is used to manage the starting, stopping, and logging of Galaxy's various processes, and `galaxy`, which can be used to run a Galaxy server in the foreground.
-### uWSGI Minutiae
+These commands are available from within Galaxy's virtualenv, or you can install them globally.
+If you have used the standard installation method for Galaxy by running `./run.sh` or executing
+`./scripts/common_startup.sh`, a default directory has been configured in which gravity stores
+its state. If you have installed Galaxy or gravity by another means, you can use the `--state-dir` argument
+or the `GRAVITY_STATE_DIR` environment variable to control the state directory. If a state dir is not specified, it defaults to `~/.config/galaxy-gravity`.
+In the following sections we assume you have correctly set up gravity and can use the `galaxyctl` command.
-**Threads**
+## Logging and daemonization
-Although `enable-threads` was explicitly set in our example, in reality, as long as any value is set for the `threads`
-option, `enable-threads` is set implicitly. This option enables the Python GIL and application threads (threads started
-by Galaxy itself for various non-web tasks), which Galaxy uses extensively. Setting it explicitly, however, is harmless
-and can prevent strange difficult-to-debug situations if `threads` is accidentally unset.
+When running `./run.sh` the log output is shown on screen, and ^ctrl-c will stop all processes.
+Galaxy can be started in the background by running `./run.sh --daemon`.
-**Worker/Mule shutdown/reload mercy**
-
-By default, uWSGI will wait up to 60 seconds for web workers and mules to terminate. This is generally safe for
-servicing web requests, but some parts of Galaxy's job preparation/submission and collection/finishing operations can
-take quite a bit of time to complete and are not entirely reentrant: job errors or state inconsistencies can occur if
-interrupted (although every effort has been made to minimize such possibilities). By default, Galaxy will wait up to 30
-seconds for the threads allocated for these operations to terminate after instructing them to shut down. You can change
-this behavior by increasing the value of `monitor_thread_join_timeout` in the `galaxy` section of `galaxy.yml`. The
-maximum amount of time that Galaxy will take to shut down job runner workers is `monitor_thread_join_timeout *
-runner_plugin_count` since each plugin is shut down sequentially (`runner_plugin_count` is the number of ``s in
-your `job_conf.xml`).
-
-Thus you should set the appropriate uWSGI `*-restart-mercy` option to a value higher than the maximum job runner worker
-shutdown time. If using **uWSGI all-in-one**, set `worker-reload-mercy`, and if using **uWSGI + Mule job handling**, set
-`mule-reload-mercy` (both in the `uwsgi` section of `galaxy.yml`).
-
-**Signals**
-
-The signal handling options (`die-on-term` and `hook-master-start` with `unix_signal` values) are not required but, if
-set, will override [uWSGI's unconventional signal handling](https://uwsgi-docs.readthedocs.io/en/latest/Management.html)
-and cause `SIGTERM` to kill the server rather than restart it, and the uWSGI master process to gracefully shut down its
-web workers and job handler mules (i.e. the various Galaxy application processes) when it receives a `SIGINT` (signal 2)
-or `SIGTERM` (signal 15) signal (e.g. from `kill(1)` or `+`). When shutting down gracefully, uWSGI will wait 60
-seconds (by default, but this can be changed with the `reload-mercy`, `worker-reload-mercy` and `mule-reload-mercy`
-options) for child processes to die before forcefully killing them with `SIGKILL` (signal 9). Alternatively, you may
-prefer to have it shut down gracefully on `SIGTERM` but forcefully on `SIGINT` (forceful shutdown by uWSGI is still
-slightly cleaner than `kill -9` of the master process since it can attempt to release sockets cleanly) or vice-versa,
-which you can do by setting one of the signals to call `kill_them_all` rather than `gracefully_kill_them_all`:
-
-```yaml
- # fix up signal handling
- die-on-term: true
- hook-master-start: unix_signal:2 kill_them_all
- hook-master-start: unix_signal:15 gracefully_kill_them_all
-```
-
-More details on the `unix_signal` hook can be found in [uWSGI Issue #849](https://github.com/unbit/uwsgi/issues/849).
-
-**Logging and daemonization**
-
-It's possible to configure uWSGI to log to a file with the `logto` or `logto2` options (when running in the foreground,
-the default), but more advanced logging options that split log files for each process are possible and described in the
-Galaxy [Logging Configuration documentation](config_logging)
-
-When running as a daemon with `run.sh --daemon`, output is logged to `galaxy.log` and the pid is written to
-`galaxy.pid`. These can be controlled with the `daemonize` and `pidfile` arguments (their `daemonize2` and `pidfile2`
-counterparts wait until after the application successfully loads to open and write the files). If you set a `daemonize*`
-option, you should not use the `--daemon` argument to `run.sh` (or not use `run.sh` at all, and start Galaxy directly
-with `uwsgi` on the command line).
-
-**External uwsgi binary:**
-
-It is still possible to run Galaxy using an external copy of uWSGI (for example, installed from APT under
-Debian/Ubuntu). This was the recommended installation method in the past. To use an external uWSGI, you'll need simply
-need to start with uWSGI directly, rather than using the `run.sh` script. Once you have configured Galaxy/uWSGI, you can
-start it with:
+Alternatively, you can control Galaxy using the `galaxyctl` command provided by gravity.
+After activating Galaxy's virtual environment you can start Galaxy in the background
+using `galaxyctl start`:
```console
-$ cd /srv/galaxy/server
-$ uwsgi --yaml config/galaxy.yml
+$ galaxyctl start
+celery STARTING
+celery-beat STARTING
+gunicorn STARTING
+Log files are in /Users/mvandenb/src/doc_test/database/gravity/log
```
-When installing uWSGI, be sure to install the Python plugin, as this is not always contained in the same package (such
-as when installing from APT under Debian/Ubuntu). With the APT packages, you will also need to add `--plugin python` to
-the command line (or `plugin: python` to the `uwsgi` section of `galaxy.yml`).
+All process logs can be seen with `galaxyctl follow`:
-**Other options**
+```console
+$ galaxyctl follow
+==> /Users/mvandenb/src/doc_test/database/gravity/log/gunicorn.log <==
+galaxy.webapps.galaxy.buildapp DEBUG 2022-02-17 16:31:33,344 [pN:main,p:91480,tN:MainThread] Prior to webapp return, Galaxy thread is alive.
+galaxy.webapps.galaxy.buildapp DEBUG 2022-02-17 16:31:33,345 [pN:main,p:91480,tN:MainThread] Prior to webapp return, Galaxy thread is alive.
+galaxy.webapps.galaxy.buildapp DEBUG 2022-02-17 16:31:33,345 [pN:main,p:91480,tN:MainThread] Prior to webapp return, Galaxy thread is alive.
+galaxy.webapps.galaxy.buildapp DEBUG 2022-02-17 16:31:33,345 [pN:main,p:91480,tN:MainThread] Prior to webapp return, Galaxy thread is alive.
+galaxy.webapps.galaxy.buildapp DEBUG 2022-02-17 16:31:33,345 [pN:main,p:91480,tN:MainThread] Prior to webapp return, Galaxy thread is alive.
+galaxy.webapps.galaxy.buildapp DEBUG 2022-02-17 16:31:33,346 [pN:main,p:91480,tN:MainThread] Prior to webapp return, Galaxy thread is alive.
+galaxy.webapps.galaxy.buildapp DEBUG 2022-02-17 16:31:33,346 [pN:main,p:91480,tN:MainThread] Prior to webapp return, Galaxy thread is alive.
+[2022-02-17 16:31:34 +0100] [91480] [INFO] Started server process [91480]
+[2022-02-17 16:31:34 +0100] [91480] [INFO] Waiting for application startup.
+[2022-02-17 16:31:34 +0100] [91480] [INFO] Application startup complete.
-The `py-call-osafterfork` option may only be needed when mule messaging is in use, but it [seems to have no negative
-effect](https://github.com/unbit/uwsgi/issues/643) and may solve other situations with starting a complex threaded
-Python application.
+==> /Users/mvandenb/src/doc_test/database/gravity/log/celery.log <==
+[2022-02-17 16:31:27,008: DEBUG/MainProcess] ^-- substep ok
+[2022-02-17 16:31:27,009: DEBUG/MainProcess] | Consumer: Starting Events
+[2022-02-17 16:31:27,009: DEBUG/MainProcess] ^-- substep ok
+[2022-02-17 16:31:27,009: DEBUG/MainProcess] | Consumer: Starting Tasks
+[2022-02-17 16:31:27,035: DEBUG/MainProcess] ^-- substep ok
+[2022-02-17 16:31:27,035: DEBUG/MainProcess] | Consumer: Starting Heart
+[2022-02-17 16:31:27,035: DEBUG/MainProcess] ^-- substep ok
+[2022-02-17 16:31:27,035: DEBUG/MainProcess] | Consumer: Starting event loop
+[2022-02-17 16:31:27,035: INFO/MainProcess] celery@MacBook-Pro-2.local ready.
+[2022-02-17 16:31:27,035: DEBUG/MainProcess] basic.qos: prefetch_count->8
-The `chdir` option is useful if you are not using `run.sh`, to be able to call `uwsgi` from anywhere without having to
-`cd` to the Galaxy directory first.
+==> /Users/mvandenb/src/doc_test/database/gravity/log/celery-beat.log <==
+[2022-02-17 16:29:04,023: DEBUG/MainProcess] beat: Ticking with max interval->5.00 minutes
+[2022-02-17 16:29:04,024: DEBUG/MainProcess] beat: Waking up in 5.00 minutes.
+No Galaxy config file found, running from current working directory: /Users/mvandenb/src/doc_test
+[2022-02-17 16:31:26,818: DEBUG/MainProcess] Setting default socket timeout to 30
+[2022-02-17 16:31:26,819: INFO/MainProcess] beat: Starting...
+[2022-02-17 16:31:26,824: DEBUG/MainProcess] Current schedule:
+
+
+[2022-02-17 16:31:26,824: DEBUG/MainProcess] beat: Ticking with max interval->5.00 minutes
+[2022-02-17 16:31:26,825: DEBUG/MainProcess] beat: Waking up in 5.00 minutes.
+```
-**Monitoring**
-
-The [uwsgitop](https://github.com/xrmx/uwsgitop) tool uses uWSGI's stats server (the `stats` option, which is configured
-to listen on a socket or port in the same manner as the `socket` option) to report on the health and performance of the
-web workers. It can be installed with `pip install uwsgitop`. This tool can be useful for determing whether a worker is
-stuck, or seeing the throughput of traffic on your site.
+More advanced logging options are described in the Galaxy [Logging Configuration documentation](config_logging).
## Starting and Stopping
-If you are using the **uWSGI + Webless job handlers** deployment strategy or want to run your Galaxy server as a
-persistent service, you can control it through a process manager. The current recommended process manager is
-[Supervisord](http://supervisord.org/). If you are comfortable with systemd and are running a relatively modern Linux
-distribution, you can also configure Galaxy as a service directly in systemd.
+If you want to run your Galaxy server as a persistent service, you can include the `galaxy` script from Galaxy's
+virtualenv in the configuration of your process manager (e.g. systemd). You can then continue using the `galaxyctl` command as usual
+to start/stop/restart Galaxy or follow the logs.
-### Supervisord
+### Transparent restarts
-You can use a supervisord config file like the following or be inspired by [this
-example](https://github.com/galaxyproject/galaxy/blob/dev/contrib/galaxy_supervisor.conf). Be sure to `supervisord
-update` or `supervisord reread && supervisord restart` whenever you make configuration changes.
-
-```ini
-[program:web]
-command = /srv/galaxy/venv/bin/uwsgi --yaml /srv/galaxy/config/galaxy.yml
-directory = /srv/galaxy/server
-umask = 022
-autostart = true
-autorestart = true
-startsecs = 10
-stopwaitsecs = 65
-user = galaxy
-numprocs = 1
-stopsignal = INT
-```
-
-This configuration defines a "program" named `web` which represents our Galaxy uWSGI frontend. You'll notice that we've
-set a command, a directory, a umask, all of which you should be familiar with. Additionally we've specified that the
-process should `autostart` on boot, and `autorestart` if it ever crashes. We specify `startsecs` to say "the process
-must stay up for this long before we consider it OK. If the process crashes sooner than that (e.g. bad changes you've
-made to your local installation) supervisord will try again a couple of times to restart the process before giving up
-and marking it as failed. This is one of the many ways supervisord is much friendly for managing these sorts of tasks.
-
-The value of `stopwaitsecs` should be at least as large as the smallest value of uWSGI's `reload-mercy`,
-`worker-reload-mercy`, and `mule-reload-mercy` options, all of which default to `60`.
-
-If using the **uWSGI + Webless** strategy, you'll need to addtionally define job handlers to start. There's no simple
-way to activate a virtualenv when using supervisor, but you can simulate the effects by setting `$PATH` and
-`$VIRTUAL_ENV`:
-
-```ini
-[program:handler]
-command = /srv/galaxy/venv/bin/python ./scripts/galaxy-main -c /srv/galaxy/config/galaxy.yml --server-name=handler%(process_num)s --pid-file=/srv/galaxy/var/handler%(process_num)s.pid --log-file=/srv/galaxy/log/handler%(process_num)s.log
-directory = /srv/galaxy/server
-process_name = handler%(process_num)s
-numprocs = 3
-umask = 022
-autostart = true
-autorestart = true
-startsecs = 15
-stopwaitsecs = 35
-user = galaxy
-environment = VIRTUAL_ENV="/srv/galaxy/venv",PATH="/srv/galaxy/venv/bin:%(ENV_PATH)s"
-```
-
-This is similar to the "web" definition above, however, you'll notice that we use `%(process_num)s`. That's a variable
-substitution in the `command` and `process_name` fields. We've set `numprocs = 3`, which says to launch three handler
-processes. Supervisord will loop over `0..numprocs` and launch `handler0`, `handler1`, and `handler2` processes
-automatically for us, templating out the command string so each handler receives a different log file and name.
-
-The value of `stopwaitsecs` should be at least as large as `monitor_thread_join_timeout * runner_plugin_count`, which
-is `30` in the default configuration (`monitor_thread_join_timeout` is a Galaxy configuration option and
-`runner_plugin_count` is the number of ``s in your `job_conf.xml`).
-
-Lastly, collect the tasks defined above into a single group. If you are not using webless handlers this is as simple as:
-
-```ini
-[group:galaxy]
-programs = web
-```
-
-With webless handlers, it is:
-
-```ini
-[group:galaxy]
-programs = web, handler
-```
-
-This will let us manage these tasks more globally with the `supervisorctl` command line tool:
-
-```console
-# supervisorctl status
-galaxy:handler0 RUNNING pid 7275, uptime 16:32:17
-galaxy:handler1 RUNNING pid 7276, uptime 16:32:17
-galaxy:handler2 RUNNING pid 7277, uptime 16:32:17
-galaxy:web RUNNING pid 7299, uptime 16:32:16
-```
-
-This command shows us the status of our jobs, and we can easily restart all of the processes at once by naming the
-group. Familiar commands like start and stop are also available.
-
-```console
-# supervisorctl restart galaxy:
-galaxy:handler0: stopped
-galaxy:handler1: stopped
-galaxy:handler2: stopped
-galaxy:web: stopped
-galaxy:web: started
-galaxy:handler0: started
-galaxy:handler1: started
-galaxy:handler2: started
-```
+For zero-downtime restarts use the command `galaxyctl graceful`.
### Systemd
-Sample **uWSGI + Webless** strategy for systemd. More information on systemd.service environment
-settings can be found in the [documentation](http://0pointer.de/public/systemd-man/systemd.exec.html#Environment=)
-
+This is a sample config for systemd. More information on systemd.service environment
+settings can be found in the [documentation](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Environment=)
+The filename follows the pattern `.service`. In this case we will use `galaxy.service`
```ini
[Unit]
-Description=Galaxy web handler
+Description=Galaxy processes
After=network.target
After=time-sync.target
@@ -792,50 +525,15 @@ Group=galaxy
Restart=on-abort
WorkingDirectory=/srv/galaxy/server
TimeoutStartSec=10
-ExecStart=/srv/galaxy/venv/bin/uwsgi --yaml /srv/galaxy/config/galaxy.yml
+ExecStart=/srv/galaxy/venv/bin/galaxy --state-dir /srv/galaxy/database/gravity
Environment=VIRTUAL_ENV=/srv/galaxy/venv PATH=/srv/galaxy/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
[Install]
WantedBy=multi-user.target
```
-For multiple handlers, the service file needs to be a [template unit](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Description>) - the filename follows the syntax
-`@.service` and all instances of `%I` in the service file are replaced with the ``
+We can now enable and start the the Galaxy services with systemd:
-```ini
-[Unit]
-Description=Galaxy job handlers
-After=network.target
-After=time-sync.target
-
-[Service]
-PermissionsStartOnly=true
-Type=simple
-User=galaxy
-Group=galaxy
-Restart=on-abort
-WorkingDirectory=/srv/galaxy/server
-TimeoutStartSec=10
-ExecStart=/srv/galaxy/venv/bin/python ./scripts/galaxy-main -c /srv/galaxy/config/galaxy.yml --server-name=handler%I --log-file=/srv/galaxy/log/handler%I.log
-#Environment=VIRTUAL_ENV=/srv/galaxy/venv PATH=/srv/galaxy/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
-[Install]
-WantedBy=multi-user.target
-```
-
-We can now enable and start the web services with systemd
```console
-# systemctl enable galaxy-web
-Created symlink from /etc/systemd/system/multi-user.target.wants/galaxy-web.service to /etc/systemd/system/galaxy-web.service.
-# systemctl enable galaxy-handler@{0..3}
-Created symlink from /etc/systemd/system/multi-user.target.wants/galaxy-handler@0.service to /etc/systemd/system/galaxy-handler@.service.
-Created symlink from /etc/systemd/system/multi-user.target.wants/galaxy-handler@1.service to /etc/systemd/system/galaxy-handler@.service.
-Created symlink from /etc/systemd/system/multi-user.target.wants/galaxy-handler@2.service to /etc/systemd/system/galaxy-handler@.service.
-Created symlink from /etc/systemd/system/multi-user.target.wants/galaxy-handler@3.service to /etc/systemd/system/galaxy-handler@.service.
-# systemctl start galaxy-handler@{0..3}
-# systemctl start galaxy-web
+# systemctl enable galaxy
+Created symlink from /etc/systemd/system/multi-user.target.wants/galaxy.service to /etc/systemd/system/galaxy.service.
```
-
-### Transparent Restart - Zerg Mode
-
-The standard uWSGI operation mode allows you to restart the Galaxy application while blocking client connections. Zerg Mode does away with the waiting by running a special Zerg Pool process, and connecting Zergling workers (aka Galaxy application processes) to the pool. As long as at least one is connected, requests can be served.
-
-See the [GCC2017 Admin Training session](https://github.com/galaxyproject/dagobah-training/blob/2017-montpellier/sessions/10-uwsgi/ex2-zerg-mode.md) on how to set this up.
diff --git a/doc/source/admin/special_topics/index.rst b/doc/source/admin/special_topics/index.rst
index 2f904d28fa5..834a686d052 100644
--- a/doc/source/admin/special_topics/index.rst
+++ b/doc/source/admin/special_topics/index.rst
@@ -7,7 +7,6 @@ Special Topics
ftp
interactivetools
- interactive_environments
mulled_containers
grt
gtn
diff --git a/doc/source/admin/special_topics/interactive_environments.png b/doc/source/admin/special_topics/interactive_environments.png
deleted file mode 100644
index 49a31646fd8..00000000000
Binary files a/doc/source/admin/special_topics/interactive_environments.png and /dev/null differ
diff --git a/doc/source/admin/special_topics/interactive_environments.rst b/doc/source/admin/special_topics/interactive_environments.rst
deleted file mode 100644
index c8d87b9d615..00000000000
--- a/doc/source/admin/special_topics/interactive_environments.rst
+++ /dev/null
@@ -1,300 +0,0 @@
-Galaxy Interactive Environments
-===============================
-
-A GIE is a Docker container, launched by Galaxy, proxied by Galaxy, with some
-extra sugar inside the container to allow users to interact easily with their
-Galaxy histories.
-
-How GIEs Work
--------------
-
-A GIE is primarily composed of a Docker container, and the Galaxy visualization
-component. Galaxy visualization plugins are rendered using Mako templates and
-Mako templates in turn can run Python code. GIEs build upon visualization plugins,
-adding features to allow for container management and proxying. This Python code
-in the Mako templates is used to launch the Docker container within which a GIE
-runs. Once this container is launched, we notify a proxy built into Galaxy which
-helps coordinate a 1:1 mapping of users and their docker containers.
-
-Here's a simple diagram recapping the above:
-
-.. image:: interactive_environments.png
-
-Deploying GIEs
---------------
-
-Deploying GIEs is not a trivial operation. They have complex interactions with
-numerous services, you'll need to be a fairly competent SysAdmin to debug all
-of the possible problems that can occur during deployment. After the initial
-hurdle, most find that GIEs require little to no maintenance.
-
-An `Ansible `__ role for installing and managing GIEs
-can be found on
-`Github `__
-and `Ansible Galaxy `__.
-
-Setting up the Proxy
-^^^^^^^^^^^^^^^^^^^^
-
-The Galaxy IE Proxy is a NodeJS+Sqlite3 application. The NodeJS that is
-installed by default into the Galaxy Virtualenv is suitable for an execution
-environment for the Galaxy IE Proxy.
-
-- Note that if you have NodeJS installed under Ubuntu, it often installs to
- ``/usr/bin/nodejs``, whereas ``npm`` expects it to be ``/usr/bin/node``. You
- may need to create that symlink yourself.
-
-Once Node and npm are ready to go, you'll need to install the dependencies
-
-.. code-block:: console
-
- $ cd $GALAXY_ROOT/lib/galaxy/web/proxy/js
- $ npm install
-
-Running ``node lib/main.js --help`` should produce some useful help text
-
-.. code-block:: console
-
- Usage: main [options]
-
- Options:
-
- -h, --help output usage information
- -V, --version output the version number
- --ip Public-facing IP of the proxy
- --port Public-facing port of the proxy
- --cookie Cookie proving authentication
- --sessions Routes file to monitor
- --verbose
-
-There are two ways to handle actually running the proxy. The first is to have
-Galaxy automatically launches the proxy as needed. This is the default configuration
-as of 2014. Alternately, the proxy can be stated manually or via a system such as
-Supervisord. Assuming that the ``$GALAXY_ROOT`` environment variable refers to the location of
-the Galaxy installation, the command for launching the proxy is:
-
-.. code-block:: console
-
- $ node $GALAXY_ROOT/lib/galaxy/web/proxy/js/lib/main.js --ip 0.0.0.0 \
- --port 8800 --sessions $GALAXY_ROOT/database/session_map.sqlite \
- --cookie galaxysession --verbose
-
-And this can be configured in your supervisord config by adding:
-
-.. code-block:: console
-
-
- [program:galaxy_nodejs_proxy]
- directory = GALAXY_ROOT
- command = GALAXY_ROOT/lib/galaxy/web/proxy/js/lib/main.js --sessions database/session_map.sqlite --ip 0.0.0.0 --port 8800
- autostart = true
- autorestart = unexpected
- user = GALAXY_USER
- startsecs = 5
- redirect_stderr = true
-
-where ``GALAXY_ROOT`` is the location of your Galaxy installation and ``GALAXY_USER`` is the username of the user that
-Galaxy runs as.
-
-Configuring the Proxy
-^^^^^^^^^^^^^^^^^^^^^
-
-Configuration is all managed in ``galaxy.yml``. The default arguments used
-for the proxy are:
-
-.. code-block:: yaml
-
- dynamic_proxy_manage: true
- dynamic_proxy_session_map: database/session_map.sqlite
- dynamic_proxy_bind_port: 8800
- dynamic_proxy_bind_ip: 0.0.0.0
- dynamic_proxy_debug: true
-
-As you can see most of these variables map directly to the command line
-arguments to the NodeJS script. There are a few extra parameters which will
-be needed if you run Galaxy behind an upstream proxy like nginx or
-Apache:
-
-.. code-block:: yaml
-
- dynamic_proxy_external_proxy: true
- dynamic_proxy_prefix: gie_proxy
-
-The first option says that you have Galaxy and the Galaxy NodeJS proxy wrapped
-in an upstream proxy like Apache or NGINX. This will cause Galaxy to connect
-users to the same port as Galaxy is being served on (so 80/443), rather than
-directing them to port 8800.
-
-The second option is closely entertwined with the first option. When Galaxy is
-accessed, it sets a cookie called ``galaxysession``. This cookie generally cannot be sent with requests
-to different domains and different ports, so Galaxy and the dynamic proxy must
-be accessible on the same port and protocol. In addition, the cookie is only
-accessible to URLs that share the same prefix as the Galaxy URL. For example,
-if you're running Galaxy under a URL like ``https://f.q.d.n/galaxy/``, the cookie
-is only accessible to URLs that look like ``https://f.q.d.n/galaxy/*``. The
-second (``dynamic_proxy_prefix``) option sets the URL path that's used to
-differentiate requests that should go through the proxy to those that should go
-to Galaxy. You will need to add special upstream proxy configuration to handle
-this, and you'll need to use the same ``dynamic_proxy_prefix`` in your
-``galaxy.yml`` that you use in your URL routes.
-
-In the examples below, we assume that your Galaxy installation is available
-at a URL such as ``https://f.q.d.n/galaxy``. If instead it is available at a
-URL like ``https://f.q.d.n``, remove the ``/galaxy`` prefix from the examples.
-For example ``/galaxy/gie_proxy`` would become ``/gie_proxy``. Remember that
-``gie_proxy`` is the value you use for the ``dynamic_proxy_prefix`` option. If
-you use a different value in that option you should change the examples
-accordingly.
-
-**Apache**
-
-.. code-block:: apache
-
- # Project Jupyter specific. Other IEs may require their own routes.
- ProxyPass /galaxy/gie_proxy/jupyter/ipython/api/kernels ws://localhost:8800/galaxy/gie_proxy/jupyter/ipython/api/kernels
-
- # Global GIE configuration
- ProxyPass /galaxy/gie_proxy http://localhost:8800/galaxy/gie_proxy
- ProxyPassReverse /galaxy/gie_proxy http://localhost:8800/galaxy/gie_proxy
-
- # Normal Galaxy configuration
- ProxyPass /galaxy http://localhost:8000/galaxy
- ProxyPassReverse /galaxy http://localhost:8000/galaxy
-
-Please note you will need to be using apache2.4 with ``mod_proxy_wstunnel``.
-
-**Nginx**
-
-.. code-block:: nginx
-
- # Global GIE configuration
- location /galaxy/gie_proxy {
- proxy_pass http://localhost:8800/galaxy/gie_proxy;
- proxy_redirect off;
- }
-
- # Project Jupyter specific. Other IEs may require their own routes.
- location ~ ^/galaxy/gie_proxy/jupyter/(?[^/]+)/api/kernels(?.*?)$ {
- proxy_pass http://localhost:8800/galaxy/gie_proxy/jupyter/$nbtype/api/kernels$rest;
- proxy_redirect off;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
- }
-
-If you proxy static content, you may find the following rule useful for
-proxying to GIE and other visualization plugin static content.
-
-.. code-block:: nginx
-
- location ~ ^/static/plugins/(?.+?)/(?.+?)/static/(?.*?)$ {
- alias /path/to/galaxy-dist/config/plugins/$plug_type/$vis_name/static/$static_file;
- }
-
-Docker on Another Host
-^^^^^^^^^^^^^^^^^^^^^^
-
-You might want to run your IEs on a host different to the one that hosts your
-Galaxy webserver, since IEs on the same host as the webserver compete for
-resources with that webserver and introduce some security considerations which
-could be mitigated by moving containers to a separate host. This feature has
-been available since 15.07 and is used in production at the University of
-Freiburg and on usegalaxy.org.
-
-First you need to configure a second host to be Docker enabled. In the
-following we call this host ``gx-docker`` You need to start the Docker daemon
-and bind it to a TCP port, not to a Unix socket as is the default. For example
-you can start the daemon with
-
-.. code-block:: console
-
- $ docker -H 0.0.0.0:4243 -d
-
-On your client, the Galaxy webserver, you can now install a Docker client. This
-can also be done on older systems like Scientific-Linux, CentOS 6, which do not
-have Docker support by default. The client just talks to the Docker daemon on
-host ``gx-docker``, and does not run anything itself, locally. You can test
-your configuration for example by starting busybox from your client on the
-Docker host with
-
-.. code-block:: console
-
- $ docker -H tcp://gx-docker:4243 run -it busybox sh
-
-So far so good! Note, however, that unless restricted by a firewall, this mode
-of operation is insecure, as any client could connect and run containers on
-``gx-docker``. If this is a concern at your site, follow the instructions in
-the Docker documentation to `Protect the Docker daemon socket
-`__.
-
-Now we need to configure Galaxy to use our new Docker host
-to start the Interactive Environments. For that we need to edit the Jupyter GIE
-configuration, ``jupyter.ini`` to use our custom docker host
-
-.. code-block:: ini
-
- [main]
-
- [docker]
- command = docker -H tcp://gx-docker:4243 {docker_args}
- docker_hostname = gx-docker
-
-Please adapt your ``command`` as needed.
-
-The Jupyter GIE supports getting and fetching Galaxy history datasets entirely
-through the Galaxy API so it is not necessary to share a filesystem with
-``gx-docker``. However, other GIE plugins may still require this.
-
-For those GIE plugins, we need to configure a share mount point between the
-Docker host and Galaxy. Unfortunately, this can not be a NFS mount. Docker does
-not like NFS yet. You could for example use a sshfs mount with the following
-script
-
-.. code-block:: bash
-
- if mount | grep ^gx-docker:/var/tmp/gx-docker; then
- echo "/var/tmp/gx-docker already mounted."
- else
- sshfs gx-docker:/var/tmp/gx-docker /var/tmp/gx-docker
- echo 'Mounting ...'
- fi
-
-This will let Galaxy and the Docker host share temporary files.
-
-Docker Engine Swarm Mode
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-As of Docker Engine version 1.12, Docker Engine can be configured to provide a
-cluster of Docker Engines in a configuration known as *Docker Engine swarm
-mode*. This replaces the previous and similarly named *Docker Swarm*
-clustering solution, which is not compatible with swarm mode.
-
-`The Docker Engine swarm mode documentation
-`__ fully explains the differences, but
-the major difference is that whereas under Docker Swarm one could run commands
-on the swarm with ``docker run``, Docker Engine swarm mode requires one to
-create persistent services with ``docker service create`` and to remove those
-services once no longer in use with ``docker service rm``.
-
-Galaxy supports both Docker Engine swarm mode and the legacy Docker Swarm
-system. Legacy Docker Swarm is supported without any special configuration,
-because the containers are still run with ``docker run`` as before. To support
-Docker Engine swarm mode, additional configuration is required. Begin by
-editing your GIE plugin's ini configuration file (e.g. ``jupyter.ini``) and set
-the ``docker_connect_port`` in addition to any other
-relevant options. Unless you are using a non-standard Docker image, the correct
-value for ``docker_connect_port`` should be suggested to you in the sample
-configuration file:
-
-.. code-block:: ini
-
- [docker]
- docker_connect_port = 8888
-
-Note that your Galaxy server does not need to be a member of the swarm itself.
-It can use the method outlined above in the `Docker on Another Host`_ section
-to connect as a client to a Docker daemon acting as a swarm mode manager.
-
-Once configured, you should see that your GIE containers are started and run as
-services, which you can inspect using the ``docker service ls`` command and
-other ``docker service`` subcommands.
diff --git a/doc/source/admin/special_topics/interactive_environments.rst b/doc/source/admin/special_topics/interactive_environments.rst
new file mode 120000
index 00000000000..454bb916148
--- /dev/null
+++ b/doc/source/admin/special_topics/interactive_environments.rst
@@ -0,0 +1 @@
+../../dev/interactive_environments.rst
\ No newline at end of file
diff --git a/doc/source/admin/special_topics/interactive_environments.svg b/doc/source/admin/special_topics/interactive_environments.svg
deleted file mode 100644
index 55c81e4c55f..00000000000
--- a/doc/source/admin/special_topics/interactive_environments.svg
+++ /dev/null
@@ -1,2536 +0,0 @@
-
-
-
-
diff --git a/doc/source/admin/special_topics/interactivetools.rst b/doc/source/admin/special_topics/interactivetools.rst
index 3e1e70e93a4..1bea5ac37ca 100644
--- a/doc/source/admin/special_topics/interactivetools.rst
+++ b/doc/source/admin/special_topics/interactivetools.rst
@@ -1,3 +1,5 @@
+.. _interactivetools:
+
Galaxy InteractiveTools
=======================
@@ -42,52 +44,74 @@ Some important benefits of using Galaxy InteractiveTools
Server-side configuration of Galaxy InteractiveTools
----------------------------------------------------
+For production deployments and additional considerations please see the `Galaxy Interactive Tools Tutorial `__.
+
The ``galaxy.yml`` file will need to be populated as seen in
``config/galaxy.yml.interactivetools``.
-Galaxy InteractiveTool routing relies on wildcard subdomain routes. For users
-who manage their own DNS, you can set the appropriate A records to redirect
-``*.interactivetool.yourdomain``, following format seen below.
+Galaxy InteractiveTool routing relies on wildcard subdomain routes and a proxy server that forwards requests to a running container.
+For users who manage their own DNS, you can set the appropriate A records to redirect
+``*.interactivetool.yourdomain``.
-It's not recommended for production, but for a quick local deployment
-``localhost.blankenberglab.org`` is a domain record provided by Dan Blankenberg
-(a Galaxy contributor and the architect of ITs) configured with the appropriate
-wildcard redirect to 127.0.0.1, which you can use that in place of
-```` to resolve to your local machine.
+`gravity` will automatically start the needed proxy server.
-In the ``uwsgi:`` section:
+The following configuration is only recommended for local testing, as users will directly connect to the InteractiveTool Proxy.
+In a production setup an upstream proxy should route requests to the proxy via the ``*.interactivetool.yourdomain`` subdomain.
+
+Set these values in `galaxy.yml`:
.. code-block:: yaml
- http-raw-body: true
- # master: true
-
- interactivetools_map: database/interactivetools_map.sqlite
- python-raw: scripts/interactivetools/key_type_token_mapping.py
- route-host: ^([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)-([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\.([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\.(interactivetool\.:8080)$ goto:interactivetool
- route-run: goto:endendend
- route-label: interactivetool
- route-host: ^([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)-([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\.([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\.(interactivetool\.:8080)$ rpcvar:TARGET_HOST rtt_key_type_token_mapper_cached $1 $3 $2 $4 $0 5
- route-if-not: empty:${TARGET_HOST} httpdumb:${TARGET_HOST}
- route: .* break:404 Not Found
- route-label: endendend
+ gravity:
+ # ...
+ gx_it_proxy:
+ enable: true
+ proxy_port: 4002
+ galaxy:
+ # ...
+ interactivetools_enable: true
+ interactivetools_map: database/interactivetools_map.sqlite
+ galaxy_infrastructure_url: http://localhost:8080
+ # Do not set the following 2 options if you are using an upstream proxy server like nginx
+ interactivetools_upstream_proxy: false
+ interactivetools_proxy_host: localhost:4002
+ # ...
-In the ``galaxy:`` section:
+If you do want to use nginx as an upstream proxy server you can use the following server section to route requests to the InteractiveTool proxy:
-.. code-block:: yaml
+.. code-block:: nginx
- interactivetools_enable: true
- interactivetools_map: database/interactivetools_map.sqlite
- galaxy_infrastructure_url: http://.org:8080
+ server {
+ # Listen on port 443
+ listen *:443 ssl;
+ # Match all requests for the interactive tools subdomain
+ server_name *.interactivetool.localhost;
+
+ # Proxy all requests to the GIE Proxy application
+ location / {
+ proxy_redirect off;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_pass http://localhost:4002;
+ }
+ }
-The admin should modify the ``route-host`` and ``interactivetools_prefix`` to match their preferred configuration.
+Note that this nginx example uses https, so you need to have a wildcard certificate for your domain,
+and you need to adjust ``galaxy_infrastructure_url`` as appropriate. You will most likely also want
+to replace localhost with your server domain.
+You will also need to enable a docker destination in the job_conf.xml file.
An example ``job_conf.xml`` file as seen in ``config/job_conf.xml.interactivetools``:
.. code-block:: xml
+
+
@@ -96,11 +120,23 @@ An example ``job_conf.xml`` file as seen in ``config/job_conf.xml.interactivetoo
true
+
$galaxy_root:ro,$tool_directory:ro,$job_directory:rw,$working_directory:rw,$default_file_path:ro
false
bridge
true
true
+ true
+
+
+ --add-host localhost:host-gateway
docker_dispatch
@@ -108,10 +144,11 @@ An example ``job_conf.xml`` file as seen in ``config/job_conf.xml.interactivetoo
local
-
+
-Alternatively to the local job runner, InteractiveTools have been enabled for the condor job runner, e.g.:
+InteractiveTools have been enabled for the Condor, Slurm, Pulsar and Kuberneters job runner.
+A destination configuration for Condor may look like this:
.. code-block:: xml
diff --git a/doc/source/admin/special_topics/performance_tracking.rst b/doc/source/admin/special_topics/performance_tracking.rst
index e500cca698b..e6a420a7fae 100644
--- a/doc/source/admin/special_topics/performance_tracking.rst
+++ b/doc/source/admin/special_topics/performance_tracking.rst
@@ -2,44 +2,22 @@ Galaxy Performance Tracking
===========================
Tracking performance over time and identifying slow queries in your Galaxy can be an extremely important thing to do, especially for larger Galaxies.
+[A more in-depth tutorial is available at the Galaxy Training Network](https://training.galaxyproject.org/training-material/topics/admin/tutorials/monitoring/tutorial.html).
-Most performance tracking requires sending metrics to a metrics collection server such as `Graphite `__ or `StatsD `__. This document assumes you have already deployed a metrics server.
+Most performance tracking requires sending metrics to a metrics collection server such as `StatsD `__. This document assumes you have already deployed StatsD.
-uWSGI
+Gunicorn
-----
-There is some built-in uWSGI support for performance logging. You can send uWSGI's internal metrics to a carbon (Graphite) server by setting the carbon option in your galaxy.yml:
+There is some built-in `Gunicorn `__ support for performance logging. You can send Gunicorn's internal metrics to a StatsD server by setting the `--statsd-host` and `--statsd-prefix` command line options for Gunicorn in the `gravity` section of `galaxy.yml`:
.. code-block:: yaml
- uwsgi:
- socket: ...
- carbon: 127.0.0.1:2003
-
-Or a StatsD server via:
-
-.. code-block:: yaml
-
- uwsgi:
- socket: ...
- stats-push: statsd:127.0.0.1:8125
-
-The `official documentation `__ contains further information on uWSGI and stats servers. In the `uWSGI Stats Server `__ documentation, you can see an example of the sort of information that you will be able to collect. Note that you will need to make sure that the statsd pusher plugin is activated in your uWSGI servers.
-
-Alternatively, you can use `gxadmin `__ to generate data ready to load in an InfluxDB database. In this case, you will need to add the stats option to your galaxy.yml:
-
-.. code-block:: yaml
-
- uwsgi:
- socket: ...
- stats: 127.0.0.1:9191
-
-And then run gxadmin like this:
-
-
-.. code-block:: bash
-
- gxadmin uwsgi stats_influx 127.0.0.1:9191
+ gravity:
+ ...
+ gunicorn:
+ gunicorn_extra_args: `--statsd-host 127.0.0.1:8125 --statsd-prefix=gunicorn`
+ ...
API / Route Timing Statistics
-----------------------------
diff --git a/doc/source/admin/special_topics/vault.md b/doc/source/admin/special_topics/vault.md
index 6dee3563ec5..2c104eec37b 100644
--- a/doc/source/admin/special_topics/vault.md
+++ b/doc/source/admin/special_topics/vault.md
@@ -85,6 +85,7 @@ Fernet key, use the following Python code:
```python
from cryptography.fernet import Fernet
Fernet.generate_key().decode('utf-8')
+```
If multiple encryption keys are defined, only the first key is used to encrypt secrets. The remaining keys are tried in turn during decryption. This is useful for key rotation.
We recommend periodically generating a new fernet key and rotating old keys. However, before removing an old key, make sure that any data encrypted using that old key is no longer
diff --git a/doc/source/dev/index.rst b/doc/source/dev/index.rst
index 5741b5488e6..afe39081eee 100644
--- a/doc/source/dev/index.rst
+++ b/doc/source/dev/index.rst
@@ -23,6 +23,5 @@ A multi-hour long video playlist covering these slides can be found at
debugging_tests
debugging_galaxy
debugging_galaxy_slurm
- starting_galaxy
file_upload
translating
diff --git a/doc/source/dev/interactive_environments.rst b/doc/source/dev/interactive_environments.rst
index 99d8f190f60..e7eb5462657 100644
--- a/doc/source/dev/interactive_environments.rst
+++ b/doc/source/dev/interactive_environments.rst
@@ -1,548 +1,5 @@
-Build an Interactive Environment
-================================
+Interactive Environments
+=========================
-Unfortunately building a Galaxy Interactive Environment (GIE) isn't completely straightforward, and it's
-certainly not as simple as picking out an existing container and plugging it
-in. Here we'll go through build a "Hello, World" GIE which just displays a file
-from a user's history.
-
-Directory Layout
-----------------
-
-The GIE directory layout looks identical to that of normal visualization
-plugins, for those familiar with developing those
-
-.. code-block:: console
-
-
- $ tree config/plugins/interactive_environments/jupyter/
- config/plugins/interactive_environments/jupyter/
- ├── config
- │ ├── allowed_images.yml.sample
- │ ├── jupyter.ini.sample
- │ └── jupyter.xml
- ├── static
- │ └── js
- │ └── jupyter.js
- └── templates
- └── jupyter.mako
-
-We'll use the variable ``{gie}`` to stand in for the name of your GIE. It
-should match ``[a-z]+``, like ``jupyter`` or ``rstudio``. Here you can see the
-``config/`` directory with a ``{gie}.ini.sample`` providing docker and image
-configuration, ``allowed_images.yml.sample`` specifies acceptable images,
-and then ``{gie}.xml`` which outlines that it is a GIE.
-
-The static directory can hold resources such as JavaScript and CSS files. If
-you are actively developing a GIE, you'll need to restart Galaxy after adding
-any resources to that file, before they can be accessed in the browser.
-
-Lastly, and most importantly, there's the templates folder. This normally just
-contains ``{gie}.mako``, however the Jupyter file needs an extra template file.
-
-First Steps, Configuration
---------------------------
-
-We will name our GIE "helloworld", but you are free to name your's differently.
-We'll first need to create the directory structure and set up our
-configuration
-
-.. code-block:: console
-
- $ mkdir -p $GALAXY_ROOT/config/plugins/interactive_environments/helloworld/{config,static,templates}
- $ cd $GALAXY_ROOT/config/plugins/interactive_environments/helloworld/
-
-Next, you'll need to create the GIE plugin XML file ``config/helloworld.xml``
-
-.. code-block:: xml
-
-
-
-
-
-
-
- HistoryDatasetAssociation
-
-
- tabular.Tabular
- data.Text
- dataset_id
-
-
-
- dataset_id
-
-
- helloworld.mako
-
-
-Once this is done, we can set up our INI file, ``config/helloworld.ini.sample`` which controls docker interaction
-
-.. code-block:: ini
-
- [main]
- # Unused
-
- [docker]
- # Command to execute docker. For example `sudo docker` or `docker-lxc`.
- #command = docker {docker_args}
-
- # The image argument was moved to "allowed_images.yml.sample"
-
- # Additional arguments that are passed to the `docker run` command.
- #command_inject = --sig-proxy=true -e DEBUG=false
-
- # URL to access the Galaxy API with from the spawn Docker container, if empty
- # this falls back to galaxy.ini's galaxy_infrastructure_url and finally to the
- # Docker host of the spawned container if that is also not set.
- #galaxy_url =
-
- # The Docker hostname. It can be useful to run the Docker daemon on a different
- # host than Galaxy.
- #docker_hostname = localhost
-
- # Try to set the temp directory to world execute - this can fix the issue
- # where 'sudo docker' is not able to mount the folder otherwise.
- # "finalize namespace chdir to /import permission denied"
- #wx_tempdir = False
-
- # Overwrite the IE temp directory. This can be useful if you regular tempdir is
- # located on an NFS share, which does not work well as Docker volume. In this case
- # you can have a shared sshfs share which you can use as temporary directory to
- # share data between the IE and Galaxy.
- #docker_galaxy_temp_dir = None
-
- # If your Docker container exposes more then one port, Galaxy needs to know to
- # which ports it needs to connect. With this option you can specify the port number
- # inside your container to which Galaxy should connect the UI.
- #docker_connect_port = None
-
- # Set the following value to false if Docker volumes between Galaxy server and Docker
- # container cannot or should not be used.
- #use_volumes = True
-
-You'll then need to create the GIE plugin YML file ``allowed_images.yml.sample``
-to specify allowed images
-.. code-block::
-
- # This file lists acceptable images to allow running.
- #
- # This allows you, the admin, to create multiple flavours
- # for your users to run. E.g. maybe you need a geosciences flavour,
- # you can create the image based on our default image and add the
- # appropriate `apt-get/pip install` statements.
- ---
- -
- image: hello-ie
- description: |
- hello-ie is for getting you up to speed with
- IE development.
-
-We've named our image ``hello-ie``, we'll get to creating that in a minute.
-
-Mako Templates
---------------
-
-Mako templates are very easy to use, and they allow significantly more
-flexibility than many other templating languages. It's because of this
-flexibility (and ability to write plain python code in them) that GIEs were
-possible to develop easily.
-
-In our ``templates/helloworld.mako``, we'll add the following
-
-.. code-block:: html+mako
-
- <%namespace name="ie" file="ie.mako" />
-
-This line says to inherit from the ``ie.mako`` file that's available in
-``$GALAXY_ROOT/config/plugins/interactive_environments/common/templates/ie.mako``.
-Next we'll add the following
-
-.. code-block:: html+mako
-
- <%
- # Sets ID and sets up a lot of other variables
- ie_request.load_deploy_config()
-
- # Define a volume that will be mounted into the container.
- # This is a useful way to provide access to large files in the container,
- # if the user knows ahead of time that they will need it.
- user_file = ie_request.volume(
- hda.file_name, '/import/file.dat', mode='ro')
-
- # Launch the IE. This builds and runs the docker command in the background.
- ie_request.launch(
- volumes=[user_file],
- env_override={
- 'custom': '42'
- }
- )
-
- # Only once the container is launched can we template our URLs. The ie_request
- # doesn't have all of the information needed until the container is running.
- url = ie_request.url_template('${PROXY_URL}/helloworld/')
- %>
-
-That mako snippet loaded the configuration from the INI files, launched the
-docker container, and then built a URL to the correct endpoint, through the
-Galaxy NodeJS proxy. Additionally we've set an environment variable named ``CUSTOM``
-with the value ``42`` to be passed to the container, and we've attached the dataset the
-user selected (available in ``hda``) to the container as a read-only volume.
-
-We'll continue appending to our ``helloworld.mako`` the HTML code that's actually displayed to the user, when this template is rendered
-
-.. code-block:: html+mako
-
-
-
-
- ${ ie.load_default_js() }
-
- ${ ie.load_default_app() }
-
-
-
-
-
-
-
-
-
-We've glossed over some of the features of this file, but most IEs do a significant amount
-of "magic" in the top half of the mako template. For instance, the Jupyter notebook:
-
-- If the user is trying to run the Jupyter GIE Visualization on an existing notebook in their history, then that gets loaded into the docker container via the temp directory and set as the default notebook
-- Otherwise a default notebook is built for the user.
-
-The RStudio notebook:
-
-- generates a random password and configures the image to use this password
-- Copies in an RData file if the user has loaded one
-- sets some custom environment variables.
-
-
-Connecting the User to the Container via Javascript
----------------------------------------------------
-
-With the mako template above finished, if you were to load this in your
-browser, not a lot would happen because we haven't built the hello-ie image,
-and we haven't used Javascript to connect the user with the container. In the
-tail end of the template, we set a variable ``notebook_access_url``. These are
-partially a legacy of how things used to be done and you're welcome to clean up
-your code according to your desires. Galaxy's NodeJS proxy handles the
-authentication of users, so you don't have to worry about it, and can just
-assume that only the correct user will have access to a given notebook.
-
-In the ``static/`` directory, we generally create a ``js/`` directory below that,
-and create a ``main.js`` file in there.
-That file will have a function, ``load_notebook`` which will check if the GIE is available,
-and when it is, display it to the user.
-
-We start by writing the load notebook function, which is pretty generic
-
-.. code-block:: javascript
-
- // Globals
- var IES = window.IES;
- // Load an interactive environment (IE) from a remote URL
- // @param {String} notebook_access_url: the URL embeded in the page and loaded
- function load_notebook(notebook_access_url){
- // When the page has completely loaded...
- // Test if we can access the GIE, and if so, execute the function
- // to load the GIE for the user.
- IES.test_ie_availability(notebook_access_url, function(){
- IES.append_notebook(notebook_access_url);
- });
- }
-
-This function will display a spinner to the user to indicate process, make multiple requests
-to ``notebook_access_url`` and display the GIE to the user in an iframe. That MUST return a 200 OK for the ``append_notebook`` function to ever be called. 302s do not count!
-
-Historically, the GIE process involved a complex dance of:
-
-- generating a random password in the mako template
-- setting it as a javascript variable
-- passing it to the docker container
-- once the container was available, have the javascript automatically log a
- user in (something browsers try to prevent since that's otherwise an XSS
- vulnerability.)
-- hope everything worked
-
-You may wish to look at the Jupyter and RStudio GIEs for examples of the complex things that can be done at every step.
-
-The GIE Container
------------------
-
-We'll build a simple container that just displays the dataset a user has
-selected to them. Remember when we attached a volume to the container? We'll
-make use of that now.
-
-GIE Containers (often) consist of:
-
-- Dockerfile
-- NGINX Proxy configuration
-- A custom startup script/entrypoint
-- A script to monitor traffic and kill unused containers
-
-We have to monitor the container's traffic and kill off unused containers,
-because no one is watching them. The user launches the container in Galaxy, and
-Galaxy immediately forgets the container exists. Thus, we say that if a
-container has no connections to TCP connections to itself, then it should
-commit suicide by killing the root process.
-
-Here's an example ``Dockerfile`` for our helloworld container
-
-.. code-block:: dockerfile
-
- FROM alpine
- # These environment variables are passed from Galaxy to the container
- # and help you enable connectivity to Galaxy from within the container.
- # This means your user can import/export data from/to Galaxy.
- ENV DEBIAN_FRONTEND=noninteractive \
- API_KEY=none \
- DEBUG=false \
- PROXY_PREFIX=none \
- GALAXY_URL=none \
- GALAXY_WEB_PORT=10000 \
- HISTORY_ID=none \
- REMOTE_HOST=none \
- DOCKER_PORT=none \
- CORS_ORIGIN-none
-
- RUN apk update && \
- apk add \
- wget procps nginx python py2-pip net-tools nginx git patch
-
- # Our very important scripts. Make sure you've run `chmod +x startup.sh
- # monitor_traffic.sh` outside of the container!
- ADD ./startup.sh /startup.sh
- ADD ./monitor_traffic.sh /monitor_traffic.sh
-
- # /import will be the universal mount-point
- # The Galaxy instance can copy in data that needs to be present to the
- # container
- RUN mkdir -p /import /web/helloworld /run/nginx
-
- # Nginx configuration
- COPY ./proxy.conf /proxy.conf
- COPY ./index.html /web/helloworld/
- RUN chmod ugo+r /web/helloworld/index.html
-
- VOLUME ["/import"]
- WORKDIR /import/
-
- # EXTREMELY IMPORTANT! You must expose a SINGLE port on your container.
- EXPOSE 80
- CMD /startup.sh
-
-If you have questions on this, please feel free to contact us on IRC
-(`irc.freenode.net#galaxyproject `__).
-
-The proxy configuration is interesting, here we'll point NGINX to reverse proxy
-a service running on ``:8000`` inside the container. That port will be hosting
-a python process which serves up the directory contents of ``/import``, i.e.
-the file the user selected which was mounted as a volume into
-``/import/file.dat``
-
-.. code-block:: nginx
-
- events {
- worker_connections 1024;
- }
-
-
- http {
- include mime.types;
- default_type application/octet-stream;
-
- sendfile on;
- keepalive_timeout 65;
-
- server {
- listen 80;
- server_name localhost;
- access_log /var/log/nginx/localhost.access.log;
-
- root /web/;
-
- location PROXY_PREFIX/ {
- alias /web/;
- }
-
- rewrite ^(.*)/helloworld/(.*\.dat)$ PROXY_PREFIX/helloworld/dir/$2;
-
- location PROXY_PREFIX/helloworld/dir/ {
- proxy_buffering off;
- proxy_pass http://127.0.0.1:8000/;
- proxy_redirect http://127.0.0.1:8000/ PROXY_PREFIX/helloworld/dir/;
- }
- }
- }
-
-Below is our ``index.html`` file
-
-.. code-block:: html
-
-
-
-
-
-
Welcome to Hello-World IE
-
- There is one service running, a directory
- listing. (We originally had more but the github repository
- for the flask app we were using disappeared.)
-
-
-
-
-And here we'll run that service in our ``startup.sh`` file
-
-.. code-block:: bash
-
- #!/bin/bash
- # First, replace the PROXY_PREFIX value in /proxy.conf with the value from
- # the environment variable.
- sed -i "s|PROXY_PREFIX|${PROXY_PREFIX}|" /proxy.conf;
- # Then copy into the default location for ubuntu+nginx
- cp /proxy.conf /etc/nginx/sites-enabled/default;
-
- # Here you would normally start whatever service you want to start. In our
- # example we start a simple directory listing service on port 8000
- cd /import/ && python -mSimpleHTTPServer &
-
- # Launch traffic monitor which will automatically kill the container if
- # traffic stops
- /monitor_traffic.sh &
- # And finally launch nginx in foreground mode. This will make debugging
- # easier as logs will be available from `docker logs ...`
- nginx -g 'daemon off;'
-
-Lastly, our ``monitor_traffic.sh`` file is often re-used between containers, the only adjustment being the port that is looked at
-
-.. code-block:: bash
-
- #!/bin/bash
- while true; do
- sleep 60
- if [ `netstat -t | grep -v CLOSE_WAIT | grep ':80' | wc -l` -lt 3 ]
- then
- pkill nginx
- fi
- done
-
-With those files, ``monitor_traffic.sh``, ``Dockerfile``, ``startup.sh``, and ``proxy.conf``, you should be able to build your ``hello-ie`` container
-
-.. code-block:: bash
-
- $ cd hello-ie
- $ docker build -t hello-ie .
-
-Now, if everything went smoothly, you should be able to restart Galaxy and try out your new GIE on a tabular or text file!
-
-Debugging
----------
-
-When you launch your new GIE in Galaxy, your Galaxy logs should show something like the following:
-
-.. code-block:: console
-
- Starting docker container for IE helloworld with command [docker run --sig-proxy=true -e DEBUG=false -e "GALAXY_URL=http://localhost/galaxy/" -e "CORS_ORIGIN=http://localhost" -e "GALAXY_WEB_PORT=8000" -e "HISTORY_ID=f2db41e1fa331b3e" -e "CUSTOM=42" -e "GALAXY_PASTER_PORT=8000" -e "PROXY_PREFIX=/galaxy/gie_proxy" -e "API_KEY=1712364174a0ff79b34e9a78fee3ca1c" -e "REMOTE_HOST=127.0.0.1" -e "USER_EMAIL=hxr@local.host" -d -P -v "/home/hxr/work/galaxy/database/tmp/tmp5HaqZy:/import/" -v "/home/hxr/work/galaxy/database/files/000/dataset_68.dat:/import/file.dat:ro" hello-ie]
-
-Here's the docker command written out in a more readable manner:
-
-.. code-block:: console
-
- $ docker run --sig-proxy=true \
- -d -P \
- -e "API_KEY=1712364174a0ff79b34e9a78fee3ca1c" \
- -e "CORS_ORIGIN=http://localhost" \
- -e "CUSTOM=42" \
- -e "DEBUG=false" \
- -e "GALAXY_PASTER_PORT=8000" \
- -e "GALAXY_URL=http://localhost/galaxy/" \
- -e "GALAXY_WEB_PORT=8000" \
- -e "HISTORY_ID=f2db41e1fa331b3e" \
- -e "PROXY_PREFIX=/galaxy/gie_proxy" \
- -e "REMOTE_HOST=127.0.0.1" \
- -e "USER_EMAIL=hxr@local.host" \
- -v "/home/hxr/work/galaxy/database/tmp/tmp5HaqZy:/import/" \
- -v "/home/hxr/work/galaxy/database/files/000/dataset_68.dat:/import/file.dat:ro" \
- hello-ie
-
-As you can see, a LOT is going on! We'll break it down further:
-
-- ``-d`` runs the container in daemon mode, it launches and the client
- submitting the container finished
-- ``-P`` randomly assigns an unused port to the container for each ``EXPOSE``d
- port from our ``Dockerfile``. This is why you must expose a port, and only
- one port.
-- A large number of environment variables are set:
-
- - The user's API key is provided, allowing you to access datasets and
- submit jobs on their behalf. If you have an environment like
- Jupyter/RStudio, it is **highly recommended** that you provide some magic
- by which the user can use their API key without embedding it in the
- notebook. If you do embed it somehow in a document that gets saved to
- their history, anyone can impersonate that user if they get a hold of it.
- In the Jupyter GIE we have a variable that just runs
- ``os.environ.get('API_KEY')`` to avoid embedding it in their notebook.
- - A CORS Origin is provided for very strict servers, but it may be easier
- to simply void CORS requirements within the nginx proxy in your
- container.
- - Custom variables specified in your ``launch()`` command are available
- - A ``DEBUG`` environment variable should be used to help admins debug
- existing containers. You should use it to increase logging, not cleanup
- temporary files, and so on.
- - ``GALAXY_PASTER_PORT`` (deprecated) and ``GALAXY_WEB_PORT`` are the raw
- port that Galaxy is listening on. You can use this to help decide how to
- talk to Galaxy.
- - ``GALAXY_URL`` is the URL that Galaxy should be accessible at. For
- various reasons this may not be true. We recommend looking at our
- implementation of `galaxy.py
- `__
- which is a small utility script to provide API access to Galaxy to get
- and fetch data, based on those environment variables.
- - The ``HISTORY_ID`` of the current history the user is on is provided. In
- the Jupyter/RStudio containers, we provide a dead simple method for users
- to download datasets from their current history which will be visible to
- them on the right hand side of their screen.
- - A ``PROXY_PREFIX`` is provided which should be used in the nginx conf.
- - ``REMOTE_HOST`` is another component used to test for a possible Galaxy
- access path
- - The user's email is made available, very convenient for webservices like
- Entrez which require the user's email address. You can pre-fill it out
- for them, making their life easier.
- - Two volumes are mounted, one a temporary directory from Galaxy (rw), and one
- the dataset the user selected (ro).
-
-- and finally the image is specified.
-
-Most of this information is usually required to build friendly, easy-to-use
-GIEs. One of the strong points of GIEs is their magic interaction with Galaxy.
-Here we've mounted a volume read-only, but in real life you may wish to provide
-connectivity like Jupyter and RStudio provide, allowing the user to load
-datasets on demand for interactive analysis, and then to store analysis
-artifacts (and a log of what was done inside the container, à la Jupyter's
-"notebooks") back to their current history.
-
-If everything went well, at this point you should see a directory listing show up:
-
-.. image:: interactive_environments_success.png
-
-If you find yourself encountering difficulties, the "Hello, World" IE is
-available in a `GitHub repo `__, and there are people on the IRC channel who can help debug.
+Galaxy Interactive Environments are deprecated and were the precursors to the current :doc:`Galaxy Interactive Tools <../admin/special_topics/interactivetools>`.
+You can find information about Galaxy Interactive Environments in `older versions `__ of this document.
diff --git a/doc/source/dev/interactive_environments_success.png b/doc/source/dev/interactive_environments_success.png
deleted file mode 100644
index 2f881909379..00000000000
Binary files a/doc/source/dev/interactive_environments_success.png and /dev/null differ
diff --git a/doc/source/dev/starting_galaxy.md b/doc/source/dev/starting_galaxy.md
deleted file mode 100644
index 2f8c483f45e..00000000000
--- a/doc/source/dev/starting_galaxy.md
+++ /dev/null
@@ -1,95 +0,0 @@
-# Starting Galaxy
-
-## What happens when you start Galaxy?
-
-Galaxy is started by running ./run.sh script. The following call graph documents what happens during Galaxy startup process. Please note, Galaxy is a WSGI app, so in principle all Python WSGI servers can run the Galaxy app (Paste, Gunicorn and uWSGI are known to work and have some level of support). This document separates web server specific section (e.g. Paste) from Galaxy specific section (FYI, Galaxy uses uWSGI by default).
-
-## Paste
-
-* ./galaxy/scripts/paster.py
- * Add ./galaxy/lib to system path
- * Check Python version
- * version >= 3.5 -> OK
- * version = 2.7 -> Deprecated
- * No other version is supported
- * serve.run()
-
-* ./galaxy/lib/galaxy/util/pastescript/serve.py (The Python Paste package contains Python modules that help in implementing WSGI middleware)
- * serve.run()
- * Parse Python command line arguments
- * Extract the command name from command line arguments (e.g., 'serve')
- * Get the Command object for command name, then invoke it (call Command's run() method)
- * Command.run()
- * Setup default options, validate command line arguments, then call ServeCommand's command() method
- * ServeCommand.command()
- * Conditionally, stop the daemon
- * If a config file is required, make sure a config file is provided on the command line arguments.
- * Possible subcommands: start, stop, restart, status (or None)
- * Call loadserver() method in ./galaxy/lib/galaxy/util/pastescript/loadwsgi.py
- * Calls loadobj() -> calls LoaderContext's create() -> calls _Server's invoke()
- * Call loadapp() method in ./galaxy/lib/galaxy/util/pastescript/loadwsgi.py
- * Calls loadobj() -> calls LoaderContext's create() -> calls _App's invoke() -> calls fix_call() on app_factory (in ./galaxy/lib/galaxy/webapps/galaxy/buildapp.py)
-
-## Galaxy
-
-* app_factory:
- * Create UniverseApplication (in ./galaxy/lib/galaxy/webapps/galaxy/buildapp.py)
- * Create GalaxyAppConfiguration instance from config file specified on the command line, then check for errors
- * Configure logging (in ./galaxy/lib/galaxy/config/__init__.py)
- * Create ExecutionTimerFactory
- * Which has a GalaxyStatsdClient field
- * Configure FluentTraceLogger
- * Create the application stack (uWSGi, Paste, or Webless)
- * App registers post fork functions to start application stack threads
- * Create GalaxyQueueWorker instance (a worker for Galaxy's queues, used for dispatching control tasks. Sqlite instance)
- * Configure tool shed registry
- * Configure object store. build_object_store_from_config() (in ./galaxy/lib/galaxy/objectstore/__init__.py) calls objectstore_class.from_xml(), calls clazz.parse_xml()
- * Configure models in _configure_models()
- * Calls create_or_verify_database() in ./galaxy/libl/galaxy/model/migrate/check.py
- * If a new database, calls migrate_from_scratch() in ./galaxy/libl/galaxy/model/migrate/check.py
- * Calls mapping.init() in ./galaxy/libl/galaxy/model/mapping.py (Details of how data objects are mapped to relational DB tables).
- * Calls init_models_from_config in in ./galaxy/libl/galaxy/model/mapping.py
- * Configure security
- * Set GalaxyTagHandler (in ./galaxy/lib/galaxy/model/tags.py)
- * Handles CRUD operations for tagging datasets, workflows, visualizations, etc
- * Set DatasetCollectionManager (in ./galaxy/lib/galaxy/managers/collections.py)
- * Configure HistoryManager
- * Configure HistoryDatasetAssociation (HDA) Manager
- * Create WorkflowsManager
- * Handles CRUD operations related to workflows
- * Configure DependencyResolverView (a RESTful interface to galaxy.tool_util.deps.DependencyResolver)
- * Configure TestDataResolver
- * Configure LibraryManager (Data libraries under Shared Data)
- * Configure FolderManager (Folders are folders in a data library)
- * Configure DynamicToolManager (Tools that are loaded from DB instead of disk files)
- * Configure DataProviderRegistry
- * Configure JobMetrics manager
- * Configure ErrorReport plugins
- * Configure job management configuration
- * Setup a tool cache
- * Watch various config files for immediate reload
- * Configure Data Manager
- * Configure UpdateRespositoyManager
- * Load proprietary datatype convertors and display applications
- * Configure VisualizationRegistry, ToursRegistry, and WebHookRegistry
- * Load security policy and quota management
- * Configure heartbeat for thread profiling
- * If configured, create Sentry client
- * App registers post fork functions to start Sentry client thread
- * Create JobManager
- * App registers post fork functions to start application job manager thread
- * Job manager thread starts monitor threads for JobHandlerQueue and JobHandlerStopQueue (2 threads)
- * JobManager has a JobHandler field, which manages the preparation, running, tracking, and finishing of jobs
- * JobHandler has a job dispatcher, which launches underlying job runners
- * DefaultJobDispatcher calls app's JobConfiguration's get_job_runner_plugins() to create LocalJobRunner instances
- * The default number of LocalJobRuner instances is 4 (4 threads)
- * JobHandler also has queues for starting and stopping jobs (unless track_jobs_in_database is True)
- * Create WorkflowSchedulingManager
- * Starts workflow request monitor thread in __start_request_monitor() method (1 thread)
- * Configure InteractiveToolManager
- * Create database heartbeat instance
- * App registers post fork functions to start application DB heartbeat thread (1 thread)
- * Create CommunityWebApplication (in ./galaxy/lib/galaxy/webapps/galaxy/buildapp.py)
- * CommunityWebApplication: A WSGI application that maps requests to objects using routes and to methods on those objects
- * Map all requests to controllers/actions
- * Wrap web app in some middleware and return webapp
diff --git a/doc/source/releases/22.01.rst b/doc/source/releases/22.01.rst
new file mode 100644
index 00000000000..730bbdd92ff
--- /dev/null
+++ b/doc/source/releases/22.01.rst
@@ -0,0 +1,971 @@
+
+.. to_doc
+
+22.01
+===============================
+
+Enhancements
+-------------------------------
+
+* Swap to Webpack5
+ `Pull Request 11710`_
+* Remote / Late evaluation of tools
+ `Pull Request 12459`_
+* File sources for gdrive, gcs, onedata, basespace
+ (thanks to `@nuwang `__).
+ `Pull Request 12500`_
+* Add support for caching the Singularity cached images directory
+ `Pull Request 12524`_
+* Various extensions and improvements for asserts
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12528`_
+* New interactive tool - iSEE
+ (thanks to `@neoformit `__).
+ `Pull Request 12650`_
+* Resumable file uploads with tus.io
+ `Pull Request 12656`_
+* Make directory path editable in remote files
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12759`_
+* Display tool source in tool form
+ `Pull Request 12811`_
+* Modify history contents/near endpoint to support new history scroller
+ `Pull Request 12892`_
+* Vault abstraction for Galaxy
+ (thanks to `@nuwang `__).
+ `Pull Request 12940`_
+* Sort icon on List Collection Creator
+ (thanks to `@assuntad23 `__).
+ `Pull Request 12945`_
+* Provide more context for lint context
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12978`_
+* Add mulled-hash command to galaxy-tool-util
+ (thanks to `@simonbray `__).
+ `Pull Request 13061`_
+* Add parquet to csv datatype converter
+ `Pull Request 13078`_
+* XML macros: add named yields, tokenized macros, tokens for attributes, and fix replacement of toplevel yield
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13152`_
+* Enable setting SQLALCHEMY_WARN_20
+ `Pull Request 13171`_
+* Add new datatype GRIB
+ (thanks to `@annefou `__).
+ `Pull Request 13175`_
+* Use Gravity to run Galaxy
+ `Pull Request 13224`_
+* Add datatype iml_dataset subclassing html
+ (thanks to `@knutwa-ext `__).
+ `Pull Request 12099`_
+* Mark sniffer for fastqillumina as not implemented
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12685`_
+* Create sniffer for GRO file type
+ (thanks to `@simonbray `__).
+ `Pull Request 12885`_
+* Agp datatype
+ `Pull Request 12891`_
+* Type updates from @mr-c - part 2
+ (thanks to `@common-workflow-lab `__).
+ `Pull Request 12899`_
+* 3rd round of type updates to support CWL import
+ (thanks to `@common-workflow-lab `__).
+ `Pull Request 12913`_
+* Tighten type ignores
+ (thanks to `@common-workflow-lab `__).
+ `Pull Request 12965`_
+* Remove is_multi_byte
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12996`_
+* Add ludwig model datatype
+ (thanks to `@qiagu `__).
+ `Pull Request 13073`_
+* Add ampvis2 datatype
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13083`_
+* Add Neper and Gmsh datatypes
+ (thanks to `@jj-umn `__).
+ `Pull Request 13087`_
+* Add description of inpcrd and prmtop
+ (thanks to `@thepineapplepirate `__).
+ `Pull Request 13126`_
+* Add compression converter
+ (thanks to `@gallardoalba `__).
+ `Pull Request 13223`_
+* Change display_in_upload to true for PHAR datatype
+ (thanks to `@simonbray `__).
+ `Pull Request 13238`_
+* Add gz as datatype
+ (thanks to `@astrovsky01 `__).
+ `Pull Request 13271`_
+* Limit required element validation to safe elements
+ `Pull Request 13299`_
+* Add phyloseq datatype
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13462`_
+* Allow any format in export tool
+ (thanks to `@astrovsky01 `__).
+ `Pull Request 13151`_
+* Add bioconductor as valid xref for tools
+ (thanks to `@bgruening `__).
+ `Pull Request 13268`_
+* Test cases to verify only admins can import workflows from paths.
+ `Pull Request 12513`_
+* Remove deprecated workflow run path through the API.
+ `Pull Request 12516`_
+* Type updates
+ (thanks to `@common-workflow-lab `__).
+ `Pull Request 12868`_
+* Allow workflows to automatically filter inputs by tag
+ (thanks to `@astrovsky01 `__).
+ `Pull Request 12930`_
+* Enable macros for workflow scheduler config
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13167`_
+* Remove history service worker
+ `Pull Request 12510`_
+* Implement fastAPI prefix handling, run selenium tests against prefix
+ `Pull Request 13103`_
+* Hide form fields and button upon successful submission of bug report
+ `Pull Request 13237`_
+* Fix toolbox cache
+ `Pull Request 13333`_
+* Limit maximum number of discovered files per job
+ `Pull Request 13170`_
+* Fixes for HTML sanitization
+ (thanks to `@abretaud `__).
+ `Pull Request 13059`_
+* Make admin user list sortable by last login
+ (thanks to `@cat-bro `__).
+ `Pull Request 13209`_
+* Support "show all running" in admin job interface
+ `Pull Request 13215`_
+* Add config variable for setting tus upload directory
+ `Pull Request 13313`_
+* Document gunicorn and nginx
+ `Pull Request 13436`_
+* Update interactive tool docs for Gunicorn / dropping uWSGI
+ `Pull Request 13470`_
+* Add Migrating from uWSGI to Gunicorn and FastAPI document
+ `Pull Request 13480`_
+* Support ``--preload`` and worker_id for server processes
+ `Pull Request 13514`_
+* Separated data PVC
+ (thanks to `@almahmoud `__).
+ `Pull Request 12345`_
+* Revised download() so parallel get() is utilized. Small refactor.
+ (thanks to `@kxk302 `__).
+ `Pull Request 12522`_
+* More linting for requirements
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12527`_
+* Preserve important dataset metadata when importing/exporting histories.
+ `Pull Request 12537`_
+* Modify description of the "database" label
+ `Pull Request 12540`_
+* Add Oleg Zharkov to committers group
+ `Pull Request 12544`_
+* Add David López to committers group
+ `Pull Request 12545`_
+* Update container_resolvers_conf.xml.sample
+ (thanks to `@gmauro `__).
+ `Pull Request 12560`_
+* Add test for dataset HTML sanitization interface
+ `Pull Request 12573`_
+* FastAPI: migrate history contents routes
+ (thanks to `@davelopez `__).
+ `Pull Request 12578`_
+* Update localization directive to trim whitepsace around text content.
+ `Pull Request 12580`_
+* Added more caching for github actions which use tox and venv
+ (thanks to `@nuwang `__).
+ `Pull Request 12632`_
+* More typing for API tests (especially test_workflows).
+ `Pull Request 12636`_
+* Better model store abstractions.
+ `Pull Request 12638`_
+* More Python unit test typing fixes.
+ `Pull Request 12647`_
+* Annotate more tests as requiring Github to be online.
+ `Pull Request 12649`_
+* Change logged-in-as to use username
+ (thanks to `@hexylena `__).
+ `Pull Request 12652`_
+* Add buttons to expand and collapse history dataset display in pages
+ `Pull Request 12660`_
+* Formalize dependency of galaxy-data package on galaxy.files module.
+ `Pull Request 12665`_
+* Check types of modules without type annotations in the their signatures on new modules.
+ `Pull Request 12691`_
+* Rev Python tooling to latest mypy release.
+ `Pull Request 12695`_
+* Assorted random typing fixes.
+ `Pull Request 12696`_
+* Add Tag validation in API requests
+ (thanks to `@davelopez `__).
+ `Pull Request 12697`_
+* Framework support for integration tests requiring celery.
+ `Pull Request 12700`_
+* Allow passing Pydantic models as arguments to Celery tasks.
+ `Pull Request 12701`_
+* Discourage the use of true/falsevalue for boolean test parameters
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12706`_
+* Extend debugging test instructions for GHA
+ `Pull Request 12707`_
+* Split integration tests more evenly
+ `Pull Request 12711`_
+* Tool linter: simple test for test params absent from inputs
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12723`_
+* Add test for invoking a workflow on a new autocreated history
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12773`_
+* More Python type fixes from deferred data branch.
+ `Pull Request 12778`_
+* Type fixes for HDAs and LDDAs manager.
+ `Pull Request 12780`_
+* FastAPI: migrate Dataset Collections API
+ (thanks to `@davelopez `__).
+ `Pull Request 12781`_
+* Type fixes for various visualization backend Python files.
+ `Pull Request 12783`_
+* Add various include/exclude patterns for github workflows
+ `Pull Request 12787`_
+* Force strict channel priority when building images with mulled
+ (thanks to `@rhpvorderman `__).
+ `Pull Request 12788`_
+* More type fixes for various pieces of managers code.
+ `Pull Request 12801`_
+* Beta history menu reorg, display fixes.
+ `Pull Request 12802`_
+* More type fixes for managers code.
+ `Pull Request 12812`_
+* Fixes and test for PDF generation.
+ `Pull Request 12813`_
+* Upgrade FastAPI to v0.70.0
+ (thanks to `@davelopez `__).
+ `Pull Request 12836`_
+* Stronger typing of upload code.
+ `Pull Request 12845`_
+* Sync Selenium GitHub workflows
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12849`_
+* Update all Python dependencies
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12858`_
+* Drop legacy uploadpost
+ `Pull Request 12861`_
+* Vuefy color input form element
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12867`_
+* Show error codes when running mypy
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12894`_
+* Update cwltool pin to 3.1.20211107152837
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12895`_
+* Increase directory check specificity, of particular use with AnVIL
+ (thanks to `@luke-c-sargent `__).
+ `Pull Request 12902`_
+* Create codeql-analysis.yml
+ (thanks to `@common-workflow-lab `__).
+ `Pull Request 12908`_
+* Improved Upload Provenance and Correctness
+ `Pull Request 12912`_
+* Update Python dependencies
+ (thanks to `@galaxybot `__).
+ `Pull Request 12916`_
+* Lint for option without text or value
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12921`_
+* FastAPI: migrate datasets API
+ (thanks to `@davelopez `__).
+ `Pull Request 12924`_
+* Vuefy Number and Slider Form inputs
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12937`_
+* Allow labeling of subworkflow outputs in parent workflow
+ `Pull Request 12939`_
+* Linting: check for test expecting failure with outputs
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12960`_
+* Add CWL conformance API tests
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12966`_
+* Allow unit testing tool init to specify paths.
+ (thanks to `@common-workflow-lab `__).
+ `Pull Request 12969`_
+* Lint for inputs with redundant name
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12974`_
+* Support running celery when cwd is not galaxy_root by setting $GALAXY_ROOT_DIR
+ `Pull Request 12977`_
+* Split `run_tool_raw()` out of `BaseDatasetPopulator.run_tool()`
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12994`_
+* Move ``galaxy_tasks`` decorator to ``galaxy.celery``
+ `Pull Request 13000`_
+* Show display applications together with visualizations in center panel
+ `Pull Request 13018`_
+* Update Python dependencies
+ (thanks to `@galaxybot `__).
+ `Pull Request 13029`_
+* Explicit singularity cache
+ (thanks to `@rhpvorderman `__).
+ `Pull Request 13032`_
+* Add "diff-format" Makefile target
+ (thanks to `@common-workflow-lab `__).
+ `Pull Request 13034`_
+* Drop support for Python 3.6, add Python 3.10
+ (thanks to `@nsoranzo `__).
+ `Pull Request 13035`_
+* Allow param_value filter to refer to parameters with multiple values
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13039`_
+* Add support for CWL `CommandLineTool` and `ExpressionTool` to `DynamicToolManager.create_tool()`
+ (thanks to `@nsoranzo `__).
+ `Pull Request 13041`_
+* Update Python dependencies
+ (thanks to `@galaxybot `__).
+ `Pull Request 13051`_
+* Allow admin access to datasets API
+ (thanks to `@davelopez `__).
+ `Pull Request 13060`_
+* Drop non-actionable warnings from LibraryPermissionsWarning
+ `Pull Request 13063`_
+* Beta History: homogeneous collection indication
+ (thanks to `@davelopez `__).
+ `Pull Request 13068`_
+* Add documentation for test/param/metadata in xsd
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13082`_
+* Update Python dependencies
+ (thanks to `@galaxybot `__).
+ `Pull Request 13086`_
+* Add tox environment and GitHub workflow for reports startup test
+ (thanks to `@nsoranzo `__).
+ `Pull Request 13088`_
+* Allow duplicated static options
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13094`_
+* Beta History: additional small fixes at collection level
+ (thanks to `@davelopez `__).
+ `Pull Request 13097`_
+* Add Back button in file source navigation and ftp helper text
+ (thanks to `@itisAliRH `__).
+ `Pull Request 13104`_
+* Add job reports for node types and execution times
+ (thanks to `@gregvonkuster `__).
+ `Pull Request 13121`_
+* Initial typing for model discover module.
+ `Pull Request 13123`_
+* Remove Oleg from committers list
+ `Pull Request 13128`_
+* Remove Dave C. from committers list
+ `Pull Request 13129`_
+* Update Python dependencies
+ (thanks to `@galaxybot `__).
+ `Pull Request 13135`_
+* Fix MetadataValidator
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13139`_
+* Update DatasetError.vue
+ `Pull Request 13148`_
+* Assorted Data Libraries fixes
+ (thanks to `@davelopez `__).
+ `Pull Request 13159`_
+* Provide even more context to the lint context
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13186`_
+* Skip non-Selenium tests if only lib/galaxy_test/selenium is touched
+ `Pull Request 13227`_
+* Add documentation for output action attributes
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13236`_
+* Add openPBS cli support, rebuild CLI test images
+ `Pull Request 13251`_
+* Add missing collection types to xsd doc
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13267`_
+* Update dependencies
+ `Pull Request 13273`_
+* Only create HDAH entries for undeleted HDAs
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13309`_
+* Add version.json for exposing extra api information about docker container
+ (thanks to `@nuwang `__).
+ `Pull Request 13433`_
+* Document gunicorn and apache
+ `Pull Request 13439`_
+* Update jobs and cluster documentation
+ `Pull Request 13440`_
+* Update performance tracking for Gunicorn
+ `Pull Request 13441`_
+* Drop interactive environment build instructions from docs
+ `Pull Request 13442`_
+* Create config package, move app-related functionality to app
+ `Pull Request 13461`_
+* Fix pgcleanup.py for datasets stored by UUID
+ `Pull Request 13474`_
+* Pin gravity to 0.10.0
+ `Pull Request 13483`_
+* Include gravity in sample config
+ `Pull Request 13531`_
+* FastAPI: Histories API migration
+ (thanks to `@davelopez `__).
+ `Pull Request 12386`_
+* Vue component dangling bracket style fix (prettier upgrade)
+ `Pull Request 12428`_
+* Remove unused relationships from model
+ `Pull Request 12468`_
+* Remove workflow API hooks for tool shed.
+ `Pull Request 12512`_
+* Vueify Form Recursion
+ `Pull Request 12518`_
+* FastAPI: Add request wrapper for `SessionRequestContext`
+ (thanks to `@davelopez `__).
+ `Pull Request 12531`_
+* Update SQLAlchemy to 1.4.25
+ `Pull Request 12538`_
+* Establish unittest utils for galaxy-{data,objectstore} packages.
+ `Pull Request 12546`_
+* Move API services to their own package
+ (thanks to `@davelopez `__).
+ `Pull Request 12548`_
+* Establish galaxy-app unit tests.
+ `Pull Request 12549`_
+* Establish galaxy-job-execution unit test directory.
+ `Pull Request 12550`_
+* Establish galaxy-job-metrics unit test directory.
+ `Pull Request 12551`_
+* Fix up small issues around packaging of galaxy-tool-util code.
+ `Pull Request 12552`_
+* Move more webapps unit tests in test/unit/webapps.
+ `Pull Request 12554`_
+* Share a tool_util unittest method via packing to fix up unit test dependencies.
+ `Pull Request 12555`_
+* Better path handling in app unit tests for packaging.
+ `Pull Request 12556`_
+* Selenium abstractions for dataset information.
+ `Pull Request 12569`_
+* TS model: declarative mapping + prep for SQLAlchemy 2.0
+ `Pull Request 12666`_
+* Remove unused script and ``history_delete`` controller endpoint
+ `Pull Request 12668`_
+* Remove ui-table backbone component
+ `Pull Request 12671`_
+* Libraries (legacy) backbone entrypoint and component removal
+ `Pull Request 12674`_
+* Ignore type in unused function
+ `Pull Request 12694`_
+* Misc. fixes for SQLAlchemy 2.0
+ `Pull Request 12698`_
+* Upgrade to lagom 1.4.1
+ (thanks to `@meadsteve `__).
+ `Pull Request 12703`_
+* Remove `galaxy.util.getfullargspec`
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12755`_
+* Convert install_model to declarative mapping
+ `Pull Request 12756`_
+* Mapping tests: restructure, refactor, decouple session and engine, improve
+ `Pull Request 12765`_
+* New pyupgrade cleanups
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12774`_
+* Refactor workflow bookmark
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12810`_
+* Replace boolean input parameter with Vue component in forms
+ `Pull Request 12820`_
+* Replace hidden field input element with Vue
+ `Pull Request 12841`_
+* Refactor datasets API
+ (thanks to `@davelopez `__).
+ `Pull Request 12847`_
+* Vuefy library folder details modal
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12886`_
+* Remove chart utilities and artifacts from code base
+ `Pull Request 12890`_
+* Vuefy DirectoryUri form input field
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12898`_
+* Simplify Augustus datatype sniffer
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12905`_
+* Modify logic in history_contents/near to accommodate scroller
+ `Pull Request 12914`_
+* FastAPI: Add response wrapper for `SessionRequestContext`
+ (thanks to `@davelopez `__).
+ `Pull Request 12929`_
+* Eliminate a lot of while: True loops in datatype code
+ `Pull Request 12942`_
+* Small tweaks to facilitate deferred dataset implementation.
+ `Pull Request 12944`_
+* Modifications to next hid_counter generation
+ `Pull Request 12948`_
+* Don't bind model's MetaData to engine
+ `Pull Request 12949`_
+* Vuefy library dataset
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12950`_
+* Assorted mapping cleanup
+ `Pull Request 12951`_
+* Move `wait_for_invocation_and_jobs()` method to `BaseWorkflowPopulator`
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12954`_
+* Avoid setting response headers through `trans` in datatypes
+ (thanks to `@davelopez `__).
+ `Pull Request 12956`_
+* Use ``lazy="joined"`` instead of ``lazy=False``
+ `Pull Request 12962`_
+* Minor type fixes
+ `Pull Request 12963`_
+* Add type hints to JobHandlerQueue
+ `Pull Request 12976`_
+* Fix flaky legacy API tests (hopefully)
+ (thanks to `@davelopez `__).
+ `Pull Request 12980`_
+* Create select() construct explicitly
+ `Pull Request 12983`_
+* Remove unused dataset conversion code
+ `Pull Request 12991`_
+* Remove unnecessary list creations
+ (thanks to `@nsoranzo `__).
+ `Pull Request 13002`_
+* Don't use triple-quoted strings as comments
+ (thanks to `@nsoranzo `__).
+ `Pull Request 13007`_
+* Misc fixes - round 4
+ (thanks to `@nsoranzo `__).
+ `Pull Request 13026`_
+* Refactor uploadbox / partially remove jQuery
+ `Pull Request 13047`_
+* Initial refactoring to separate History rendering and provider components
+ `Pull Request 13049`_
+* Log missing version file as warning.
+ `Pull Request 13062`_
+* Importing math.inf no longer needs try/except
+ `Pull Request 13065`_
+* Avoid imports of history provider internals
+ `Pull Request 13098`_
+* Drop tool migration scripts and related code
+ `Pull Request 13099`_
+* Remove duplicated pydantic models
+ (thanks to `@davelopez `__).
+ `Pull Request 13125`_
+* Remove migrate tools-related code
+ `Pull Request 13163`_
+* Replace backref with back_populates
+ `Pull Request 13165`_
+* Prevent a future regression
+ `Pull Request 13218`_
+* Remove `jquery.complexify` from everywhere
+ (thanks to `@itisAliRH `__).
+ `Pull Request 13228`_
+* Replace custom tour ids in forms with regular DOM identifiers
+ `Pull Request 13252`_
+* Drop pkg_resources
+ `Pull Request 13454`_
+
+
+Fixes
+-------------------------------
+
+* Large peptide IDs
+ (thanks to `@reid-wagner `__).
+ `Pull Request 13261`_
+* Try to unit test more of DictParser in Viz component.
+ `Pull Request 13385`_
+* Fix jqplot_bar import, adjust plugin hash saving
+ `Pull Request 13493`_
+* Allow trailing semicolon in last column of gff3
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12673`_
+* Fix gff-version header sniffing
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12676`_
+* Fix gff and scidx parsing
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 12687`_
+* Version bump galaxy tool util and converter dependency fix
+ `Pull Request 12844`_
+* Downgrade bowtie requirement for CONVERTER_fasta_to_bowtie_color_index
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12851`_
+* Fix constructive_solid_geometry.py for non_utf8_error
+ (thanks to `@jj-umn `__).
+ `Pull Request 13057`_
+* Show yaml files in preview
+ `Pull Request 13176`_
+* Enable display of BAM data without sequence info
+ (thanks to `@wm75 `__).
+ `Pull Request 13219`_
+* Fix containerized NCBI Datasets Genomes data source tool
+ `Pull Request 12915`_
+* Update interactivetool_pyiron.xml
+ (thanks to `@gmauro `__).
+ `Pull Request 12990`_
+* Add dynamic step to FormNumber range slider
+ (thanks to `@davelopez `__).
+ `Pull Request 13233`_
+* FormNumber: notify value change on slider change
+ (thanks to `@davelopez `__).
+ `Pull Request 13260`_
+* Always display digest in name for refgenie assets.
+ `Pull Request 13403`_
+* Fix `UnboundLocalError` in sort collection tool
+ (thanks to `@davelopez `__).
+ `Pull Request 13429`_
+* Misc fixes - round 2
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12982`_
+* Fix workflow connections for outputs that are not displayed in uploads
+ `Pull Request 13174`_
+* Sync tool identifier string with tool version in workflow editor
+ `Pull Request 13185`_
+* Allow mapping of collection outputs to parameter inputs
+ `Pull Request 13189`_
+* Fix tool id update when updating tool shed tools in editor
+ `Pull Request 13196`_
+* Ensure tool_id/content_id is updated when refactoring workflows
+ (thanks to `@simonbray `__).
+ `Pull Request 13231`_
+* Fix construction of SelectToolParameter default value
+ `Pull Request 13293`_
+* Return actual tool id instead of specified tool id in workflow step
+ `Pull Request 13536`_
+* RxJS major version upgrade, client unit testing enhancements.
+ `Pull Request 12686`_
+* Polyfill overhaul, fixes.
+ `Pull Request 12889`_
+* Fix publicPath and asset handling when using webpack-dev-server for HMR
+ `Pull Request 13155`_
+* Bump markdown-it from 12.2.0 to 12.3.2 in /client
+ `Pull Request 13205`_
+* Bump engine.io from 4.1.1 to 4.1.2 in /client
+ `Pull Request 13206`_
+* Bump follow-redirects from 1.14.4 to 1.14.7 in /client
+ `Pull Request 13207`_
+* Bump log4js from 6.3.0 to 6.4.0 in /client
+ `Pull Request 13225`_
+* Bump nanoid from 3.1.29 to 3.2.0 in /client
+ `Pull Request 13226`_
+* Guard against instance of GenomeIndexToolData
+ `Pull Request 12523`_
+* Fix job runner shutdown
+ `Pull Request 12744`_
+* Fix parsing of yml job conf file in galaxy.dependencies
+ (thanks to `@cat-bro `__).
+ `Pull Request 12893`_
+* Rev pulsar-galaxy-lib.
+ `Pull Request 12896`_
+* Don't pass all Galaxy environment variables to jobs
+ (thanks to `@nsoranzo `__).
+ `Pull Request 13011`_
+* Unit test fixes
+ (thanks to `@nsoranzo `__).
+ `Pull Request 13033`_
+* Fix re-run with rerun_remap_job_id hiding collection
+ `Pull Request 13157`_
+* Fix univa job runner setup without nativeSpecification
+ (thanks to `@Smithsonian `__).
+ `Pull Request 13301`_
+* Make __link_file_check more robust
+ `Pull Request 13316`_
+* Don't record version command as part of command line
+ `Pull Request 13317`_
+* Fix resuming job when job has optional data parameters
+ `Pull Request 13325`_
+* Allow UNIVA destinations without runtime and memory max given in the nativespec
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 13343`_
+* Fix header content-length, add test for send_file
+ `Pull Request 13120`_
+* Add option for disabling tool shed datatypes
+ `Pull Request 13250`_
+* Drop OpenID post authentication protocols
+ `Pull Request 13281`_
+* Restore Metadata size limit
+ `Pull Request 13315`_
+* Drop uWSGI from scaling documentation
+ `Pull Request 13381`_
+* Reimplement collection order test, add wrong order, add `expect_test_failure` attribute
+ (thanks to `@bernt-matthias `__).
+ `Pull Request 10304`_
+* Fix test_sharing_valid_by_id selenium test
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12547`_
+* Update and correct sample object store config file
+ `Pull Request 12571`_
+* Fix ``user_library_import_symlink_allowlist`` option
+ (thanks to `@scholtalbers `__).
+ `Pull Request 12608`_
+* Fix selenium populators to respect the json parameter.
+ `Pull Request 12626`_
+* Fix how beta history panel decides when downloads are available.
+ `Pull Request 12642`_
+* Typing fixes for various unit tests.
+ `Pull Request 12644`_
+* Fix database display for beta history panel.
+ `Pull Request 12646`_
+* Fix deprecation warnings from the `threading` module
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12659`_
+* Join thread that hosts asyncio loop for embedded uvicorn
+ `Pull Request 12710`_
+* Removing unusable Name field from Collections upload
+ (thanks to `@assuntad23 `__).
+ `Pull Request 12736`_
+* Removing last character of pair name for Paired List Collections if it's a . or _
+ (thanks to `@assuntad23 `__).
+ `Pull Request 12739`_
+* Avoid double '/' when generating fully qualified API URLs in API tests
+ (thanks to `@davelopez `__).
+ `Pull Request 12791`_
+* Create new history for anonymous API users via history/current_histor…
+ `Pull Request 12829`_
+* Avoid console error when cloning newly created nodes
+ `Pull Request 12831`_
+* GxITs: don't always add trailing slash to entry point url
+ (thanks to `@abretaud `__).
+ `Pull Request 12833`_
+* fix typo in bookmarking
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12838`_
+* Fix bookmarking workflow twice
+ (thanks to `@OlegZharkov `__).
+ `Pull Request 12840`_
+* Temporary downgrade FastAPI to v0.68.2
+ (thanks to `@davelopez `__).
+ `Pull Request 12856`_
+* Fix startup with edam
+ (thanks to `@abretaud `__).
+ `Pull Request 12860`_
+* Fixes for packages
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12883`_
+* Fix `parse_input_sources()` method to return a list
+ (thanks to `@nsoranzo `__).
+ `Pull Request 12888`_
+* Consider a history not new once there are any items in it
+ `Pull Request 12897`_
+* Bump tensorflow from 2.5.1 to 2.5.2 in /lib/galaxy/dependencies
+ `Pull Request 12900`_
+* Sync package deps with `pyproject.toml`
+ (thanks to `@nsoranzo