Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
b52712c
Add 2 net utilities to the min image
afgane Oct 16, 2025
921c1e5
fix anndata
nilchia Aug 15, 2025
e1a2653
Mark user creation API endpoint as admin-only
mvdbeek Oct 23, 2025
e96db3c
Set minimum profile version for expression tools to 19.05
mvdbeek Oct 23, 2025
c983e44
Set profile version for shipped expression tools
mvdbeek Oct 23, 2025
6cfca01
Merge pull request #21149 from mvdbeek/put_post_api_user_behing_admin…
mvdbeek Oct 23, 2025
8838392
Drop fastapi extra dep from sentry-sdk
mvdbeek Oct 23, 2025
697520b
Merge pull request #21151 from mvdbeek/set_minimum_profile_version_fo…
mvdbeek Oct 23, 2025
259caa1
Fix subworkflow editing
mvdbeek Oct 23, 2025
a3ca957
Add Convert characters1 to workflow safe updates
mvdbeek Oct 23, 2025
e5b22db
Merge pull request #21156 from mvdbeek/sentry_sdk_fix
jmchilton Oct 23, 2025
d2de785
Merge pull request #21159 from mvdbeek/fix_subworkflow_editing_25_1
ahmedhamidawan Oct 23, 2025
202e137
Use yarn instead of npx to use pinned openapi-typescrip
mvdbeek Oct 24, 2025
5b62798
Fix workflow landing rendering if public query param not provided
mvdbeek Oct 24, 2025
0c4f318
Run prettier
mvdbeek Oct 24, 2025
05689b4
Bump up minimal tpv version
mvdbeek Oct 24, 2025
7e61106
Merge pull request #21160 from mvdbeek/make_convert_characters_1_work…
mvdbeek Oct 24, 2025
642c256
Merge pull request #21164 from mvdbeek/openapi_typescript_pin
mvdbeek Oct 24, 2025
fbd189e
Merge pull request #21166 from mvdbeek/fix_tpv_oom
mvdbeek Oct 24, 2025
73b4184
Fix proxy response streaming with encoding
davelopez Oct 24, 2025
8ccaeab
Add proxy test for content-encoding handling
davelopez Oct 24, 2025
202eca4
Merge pull request #21169 from davelopez/25.1_fix_proxy_endpoint_enco…
mvdbeek Oct 24, 2025
d91383b
Merge pull request #21165 from mvdbeek/public_fallback
jmchilton Oct 24, 2025
f4ee008
Update igv, add collection element drag&drop
guerler Oct 26, 2025
6962412
Merge pull request #21173 from guerler/igv_release_25.1
mvdbeek Oct 27, 2025
20b691b
Resolve possible symlink before establishing tool file location
mvdbeek Oct 27, 2025
6a27f56
Merge pull request #21085 from afgane/net-utilities
afgane Oct 27, 2025
ccde86f
Save build date to GITHUB_OUTPUT
ksuderman Oct 28, 2025
9c2ce67
Merge pull request #21181 from ksuderman/release_25.1
nsoranzo Oct 28, 2025
b9dd63f
Fix proxy response streaming with encoding
davelopez Oct 24, 2025
a8d5aa2
Add proxy test for content-encoding handling
davelopez Oct 24, 2025
f974fc8
Improves redirect handling and validation in proxy API
davelopez Oct 28, 2025
b86c2c0
Adds proxy API tests for redirect validation
davelopez Oct 28, 2025
d131121
Refactors URL validation into a helper method
davelopez Oct 28, 2025
6952061
Refactors proxy redirect handling
davelopez Oct 28, 2025
d6f6541
Merge pull request #21184 from davelopez/25.0_backport_#21169
mvdbeek Oct 29, 2025
abff34d
Merge pull request #21185 from davelopez/25.0_validate_proxy_redirect
mvdbeek Oct 29, 2025
0065aa6
Merge pull request #21175 from mvdbeek/fix_pulsar_tests
mvdbeek Oct 29, 2025
5aa6295
Don't show View Sheet button for non-sample sheet collections.
jmchilton Oct 29, 2025
9a8e632
force push to router so collection builder can be invoked consecutively
ahmedhamidawan Oct 29, 2025
82830d5
improve alerts in `ListWizard`
ahmedhamidawan Oct 29, 2025
f21cc9c
fix minor grammar/spell errors in collection builder cards
ahmedhamidawan Oct 29, 2025
bcf6543
add hover styling to `wizard-selection-card`
ahmedhamidawan Oct 29, 2025
bfb1fb5
Add hyphyvision
guerler Oct 29, 2025
911c7d2
Don't create extra watchers when switching tabs
natefoo Oct 29, 2025
709f924
Merge pull request #21196 from guerler/add_hyphyvision
bgruening Oct 29, 2025
ad5a2c5
Add Release Drafter integration
dannon Sep 18, 2025
9805c3e
Read version from lib/galaxy/version.py instead of calculating it
dannon Sep 30, 2025
be48b59
Fix grep pattern to match only VERSION_MAJOR line
dannon Sep 30, 2025
a13dedb
Clean up Release Drafter config for production
dannon Oct 29, 2025
6e4ac89
only conditionally force push to the route for collection builder
ahmedhamidawan Oct 29, 2025
5b45a05
Merge pull request #21195 from dannon/release-drafter-clean
ahmedhamidawan Oct 29, 2025
3abb337
Merge pull request #21191 from jmchilton/25_1_fixes_2
jmchilton Oct 30, 2025
ddbe102
Merge pull request #21193 from ahmedhamidawan/fix_collection_builder_…
jmchilton Oct 30, 2025
e064326
Drop single 'pair' from standard upload UI, preferring lists, or list…
dannon Oct 30, 2025
6aa9bfe
Updates watcher tests for visibility change polling
davelopez Oct 30, 2025
349d9a0
Merge pull request #21111 from nilchia/release_25.0
davelopez Oct 30, 2025
50c7c8b
Merge pull request #21200 from dannon/upload-drop-pair
davelopez Oct 30, 2025
66d0de4
Merge pull request #21197 from natefoo/current-history-reqs
mvdbeek Oct 30, 2025
465f774
Fix MIME type for LAZ datatype
domgz Oct 30, 2025
7b269cb
Merge pull request #21202 from kysrpex/laz_mime
davelopez Oct 30, 2025
2d9577a
Merge remote-tracking branch 'upstream/release_25.0' into merge_25.0_…
ahmedhamidawan Oct 30, 2025
e3f9a65
Merge pull request #21208 from ahmedhamidawan/merge_25.0_into_25.1_oct
nsoranzo Oct 31, 2025
def5ad1
Merge remote-tracking branch 'upstream/release_25.1' into merge_25.1_…
ahmedhamidawan Oct 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Release Drafter Configuration for Galaxy
# Implements YY.N.P versioning scheme using existing Galaxy labels
#
# IMPORTANT: Galaxy's versioning scheme is YY.N.P where:
# - YY = Two-digit year (25 for 2025)
# - N = Feature release number (0, 1, 2... - typically 2-3 per year)
# - P = Patch/point release number (0, 1, 2, 3...)
#
# Year transitions (24→25) must be handled manually when creating releases.

