Repository navigation
v0.3.0
Pre-releaseThe first release, with the app image, the Helm chart and these notes
published together. It changes almost everything since the last deployed
version (images tagged by date, FOCA 0.12) and the legacy charts (2.x and
3.0.0): proTES now requires FOCA 0.17.0 (or a later 0.17 release) and Python
3.13 or later, requires access tokens, gives each task to the user who
created it, calls TES instances with credentials of its own, can discover
them in a service registry, forwards each task exactly once, tracks tasks
without blocking workers, and has a hardened chart and image. Many of the
changes are breaking: read the upgrade
steps first. See the
documentation for details.
Known limitations of this release:
- per-user limits on stored or unfinished tasks are not available yet
(#285); limit requests at the ingress controller (see "Rate limits" on the
Configuration page of the documentation); - finished tasks are kept until they are deleted by hand: retention is not
available yet (#286); - each task adds two owner rules to the access control database, and FOCA
0.17 loads all rules for each request, so requests slow down as the number
of tasks grows; FOCA 0.18 will cache the policy enforcer; - once
CANCELEDis stored, the resume sweep of the workers ignores the
task: if its tracking is lost afterwards, its final logs may be missing
(see "Task tracking" on the Operations page of the documentation).
Breaking changes
- API: all TES endpoints except
GET /service-inforequire an access token
of a trusted issuer (security.auth.issuers) for a configured audience
(security.auth.audience), and a role from the groups of the identity
provider (security.access_control.claim_groups,group_mapping);
before, anyone could create, list, read and cancel all tasks. HTTP Basic
credentials of callers are no longer passed through to TES instances (see
Authentication)
(#212, #240) - API: bearer tokens must be access tokens as per RFC 9068 (
typheader
at+jwt); other tokens, such as ID tokens, are rejected (401). The new
optionsecurity.auth.clientslimits the accepted tokens to those of
certain clients (see
Authentication)
(#214, #245) - API: each task belongs to the user who created it: users list, read and
cancel only their own tasks, and admins can no longer see tasks; they only
manage the access control rules. Tasks of others and unknown tasks get
403(was404for unknown tasks). The ruleusers-get-cancel-tasksis
replaced byowners-get-cancel-tasks, and the access control model has
owner roles and no admin bypass. Tasks stored by earlier versions have no
owner, so nobody sees them until operators give them to their users (see
Task
ownership)
(#153, #215, #250) - API: errors are problem details (
title,status,detail, sent as
application/json) instead of objects withmessageandcode; request
bodies are limited to 1 MiB (413) (see
Errors)
(#203, #219) - API: times of tasks (
creation_time, andstart_timeandend_timeof
the logs) are UTC RFC 3339 date-times instead of local-time strings;
proTES setscreation_timeand rejects tasks that set it (400), as the
TES specification marks it read-only (see Task times and remote
identifiers)
(#208, #238) - API:
GET /tasksreturns an emptynext_page_tokenon the last page (it
returned the last task's identifier, so clients kept paging) and an empty
page if no task matches; invalid page tokens and page sizes are rejected
(400); pages have 256 tasks by default (was 5) and at most 2047;
name_prefixis taken literally, not as a regular expression (see Task
listing)
(#165, #208, #238) - API: pages of the view
FULLhave at most 64 tasks
(custom.controllers.list_tasks.max_page_size_full), also by default, so
clients that list full tasks must follownext_page_token; inline
contents of inputs (inputs[].content) over 128 KiB
(custom.controllers.post_task.max_inline_content) are rejected with
413 Content Too Large(see
Task listing)
(#284, #292) - API: tasks that no TES instance accepts (
500), and tasks that fail
validation after the middlewares (400), are deleted with their owner's
roles instead of being kept asSYSTEM_ERROR(see Stored
tasks)
(#284, #292) - API: proTES sends each task to a TES instance with a single request, to
<url>/ga4gh/tes/v1only (earlier versions also tried<url>/v1and
<url>), without following redirects, and no longer fails over to the
next path or TES instance when the outcome is unknown (read timeouts,
connections lost after sending,5xx): such tasks fail with
SYSTEM_ERRORand502 Bad Gateway, as the TES instance may run them
(see TES instances and their
credentials)
(#274, #282) - API: unfinished tasks whose identifier at their TES instance is unknown
can't be canceled (409 Conflict; was500, or200without effect for
tasks in stateUNKNOWN); tasks in stateUNKNOWNare now canceled at
their TES instance. New tasks are stored with the state that their TES
instance reports, instead ofUNKNOWN(see
Task times and remote identifiers)
(#275, #291) - API: tasks with credentials in the URLs of their inputs or outputs
(https://user:password@host/...) are rejected (400), for all TES
instances;custom.controllers.post_task.url_credentials: stripremoves
the credentials instead (see
TES instances and their credentials)
(#213, #251) - API:
logs[].metadata.forwarded_tois a list of forwards (id,url,
forward_time) instead of a nestedtesNextTesobject; tasks stored by
earlier versions are served with their forwards as lists (see
Stored tasks)
(#173, #219) - API: the middleware management API is no longer registered, as its
controllers don't exist yet (see
Middleware management API)
(#196; #203, #219) - Configuration: custom configs must apply the config changes of FOCA 0.14
to 0.17 (e.g.,exceptions.mapping; see the FOCA release notes and
migration guides). The API specification (tes) and the access control
rules are named entries, which overlays change by name; the service info
is configured inservice_info.serviceand no longer stored in the
database (see
Configuration)
(#203, #219; #214, #245) - Configuration: the identity provider is deployment configuration, without
defaults: proTES refuses to start without trusted issuers, an audience and
a group of the roleadmin(unless
custom.access_control.require_adminis false), without enforced access
control, or with service clients, which it doesn't support yet (see
Authentication)
(#212,
#240; #215, #250) - Configuration: unknown keys in
customare errors: the app and the Celery
worker refuse to start, naming them, instead of ignoring them. Remove the
keys that had no effect from config overlays:custom.celery,
custom.controllers.celeryandcustom.controllers.post_task.timeout
(post,poll,job); requests to TES instances time out after
custom.tes.timeoutseconds instead (default 15, was a hard-coded 5)
(see
Configuration)
(#276, #281; #274, #282) - Configuration: entries of
custom.tes.service_listare objects with the
URL of the TES instance (url) and how proTES authenticates at it
(auth:client_credentialsby default,basicornone), instead of
URLs; withclient_credentials, the app and the Celery worker need
PROTES_CLIENT_IDandPROTES_CLIENT_SECRETand refuse to start without
them. URLs of TES instances must behttpsURLs without credentials
(unlesscustom.tes.url_schemesallowshttp); tasks are only forwarded
to configured (or discovered) TES instances. Custom middlewares that read
custom.tes.service_listget these entries instead of URLs (see
TES instances and their credentials)
(#213, #251) - Configuration: the base config lists no TES instances (it listed public
ones), and the default service info describes the app with placeholders
on reserved example domains (RFC 2606;idisorg.example.protes);
deployments set their own, and the app warns on startup while the
placeholders are set (see
TES instances and their credentials)
(#229, #251, #263; #205, #220) - Configuration:
custom.controllers.post_task.polling.waitandattempts
must be positive, andwaitand the newmax_waitbelow 1800 seconds;
custom.controllers.list_tasks.default_page_sizemust not exceed
max_page_size(see
Task tracking)
(#277, #278, #279, #288; #208, #238) - Database: task identifiers are unique: on startup, proTES creates a unique
index ontask.idand drops the index of earlier versions; it refuses to
start while stored tasks share identifiers, and names them (see Task
identifiers)
(#248, #258) - Database: on startup, proTES removes the HTTP Basic credentials of callers
that earlier versions stored with each task (basic_auth), and
credentials in the URLs of inputs and outputs of stored tasks (see
TES instances and their credentials)
(#213, #251) - Celery: the task that tracks tasks no longer takes credentials, and tasks
are tracked by short polls that schedule the next one, so the new worker
rejects tracking jobs that earlier versions queued: upgrade while no tasks
are being submitted. Unfinished tasks stored by earlier versions keep
their last state (see Task
tracking)
(#213, #251; #277, #278, #279, #288) - Celery: after
polling.attemptsconsecutive failed polls, a task is
UNKNOWNuntil its TES instance answers again, instead of failing with a
finalSYSTEM_ERROR; workers no longer setINITIALIZINGwhen they start
tracking a task (see
Task tracking)
(#278, #288) - Helm chart: the chart is replaced by a thin chart over FOCA's library
chartfoca-common0.2.0, with camelCase values (e.g.,hostNameinstead
ofapplicationDomain), other resource names and selectors, Secrets of
the deployment for MongoDB, the broker and Flower instead of credentials
in the values (the broker's user wasguest:guest, Flower's
admin:admin), Flower off by default, pinned images, NetworkPolicies, and
an Ingress for all paths (was/ga4gh/tes/v1only). Releases of the
legacy charts can't be upgraded: uninstall them and install the new chart
(see Helm
chart)
(#216, #252; #246, #270) - Helm chart: the chart version follows the app version, so chart versions
restart below 3.0.0; the chart attached to a release deploys the image of
that release (protes.tagdefaults to the chart'sappVersion), and the
chart of this release needs images of this release (see
Image)
(#44, #230) - Image:
latestis the highest stable release (not alpha, beta or release
candidate) onmain; images of commits ondevare taggeddevand
sha-<commit>. Date-tagged images are no longer pushed (see
Image)
(#44, #230) - Image: the image installs proTES as a package, runs as a non-root user,
and serves the app withgunicorn --config python:pro_tes.gunicorn_config 'pro_tes.app:init_app()';/app/pro_tes,gunicorn.pyandwsgi.pyare
gone, andGUNICORN_PROCESSESandGUNICORN_THREADSare replaced by
GUNICORN_CMD_ARGS. The Celery worker runscelery --app pro_tes.celery_worker worker(see
Image)
(#204,
#223) - Docker Compose: MongoDB 7.0 (was 3.6, which can't be upgraded to 7.0
directly), named volumes instead ofPROTES_DATA_DIR, whose data is not
migrated, ports published on127.0.0.1only, and Flower opt-in (see
Docker
Compose)
(#171, #219; #204, #223) - Python: proTES requires Python 3.13 or later, the Python version of the
image (based onelixircloud/foca:0.17.0-py3.13), the only one it is
tested with (see
Configuration)
(#214, #245; #246, #270) - Middlewares: the distance-based middleware no longer uses the unmaintained
packageip2geotools: it looks up IP addresses with DB-IP's API over
HTTPS (was HTTP) and geocodes places with Nominatim, times out after 10
seconds (was 62), and no longer locates addresses that are not global, nor
places without city or country, for which it falls back to the next
middleware (see
Distance-based task distribution)
(#214, #245)
Features
- Task ownership: users with the role
usercreate tasks and become their
owners (FOCA's owner roles); admins manage the access control rules via
FOCA's permissions API (#153, #215, #250) - Credentials of proTES for TES instances: an access token of proTES's own
client (OAuth 2.0 client credentials grant, from
custom.tes.client_credentials, cached and refreshed), HTTP Basic
credentials from environment variables, or none, per TES instance (#213,
#251) - Discovery of TES instances in a service registry with verified services
(GA4GH Service Registry API, e.g., Cloud Registry):custom.tes.discovery,
off by default, without a default registry. Only verified TES services
with publichttpsaddresses are used, and the active TES instances are
listed in the service info (backends) (#202, #260) - Task tracking with short polls that schedule the next one, so that a few
worker processes track many tasks; polls are acknowledged after they ran,
and workers resume the tracking of stored unfinished tasks when they start
and periodically, so restarts and upgrades of the workers no longer stop
the tracking (#277, #278, #279, #288) - Helm chart: Gateway API HTTPRoute (with an optional redirect to HTTPS),
OpenShift Route, Ingress with an optional cert-manager certificate,
external MongoDB,protes.extraEnvfor the app and the worker (e.g., the
client secret), Gunicorn settings, probes, and checks that fail rendering
for values of the legacy chart and for missing security settings (#216,
#252) ignore_errorof executors is relayed to TES instances (#176, #219)- Configuration: local overrides (
config.local.yaml,
docker-compose.override.yaml) are ignored by Git (#266, #269)
Security
- Signed images and chart: images (releases,
devandsha-<commit>) come
with SBOM and provenance attestations, a GitHub artifact attestation and a
keyless Sigstore signature; the chart attached to the release has a GitHub
artifact attestation and a Sigstore bundle
(protes-0.3.0.tgz.sigstore.json). The published images are the scanned
ones: images are scanned for known vulnerabilities with Trivy in CI,
before a release is published, and weekly (latest). See "Verifying
images and charts" on the Operations page of the documentation (#234,
#256) - Task identifiers can't be shared: a request that draws an identifier in
use gets another one, and never gets a role on another user's task (#248,
#258) - Discovered TES instances must resolve to public addresses only, checked
on discovery and before each request; requests to them follow no
redirects (#202, #260)
Fixes
- Tasks that their TES instance reports as
PREEMPTEDare final (they were
polled forever), andCANCELINGtasks are polled until they are canceled
(#261, #262) - Tasks are sent to TES instances exactly once (#274, #282)
- New tasks are stored with the state that their TES instance reports, and
a cancel request while a task is being forwarded keeps itCANCELED
(#275, #291) - A cancel request no longer replaces a final state that the tracking
stored while the request was sent to the TES instance (#296, #301) - Tasks whose create request was cut off (e.g., by a rolling upgrade) no
longer stayUNKNOWNfor good: the resume sweep of the workers sets them
toSYSTEM_ERRORaftercustom.controllers.post_task.max_create_time
seconds (new, default 3600, at most a year). On upgrade, this also applies
to tasks of earlier versions:UNKNOWNtasks without any remote
identifier that are older than that becomeSYSTEM_ERROR(see Task
times and remote
identifiers)
(#297, #303) - Failed polls no longer end the tracking of tasks that are still running,
and the tracking survives worker restarts (#277, #278, #279, #288) - Task listings iterate the database cursor instead of loading all matching
tasks, and the viewBASICleaves out the logs it should (#284, #292;
#208, #238) - Each TES instance gets its own copy of the task; the remote identifier is
stored intes_endpoint.task_id, so that tasks can also be canceled with
custom.storeLogs.execution_trace: False(#208, #238) - Startup no longer loops forever with
jsonschema> 3.2.0, and no longer
fetches the GA4GH service info schemas from GitHub (#173, #203, #219) - Output sizes reported by TES instances as integers no longer fail the
tracking of finished tasks (#203, #219) - The tracking task uses the database named by
MONGO_DBNAME, as the app
does (#203, #219) - The examples of TES instances in the docs and the chart use the current
config format (#229, #263) - Release workflow: the previous release is found on first releases, and
releases are published after their assets are uploaded, as immutable
releases require (#272, #273; #280, #287)
Documentation
- A documentation site on Read the Docs (MkDocs Material), with pages on
getting started, configuration, the API, access control, middlewares,
deployment, operations, development and upgrading (#209, #228; #210,
#221) - A code of conduct, a contributing guide, a security policy, CODEOWNERS and
citation metadata (#211, #232, #243; #233, #242; #235, #244; #247, #249) - Rate limits: how to limit requests at the ingress controller (#284, #292)
- The served API specification declares the
409(cancel) and413
(create) responses of proTES as extensions (#298, #302) - The size of
FULLpages: a page can reach about 64 MiB by default, so
memory-limited deployments (the chart's API pod has 256 MiB) should lower
custom.controllers.list_tasks.max_page_size_full(#298, #302)
Maintenance
- Releases are published from signed version tags by a release workflow,
with checks of the tag, the citation metadata, the release notes and the
pinned dependencies, also before tagging; the notes of the first release
list all its pull requests (#44, #230; #264, #267; #265, #268; #289,
#293) - The release version comes from one source, the tag (and, before tagging,
the citation metadata): the docs and the chart's README get it from
there, and a test fails if it is hard-coded elsewhere (#290, #299) - Packaging with
pyproject.tomland setuptools-scm, and FOCA 0.17.0 and
foca-common0.2.0 releases pinned (#204, #223; #246, #270) - Checks with pre-commit (ruff, mypy, semgrep, ast-grep, gitleaks,
actionlint), Google-style docstrings and complete type hints, and tests
against a real MongoDB at 100% coverage (#227; #206, #231; #142, #149,
#168, #207, #236; #159, #239) - Pull requests target
devby default, also those of Dependabot (#257,
#259) - Ported fixes of cloud-registry's first release: Gunicorn keepalive 100 s,
generic-repository and docs-URL tests, Dependabot groups, unused Swagger 2
specs removed (#266, #269) - Citation metadata are set safely (file mode kept) (#253, #255)
Commits
- Gunicorn production grade deployment by @djixyacine in #4
- added travis build file by @uniqueg in #5
- RabbitMQ and MongoDB environment variables by @djixyacine in #6
- Bump urllib3 from 1.23 to 1.24.2 by @dependabot[bot] in #7
- Bump mistune from 0.7.4 to 0.8.1 by @dependabot[bot] in #8
- Bump werkzeug from 0.14.1 to 0.15.3 by @dependabot[bot] in #9
- Bump pyyaml from 3.13 to 5.1 by @dependabot[bot] in #10
- Kubernetes deployment of proTES by @uniqueg in #11
- Update requirements.txt by @uniqueg in #12
- Replaced TES specs with those of commit d55bf88 by @uniqueg in #23
- Updated Dockerfile and added docker-compose config files by @uniqueg in #24
- Hotfix docker by @uniqueg in #25
- Implemented /tasks/service-info endpoint by @uniqueg in #26
- List tasks endpoint preliminary implemented by @uniqueg in #27
- Implemented 'POST /tasks' and 'GET /tasks/{id}' by @uniqueg in #28
- Implemented endpoint POST /tasks/{id}:cancel by @uniqueg in #29
- Token validation by @uniqueg in #30
- Fixed port inconsistency in dev deployment by @uniqueg in #31
- Refactor config to allow multiple services by @uniqueg in #32
- Added Celery task monitoring service Flower by @uniqueg in #34
- Class-based JWT validation by @uniqueg in #35
- now compatible with WES-ELIXIR/cwl-tes by @uniqueg in #38
- fix: write modified specs to docker volume by @uniqueg in #40
- proTES Kubernetes deployment YAMLs by @djixyacine in #41
- proTES TLS ingress support by @djixyacine in #42
- Allow to specify security definitions from configuration file by @robertopreste in #51
- Bump MarkupSafe and psutil versions by @uniqueg in #53
- feat(ci): simplify build & remove CD by @uniqueg in #58
- Bump cryptography from 2.3.1 to 3.2 by @dependabot[bot] in #57
- build(deps): bump cryptography from 3.2 to 3.3.2 by @dependabot[bot] in #60
- build(deps): bump jinja2 from 2.10.1 to 2.11.3 by @dependabot[bot] in #61
- build(deps): bump pyyaml from 4.2b1 to 5.4 by @dependabot[bot] in #63
- build(deps): bump urllib3 from 1.24.2 to 1.26.5 by @dependabot[bot] in #66
- build(deps): bump lxml from 4.2.5 to 4.6.5 by @dependabot[bot] in #67
- build(deps): bump flask-cors from 3.0.6 to 3.0.9 by @dependabot[bot] in #65
- build(deps): bump celery from 4.1.1 to 5.2.2 by @dependabot[bot] in #68
- ci: migrate to GH Actions by @lvarin in #70
- build(deps): bump pyjwt from 1.6.4 to 2.4.0 by @dependabot[bot] in #69
- build(deps): bump lxml from 4.6.5 to 4.9.1 by @dependabot[bot] in #72
- feat: operationalize controllers by @Ayush5120 in #71
- feat: track task progress asynchronously by @Ayush5120 in #74
- feat: add task distribution middleware by @Ayush5120 in #75
- test: add unit tests & run integration tests in CI by @Ayush5120 in #76
- App versioning by @uniqueg in #97
- refactor: remove unused config handler by @uniqueg in #100
- fix(docs): fix broken links & add correct port by @uniqueg in #101
- ci: simplify CI workflow by @uniqueg in #104
- ci: build & publish app image by @uniqueg in #105
- ci: minor fixes; remove Travis by @uniqueg in #109
- fix(ci): fix Docker CI action by @uniqueg in #110
- build: fix broken Kubernetes deployment by @uniqueg in #112
- ci: fix app & reactivate CI; add Pylint by @uniqueg in #114
- fix: store task updates in correct schema property by @Ayush5120 in #118
- build(helm): fix readiness probe URL by @uniqueg in #120
- feat: distance-based task distribution logic by @Ayush5120 in #119
- fix: set default page size as per spec by @uniqueg in #126
- fix: return internal task ID & refactor db model by @Ayush5120 in #128
- fix: return execution trace in task log by @Ayush5120 in #129
- Basic auth for TES and inputs/outputs; bug in enum serialization by @uniqueg in #131
- fix: call middleware in task creation class by @Ayush5120 in #133
- fix: URIs with auth in distance-based dist logic by @uniqueg in #135
- refactor: naming of TES tasks DB documents by @BYZANTINE26 in #141
- fix: docstring and minor refactoring by @Ayush5120 in #138
- feat: raise 400/500 for invalid input/TES URIs by @Ayush5120 in #144
- fix: premature system error state by @SohamRatnaparkhi in #143
- feat: filter tasks by name prefix by @SohamRatnaparkhi in #145
- fix: exception handling in IP distance calculation by @Ayush5120 in #147
- feat: fall back to random distribution by @Ayush5120 in #148
- test: unit tests distribution middleware, distance by @Ayush5120 in #150
- fix: strip basic auth only if URLs set by @vschnei in #152
- docs: update Slack URL by @uniqueg in #154
- fix: tasks with inputs without URLs fail by @Ayush5120 in #156
- docs: update & extend documentation by @Ayush5120 in #157
- feat: sequential execution of middleware by @Ayush5120 in #160
- auth: add bearer auth security scheme by @uniqueg in #163
- build: exclude Connexion >3 by @uniqueg in #167
- refactor: update code for type checks by @JaeAeich in #169
- fix: query filter in list task endpoint by @Ayush5120 in #178
- feat: update TES models to v1.1 by @athith-g in #179
- build: address security vulnerabilty by @lvarin in #181
- ci: fix linting and test issues by @Nidhi091999 in #185
- fix: readd lost custom errors by @Nidhi091999 in #182
- feat: models for custom config validation by @Nidhi091999 in #186
- fix: resolve next page cursor loop by @Nidhi091999 in #189
- build: update Helm chart by @trispera in #190
- add troubleshooting section for Docker MTU issues by @vschnei in #192
- Update imagePullPolicy... by @trispera in #193
- feat: add middleware management API specs by @keshxvdayal in #196
- refactor!: upgrade to FOCA 0.15 by @uniqueg in #219
- fix: use neutral service-info defaults by @uniqueg in #220
- docs: present the app, use ELIXIR On-Cloud by @uniqueg in #221
- build!: adopt pyproject, harden image and Compose by @uniqueg in #223
- style: reformat with ruff by @uniqueg in #227
- docs: switch to a MkDocs Material site by @uniqueg in #228
- style: adopt the shared ruff, mypy and pre-commit by @uniqueg in #231
- test: add app test harness and fix the tests by @uniqueg in #236
- fix: task listing, timestamps and relay bugs by @uniqueg in #238
- test: enforce 100% coverage by @uniqueg in #239
- feat(auth)!: require tokens for task operations by @uniqueg in #240
- chore: add CODEOWNERS and .editorconfig by @uniqueg in #242
- docs: add community files and security policy by @uniqueg in #243
- docs: add citation metadata by @uniqueg in #244
- build!: require FOCA 0.17 and Python 3.13 by @uniqueg in #245
- ci!: release from signed version tags by @uniqueg in #230
- chore: use the service contact address by @uniqueg in #249
- feat(access-control)!: own tasks per user by @uniqueg in #250
- build(chart)!: use the FOCA library chart by @uniqueg in #252
- feat!: call TES backends with service tokens by @uniqueg in #251
- fix(scripts): set the citation file mode safely by @uniqueg in #255
- ci: attest, sign and scan published images by @uniqueg in #256
- fix(db)!: make task identifiers unique by @uniqueg in #258
- ci: keep dev as the PR target branch by @uniqueg in #259
- feat: discover TES backends from the registry by @uniqueg in #260
- fix: track PREEMPTED and CANCELING tasks by @uniqueg in #262
- docs: fix TES backend examples by @uniqueg in #263
- fix(release): publish notes in the agreed format by @uniqueg in #267
- ci: check release readiness before tagging by @uniqueg in #268
- chore: port cloud-registry pre-release fixes by @uniqueg in #269
- build: require FOCA 0.17.0 and foca-common 0.2.0 by @uniqueg in #270
- fix: find the previous release on first releases by @uniqueg in #273
- fix: reject unknown config keys by @uniqueg in #281
- build(deps): bump https://github.com/semgrep/pre-commit from v1.181.0 to 1.182.0 in the pre-commit group by @dependabot[bot] in #271
- fix: submit tasks to backends exactly once by @uniqueg in #282
- fix: publish releases after uploading assets by @uniqueg in #287
- fix: track tasks by rescheduled polls by @uniqueg in #288
- fix: store and cancel new tasks at backends by @uniqueg in #291
- fix: bound task listings and stored task data by @uniqueg in #292
- ci: start notes at the first release by @uniqueg in #293
- docs: take the version from one source by @uniqueg in #299
- fix: keep final states on cancel by @uniqueg in #301
- docs: declare 409/413 and FULL page sizes by @uniqueg in #302
- fix: fail tasks whose creation was cut off by @uniqueg in #303
- docs: add the release notes of 0.3.0 by @uniqueg in #300
- chore: set citation metadata to 0.3.0 by @uniqueg in #304
New Contributors
- @djixyacine made their first contribution in #4
- @uniqueg made their first contribution in #5
- @dependabot[bot] made their first contribution in #7
- @robertopreste made their first contribution in #51
- @lvarin made their first contribution in #70
- @Ayush5120 made their first contribution in #71
- @BYZANTINE26 made their first contribution in #141
- @SohamRatnaparkhi made their first contribution in #143
- @vschnei made their first contribution in #152
- @JaeAeich made their first contribution in #169
- @athith-g made their first contribution in #179
- @Nidhi091999 made their first contribution in #185
- @trispera made their first contribution in #190
- @keshxvdayal made their first contribution in #196
Full Changelog: https://github.com/elixir-cloud-aai/proTES/commits/v0.3.0