From e03f0d30f1ff89133a2979c928c81b0260c6977d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 16 Mar 2026 14:10:37 +0100 Subject: [PATCH 1/2] Push packages on tag push (#22367) * Push packages on tag push * Use channel/X derived from tag name --- .github/workflows/packager.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/packager.yml b/.github/workflows/packager.yml index 6efac35fc01..6f56e066eca 100644 --- a/.github/workflows/packager.yml +++ b/.github/workflows/packager.yml @@ -1,11 +1,12 @@ name: Package on: push: + tags: + - v* branches: - packaging/* - dev - release/* - - stable/* workflow_dispatch: jobs: @@ -41,6 +42,12 @@ jobs: run: | VERSION=$(ruby -r ./lib/open_project/version.rb -e "puts OpenProject::VERSION") echo "version=$VERSION" >> $GITHUB_OUTPUT + if [[ "${{ github.ref_type }}" == "tag" ]]; then + MAJOR=$(ruby -r ./lib/open_project/version.rb -e "puts OpenProject::VERSION::MAJOR") + echo "channel=stable/${MAJOR}" >> $GITHUB_OUTPUT + else + echo "channel=${{ github.ref_name }}" >> $GITHUB_OUTPUT + fi - name: Package uses: pkgr/action/package@main id: package @@ -56,5 +63,5 @@ jobs: target: ${{ matrix.target }} token: ${{ secrets.PACKAGER_PUBLISH_TOKEN }} repository: opf/openproject - channel: ${{ github.ref_name }} + channel: ${{ steps.setup.outputs.channel }} file: ${{ steps.package.outputs.package_path }} From d0aa47d345afed5e5d2b0eb9ebd214e7fde75431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 23 Mar 2026 08:54:41 +0100 Subject: [PATCH 2/2] Correctly evaluate parse number string in =n operator --- modules/reporting/lib/report/operator.rb | 2 +- .../spec/models/cost_query/operator_spec.rb | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/reporting/lib/report/operator.rb b/modules/reporting/lib/report/operator.rb index e3fc153ff65..a54cb1afdfb 100644 --- a/modules/reporting/lib/report/operator.rb +++ b/modules/reporting/lib/report/operator.rb @@ -174,7 +174,7 @@ class Report::Operator new "=n", label: :label_equals do def modify(query, field, value) - query.where "#{field} = #{parse_number_string(value)}" + query.where ["#{field} = ?", parse_number_string_to_number(value)] query end end diff --git a/modules/reporting/spec/models/cost_query/operator_spec.rb b/modules/reporting/spec/models/cost_query/operator_spec.rb index 1cc232352ed..1c90e2ccc77 100644 --- a/modules/reporting/spec/models/cost_query/operator_spec.rb +++ b/modules/reporting/spec/models/cost_query/operator_spec.rb @@ -333,6 +333,24 @@ RSpec.describe CostQuery::Operator, :reporting_query_helper do expect(query_on_entries("costs", "=n", 13.37).pluck("id")).to contain_exactly(ce1.id, ce2.id) end + describe "=n value escaping" do + let(:rate) { create(:cost_rate, rate: 10.0) } + + before do + create(:cost_entry, units: 1, rate:, cost_type: rate.cost_type) + create(:cost_entry, units: 1, rate:, cost_type: rate.cost_type) + end + + it "tries to convert invalid values" do + expect(query_on_entries("costs", "=n", "0/**/OR/**/1=1")).to be_empty + end + + it "returns the correct rows for a legitimate numeric value" do + expect(query_on_entries("costs", "=n", "10.0").size).to eq(2) + expect(query_on_entries("costs", "=n", "20.0").size).to eq(0) + end + end + it "does 0" do expect(query_on_entries("costs", "0").size).to eq(Entry.all.count { |e| e.costs == 0 }) end