name-template: 'Galaxy $RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'

# Categories for organizing release notes using existing Galaxy labels
categories:
- title: '🎉 Major Changes'
labels:
- 'major'
- 'highlight'
- title: '🚀 New Features'
labels:
- 'kind/feature'
- title: '🔧 Enhancements'
labels:
- 'kind/enhancement'
- title: '🐛 Bug Fixes'
labels:
- 'kind/bug'
- title: '🔒 Security Updates'
labels:
- 'area/security'
- title: '⚡ Performance'
labels:
- 'area/performance'
- title: '🧰 Refactoring'
labels:
- 'kind/refactoring'
- title: '📚 Documentation'
labels:
- 'area/documentation'
- title: '🔧 Admin & Configuration'
labels:
- 'area/admin'
- 'area/configuration'
- title: '🛠️ API Changes'
labels:
- 'area/API'
- title: '🧪 Testing'
labels:
- 'area/testing'
- 'area/testing/api'
- 'area/testing/integration'
- 'area/testing/selenium'
- title: '🏗️ Infrastructure & Dependencies'
labels:
- 'area/dependencies'
- 'area/client-build'

# Exclude certain labels from release notes
exclude-labels:
- 'triage'
- 'procedures'
- 'planning'
- 'merge'
- 'status/needs feedback'
- 'status/planning'

# Template for each change line
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'

# Characters to escape in titles
change-title-escapes: '\<*_&'

# Version is read from lib/galaxy/version.py by the workflow
# No version-resolver needed since Galaxy manages versions manually

# Template for the release body
template: |
## Changes in $RESOLVED_VERSION

$CHANGES

**Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
2 changes: 1 addition & 1 deletion .github/workflows/build_container_image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
id: buildargs
run: |
echo "gitcommit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "builddate=$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
echo "builddate=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Release Drafter

on:
push:
branches:
- dev
- master
- 'release_*'
pull_request_target:
types: [opened, reopened, synchronize]

permissions:
contents: read

jobs:
update_release_draft:
permissions:
contents: write
pull-requests: write
if: github.repository == 'galaxyproject/galaxy'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: dev
sparse-checkout: |
lib/galaxy/version.py

- name: Read Galaxy version
id: galaxy-version
run: |
# Extract VERSION_MAJOR from version.py (e.g., "25.1")
VERSION_MAJOR=$(grep '^VERSION_MAJOR' lib/galaxy/version.py | cut -d'"' -f2)
RELEASE_VERSION="${VERSION_MAJOR}.0"
echo "version=${RELEASE_VERSION}" >> $GITHUB_OUTPUT
echo "Galaxy release version: ${RELEASE_VERSION}"

- uses: release-drafter/release-drafter@v6
with:
config-name: release-drafter.yml
version: ${{ steps.galaxy-version.outputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 2 additions & 0 deletions .k8s_ci.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,14 @@ RUN set -xe; \
locales \
vim-tiny \
nano-tiny \
netcat-openbsd \
curl \
procps \
less \
bzip2 \
tini \
nodejs \
wget \
&& update-alternatives --install /usr/bin/nano nano /bin/nano-tiny 0 \
&& update-alternatives --install /usr/bin/vim vim /usr/bin/vim.tiny 0 \
&& echo "set nocompatible\nset backspace=indent,eol,start" >> /usr/share/vim/vimrc.tiny \
Expand Down
13 changes: 10 additions & 3 deletions client/src/components/Collections/ListWizard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { showHid } from "./common/useCollectionCreator";
import type { WhichListBuilder } from "./ListWizard/types";
import { useAutoPairing } from "./usePairing";

import LoadingSpan from "../LoadingSpan.vue";
import ListCollectionCreator from "./ListCollectionCreator.vue";
import WhichBuilder from "./ListWizard/WhichBuilder.vue";
import PairedOrUnpairedListCollectionCreator from "./PairedOrUnpairedListCollectionCreator.vue";
Expand Down Expand Up @@ -199,16 +200,22 @@ function onRuleState(newRuleState: boolean) {
<template>
<div v-if="currentHistoryId">
<div v-if="creationError">
<BAlert variant="danger">
<BAlert variant="danger" show>
{{ creationError }}
</BAlert>
</div>
<div v-if="collectionCreated">
<BAlert variant="success" show> Collection created and it has been added to your history. </BAlert>
</div>
<div v-else-if="!selectedItems">Loading...</div>
<div v-else-if="!selectedItems">
<BAlert variant="info" show>
<LoadingSpan />
</BAlert>
</div>
<div v-else-if="selectedItems.length == 0">
<p>Select datasets from history panel to use the Galaxy list building wizard.</p>
<BAlert variant="info" show>
Select datasets from the history panel to use the Galaxy list building wizard.
</BAlert>
</div>
<GenericWizard v-else :use="wizard" :is-busy="isBusy" :submit-button-label="buildButtonLabel" @submit="submit">
<div v-if="wizard.isCurrent('which-builder')">
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/Collections/ListWizard/WhichBuilder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function toggleAdvanced() {
<b>Flat List</b>
</BCardTitle>
<div>
This options creates a simple flat list of files. If your data isn't nested and does not contained
This option creates a simple flat list of files. If your data isn't nested and does not contained
paired datasets, this is the the option to choose.
</div>
</BCard>
Expand All @@ -47,8 +47,8 @@ function toggleAdvanced() {
<b>List of Paired Datasets</b>
</BCardTitle>
<div>
This options creates a uniform list of paired datasets, use this option if all of your data should
be paired off.
This option creates a uniform list of paired datasets, use this option if all of your data should be
paired off.
</div>
</BCard>
<BCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ defineProps<Props>();
<b>Flat List</b>
</BCardTitle>
<div>
This options creates a simple flat list of files. If your data isn't nested and does not contained
paired datasets, this is the the option to choose.
This option creates a simple flat list of files. If your data isn't nested and does not contained
paired datasets, this is the option to choose.
</div>
</BCard>
<BCard
Expand All @@ -39,8 +39,8 @@ defineProps<Props>();
<b>List of Paired Datasets</b>
</BCardTitle>
<div>
This options creates a uniform list of paired datasets, use this option if all of your data should
be paired off.
This option creates a uniform list of paired datasets, use this option if all of your data should be
paired off.
</div>
</BCard>
</BCardGroup>
Expand Down
5 changes: 5 additions & 0 deletions client/src/components/Common/Wizard/GenericWizard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ const bodyStyle = computed(() => {
.card-header {
border-radius: 0;
}

&:hover {
border-color: lighten($brand-primary, 20%);
cursor: pointer;
}
}
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const showCollectionDetailsUrl = computed(() =>
);
const disableDownload = props.dsc.populated_state !== "ok";

const hasSampleSheet = computed(() => {
return props.dsc.collection_type && props.dsc.collection_type.startsWith("sample_sheet");
});

const sheetUrl = computed(() => {
return `${getAppRoot()}collection/${props.dsc.id}/sheet`;
});
Expand Down Expand Up @@ -68,7 +72,7 @@ function onDownload() {
<span>Run Job Again</span>
</b-button>
<b-button
v-if="sheetUrl"
v-if="hasSampleSheet && sheetUrl"
class="rounded-0 text-decoration-none"
size="sm"
variant="link"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,14 @@ export default {
const { setSelectedItems } = useCollectionBuilderItemSelection();
const selection = Array.from(this.contentSelection.values());
setSelectedItems(selection);
this.$router.push({ path: `/collection/new_list?advanced=${advanced}` });

if (this.$route.path === "/collection/new_list") {
// vue-router 4 supports a native force push with clean URLs, but we're using a __vkey__
// bit as a workaround to allow the builder to be invoked consecutively
this.$router.push({ path: `/collection/new_list?advanced=${advanced}` }, { force: true });
} else {
this.$router.push(`/collection/new_list?advanced=${advanced}`);
}
},
// Selected content manipulation, hide/show/delete/purge
hideSelected() {
Expand Down
4 changes: 1 addition & 3 deletions client/src/components/Upload/DefaultBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ const queue = ref(createUploadQueue());
const selectedItemsForModal = ref<HDASummary[]>([]);

const counterNonRunning = computed(() => counterAnnounce.value + counterSuccess.value + counterError.value);
const creatingPairedType = computed(
() => props.isCollection && ["list:paired", "paired"].includes(collectionType.value),
);
const creatingPairedType = computed(() => props.isCollection && collectionType.value === "list:paired");
const enableBuild = computed(
() =>
!isRunning.value &&
Expand Down
1 change: 0 additions & 1 deletion client/src/components/Upload/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const AUTO_EXTENSION = {
};
export const COLLECTION_TYPES = [
{ id: "list", text: "List" },
{ id: "paired", text: "Pair" },
{ id: "list:paired", text: "List of Pairs" },
];
export const DEFAULT_DBKEY = "?";
Expand Down
32 changes: 16 additions & 16 deletions client/src/composables/resourceWatcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ describe("useResourceWatcher", () => {
expect(mockAddEventListener).toHaveBeenCalledWith("visibilitychange", expect.any(Function));
});

it("should restart watching with short interval when app becomes visible", async () => {
it("should switch to short interval when app becomes visible without restarting watcher", async () => {
const { startWatchingResource } = useResourceWatcher(mockWatchHandler);

startWatchingResource();
Expand All @@ -242,22 +242,22 @@ describe("useResourceWatcher", () => {
mockDocument.visibilityState = "hidden";
visibilityChangeHandler();

// Clear the handler calls from the visibility change restart
// Clear the handler calls
mockWatchHandler.mockClear();

// Simulate app becoming visible again
mockDocument.visibilityState = "visible";
visibilityChangeHandler();

// Should immediately call the handler (from startWatchingResource)
// Should NOT immediately call the handler (watcher already running, no restart)
await flushPromises();
expect(mockWatchHandler).toHaveBeenCalledTimes(1);
expect(mockWatchHandler).toHaveBeenCalledTimes(0);

// Should continue with short polling interval
// But should continue with short polling interval on next scheduled poll
jest.advanceTimersByTime(3000);
await flushPromises();

expect(mockWatchHandler).toHaveBeenCalledTimes(2);
expect(mockWatchHandler).toHaveBeenCalledTimes(1);
});
});

Expand Down Expand Up @@ -494,25 +494,25 @@ describe("useResourceWatcher", () => {
mockDocument.visibilityState = "hidden";
visibilityChangeHandler();

// Change to visible - this restarts the watcher
// Change to visible - this changes currentPollingInterval back to short but doesn't restart
mockDocument.visibilityState = "visible";
visibilityChangeHandler();
await flushPromises();
expect(mockWatchHandler).toHaveBeenCalledTimes(2); // + 1 from becoming visible
expect(mockWatchHandler).toHaveBeenCalledTimes(1); // No additional call from becoming visible

// Change to hidden again - this changes currentPollingInterval but doesn't restart timer
mockDocument.visibilityState = "hidden";
visibilityChangeHandler();

// The timer that was started when becoming visible is still running with short interval
// The timer continues with the short interval
jest.advanceTimersByTime(3000);
await flushPromises();
expect(mockWatchHandler).toHaveBeenCalledTimes(3); // + 1 from short interval timer
expect(mockWatchHandler).toHaveBeenCalledTimes(2); // + 1 from short interval timer

// Change to hidden again
mockDocument.visibilityState = "hidden";
visibilityChangeHandler();

// Now the next timer should be using the long interval
// The next timer should use the long interval
jest.advanceTimersByTime(10000);
await flushPromises();
expect(mockWatchHandler).toHaveBeenCalledTimes(4); // + 1 from long interval timer
expect(mockWatchHandler).toHaveBeenCalledTimes(3); // + 1 from long interval timer
});
});
});
2 changes: 1 addition & 1 deletion client/src/composables/resourceWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export function useResourceWatcher<T = unknown>(
function updateThrottle() {
if (document.visibilityState === "visible") {
currentPollingInterval = shortPollingInterval;
startWatchingResource();
startWatchingResourceIfNeeded();
} else {
currentPollingInterval = enableBackgroundPolling ? longPollingInterval : undefined;
}
Expand Down
11 changes: 10 additions & 1 deletion client/src/entry/analysis/router-push.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ export function patchRouterPush(VueRouter) {
// add key to location to force component refresh
const { title, force, preventWindowManager } = options;
if (force) {
location = addSearchParams(location, { __vkey__: Date.now() });
// since location can either be string or object, we need to pass the string url to addSearchParams
if (typeof location === "string") {
location = addSearchParams(location, { __vkey__: Date.now() });
} else if (typeof location === "object") {
// convert to string version addSearchParams can handle
let url = this.resolve(location).href;
url = addSearchParams(url, { __vkey__: Date.now() });
// convert back to object version
location = this.resolve(url).route;
}
}
// verify if confirmation is required
if (this.confirmation) {
Expand Down
Loading
Loading