Skip to content

Commit 3aac600

Browse files
committed
Merge remote-tracking branch 'origin/dev' into fix/improve_speed_of_backlog_filtering
2 parents 33a3387 + 54e2ab5 commit 3aac600

881 files changed

Lines changed: 32864 additions & 33707 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/brakeman-scan-core.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,6 @@ jobs:
4646
--output output.sarif.json
4747
4848
- name: Upload SARIF
49-
uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4
49+
uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
5050
with:
5151
sarif_file: output.sarif.json

.github/workflows/codeql-scan-core.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ jobs:
3636
persist-credentials: false
3737

3838
- name: Initialize CodeQL
39-
uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4
39+
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
4040
with:
4141
config-file: ./.github/codeql/config.yml
4242
languages: ${{ matrix.language }}
4343
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
4444
queries: security-extended,security-and-quality
4545

4646
- name: Perform CodeQL Analysis
47-
uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4
47+
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
4848
with:
4949
category: "/language:${{matrix.language}}"

.github/workflows/npm-audit.yml

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
name: npm audit fix
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: "23 4 * * 1"
7+
8+
env:
9+
BASE_BRANCH: dev
10+
BRANCH_PREFIX: npm-audit-fix
11+
12+
permissions: {}
13+
14+
concurrency:
15+
group: npm-audit-fix
16+
cancel-in-progress: false
17+
18+
jobs:
19+
audit-fix:
20+
name: npm audit fix
21+
runs-on: ubuntu-latest
22+
timeout-minutes: 15
23+
if: github.repository == 'opf/openproject' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
24+
25+
permissions:
26+
contents: write # for git push
27+
pull-requests: write # for creating pull requests
28+
29+
steps:
30+
- name: Checkout repository
31+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
32+
with:
33+
ref: ${{ env.BASE_BRANCH }}
34+
token: ${{ secrets.OPENPROJECTCI_GH_CORE_PAT }}
35+
persist-credentials: false
36+
37+
- name: Set up Node.js
38+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
39+
with:
40+
node-version: '22.21'
41+
package-manager-cache: false
42+
43+
- name: Required git config
44+
run: |
45+
git config user.name "OpenProject Actions CI"
46+
git config user.email "operations+ci@openproject.com"
47+
48+
- name: Run npm audit fix
49+
id: audit_fix
50+
run: |
51+
set -euo pipefail
52+
53+
mkdir -p reports
54+
55+
print_audit_report() {
56+
local report="$1"
57+
local label="$2"
58+
59+
node - "$report" "$label" <<'NODE'
60+
const fs = require('fs');
61+
62+
const reportPath = process.argv[2];
63+
const label = process.argv[3];
64+
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
65+
const vulnerabilities = Object.entries(report.vulnerabilities || {});
66+
const counts = report.metadata?.vulnerabilities || {};
67+
68+
console.log(`${label}: ${vulnerabilities.length} vulnerable package(s)`);
69+
console.log(`severity counts: ${JSON.stringify(counts)}`);
70+
71+
for (const [name, details] of vulnerabilities) {
72+
const via = (details.via || [])
73+
.map((finding) => typeof finding === 'string' ? finding : finding.title)
74+
.filter(Boolean)
75+
.join('; ');
76+
77+
console.log([
78+
`- ${name}`,
79+
`severity: ${details.severity}`,
80+
`range: ${details.range || 'n/a'}`,
81+
`fixAvailable: ${JSON.stringify(details.fixAvailable)}`,
82+
via ? `via: ${via}` : null
83+
].filter(Boolean).join(' | '));
84+
}
85+
NODE
86+
}
87+
88+
run_for_package() {
89+
local name="$1"
90+
local directory="$2"
91+
local before_report="$GITHUB_WORKSPACE/reports/npm-audit-${name}-before.json"
92+
local after_report="$GITHUB_WORKSPACE/reports/npm-audit-${name}-after.json"
93+
94+
echo "::group::npm audit before fix (${name})"
95+
set +e
96+
npm --prefix "$directory" audit --audit-level=high --json > "$before_report"
97+
audit_before_exit=$?
98+
set -e
99+
print_audit_report "$before_report" "${name} before fix"
100+
echo "npm audit before fix exited with ${audit_before_exit}"
101+
echo "::endgroup::"
102+
103+
echo "::group::npm audit fix (${name})"
104+
set +e
105+
npm --prefix "$directory" audit fix --package-lock-only --ignore-scripts --audit-level=high
106+
audit_fix_exit=$?
107+
set -e
108+
echo "npm audit fix exited with ${audit_fix_exit}"
109+
echo "::endgroup::"
110+
111+
echo "::group::npm audit after fix (${name})"
112+
set +e
113+
npm --prefix "$directory" audit --audit-level=high --json > "$after_report"
114+
audit_after_exit=$?
115+
set -e
116+
print_audit_report "$after_report" "${name} after fix"
117+
echo "npm audit after fix exited with ${audit_after_exit}"
118+
echo "::endgroup::"
119+
}
120+
121+
run_for_package root .
122+
run_for_package frontend frontend
123+
124+
if git diff --quiet -- package.json package-lock.json frontend/package.json frontend/package-lock.json; then
125+
echo "has_changes=false" >> "$GITHUB_OUTPUT"
126+
echo "npm audit fix produced no package or lockfile changes."
127+
else
128+
echo "has_changes=true" >> "$GITHUB_OUTPUT"
129+
echo "npm audit fix produced package or lockfile changes."
130+
fi
131+
132+
- name: Show diff
133+
if: steps.audit_fix.outputs.has_changes == 'true'
134+
run: git diff -- package.json package-lock.json frontend/package.json frontend/package-lock.json
135+
136+
- name: Create pull request
137+
if: steps.audit_fix.outputs.has_changes == 'true'
138+
env:
139+
GITHUB_TOKEN: ${{ secrets.OPENPROJECTCI_GH_CORE_PAT }}
140+
run: |
141+
set -euo pipefail
142+
143+
pr_numbers=$(gh pr list \
144+
--base "$BASE_BRANCH" \
145+
--state open \
146+
--limit 100 \
147+
--json number,headRefName \
148+
--jq '.[] | select(.headRefName | startswith("'"$BRANCH_PREFIX"'-")) | .number')
149+
150+
for pr_number in $pr_numbers; do
151+
gh pr close "$pr_number" --delete-branch
152+
done
153+
154+
pr_body_file=$(mktemp)
155+
156+
{
157+
echo 'Created by GitHub action.'
158+
echo
159+
echo '## Impacted packages'
160+
} > "$pr_body_file"
161+
162+
node <<'NODE' >> "$pr_body_file"
163+
const fs = require('fs');
164+
165+
const reports = [
166+
['root', 'reports/npm-audit-root-before.json'],
167+
['frontend', 'reports/npm-audit-frontend-before.json']
168+
];
169+
let foundPackages = false;
170+
171+
for (const [label, reportPath] of reports) {
172+
if (!fs.existsSync(reportPath)) {
173+
continue;
174+
}
175+
176+
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
177+
const vulnerabilities = Object.entries(report.vulnerabilities || {})
178+
.sort(([left], [right]) => left.localeCompare(right));
179+
180+
if (vulnerabilities.length === 0) {
181+
continue;
182+
}
183+
184+
foundPackages = true;
185+
console.log('');
186+
console.log(`### ${label}`);
187+
188+
for (const [name, details] of vulnerabilities) {
189+
console.log(`- \`${name}\` (${details.severity})`);
190+
}
191+
}
192+
193+
if (!foundPackages) {
194+
console.log('');
195+
console.log('No vulnerable packages were reported before the fix.');
196+
}
197+
NODE
198+
199+
{
200+
for pr_number in $pr_numbers; do
201+
if [ "$pr_number" = "$(echo "$pr_numbers" | head -1)" ]; then
202+
echo
203+
echo '## Replaced PRs'
204+
echo
205+
fi
206+
echo "Replaces #$pr_number"
207+
done
208+
} >> "$pr_body_file"
209+
210+
temp_branch="$BRANCH_PREFIX-$(date "+%Y%m%d%H%M%S")"
211+
212+
git switch -c "$temp_branch"
213+
git add package.json package-lock.json frontend/package.json frontend/package-lock.json
214+
git commit -m "Run npm audit fix"
215+
gh auth setup-git
216+
git push origin "$temp_branch"
217+
218+
gh pr create \
219+
--base "$BASE_BRANCH" \
220+
--head "$temp_branch" \
221+
--title "Run npm audit fix" \
222+
--body-file "$pr_body_file"
223+
224+
echo "Created a PR with npm audit fixes (${temp_branch}) against ${BASE_BRANCH}"

.github/workflows/yamllint-core.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
uses: reviewdog/action-yamllint@f01d8a48fd8d89f89895499fca2cff09f9e9e8c0 # v1.21.0
2626
with:
2727
github_token: ${{ secrets.github_token }}
28+
fail_level: error
2829
yamllint_flags: >
2930
.yamllint.yml
3031
config/locales/en.yml

Gemfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ gem "ttfunk", "~> 1.7.0" # remove after https://github.com/prawnpdf/prawn/issues
162162
# prawn implicitly depends on matrix gem no longer in ruby core with 3.1
163163
gem "matrix", "~> 0.4.3"
164164

165-
gem "mcp", "~> 0.16.0"
165+
gem "mcp", "~> 0.17.0"
166166

167167
gem "meta-tags", "~> 2.23.0"
168168

@@ -295,7 +295,7 @@ group :test do
295295
gem "rails-controller-testing", "~> 1.0.2"
296296

297297
gem "capybara", "~> 3.40.0"
298-
gem "capybara_accessible_selectors", git: "https://github.com/citizensadvice/capybara_accessible_selectors", tag: "v0.15.0"
298+
gem "capybara_accessible_selectors", git: "https://github.com/citizensadvice/capybara_accessible_selectors", tag: "v0.16.0"
299299
gem "capybara-screenshot", "~> 1.0.17"
300300
gem "cuprite", "~> 0.17.0"
301301
gem "rspec-wait"

Gemfile.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
GIT
22
remote: https://github.com/citizensadvice/capybara_accessible_selectors
3-
revision: 5b9ce7840d04270e99f4f0cb03989e05437326a6
4-
tag: v0.15.0
3+
revision: 568699fc71b6648e7186a4ac77bba072447c131e
4+
tag: v0.16.0
55
specs:
66
capybara_accessible_selectors (0.15.0)
77
capybara (~> 3.36)
@@ -829,7 +829,7 @@ GEM
829829
marcel (1.0.4)
830830
markly (0.16.0)
831831
matrix (0.4.3)
832-
mcp (0.16.0)
832+
mcp (0.17.0)
833833
json-schema (>= 4.1)
834834
messagebird-rest (5.0.0)
835835
jwt (< 4)
@@ -1656,7 +1656,7 @@ DEPENDENCIES
16561656
mail (= 2.9.0)
16571657
markly (~> 0.15)
16581658
matrix (~> 0.4.3)
1659-
mcp (~> 0.16.0)
1659+
mcp (~> 0.17.0)
16601660
md_to_pdf!
16611661
meta-tags (~> 2.23.0)
16621662
mini_magick (~> 5.3.0)
@@ -2013,7 +2013,7 @@ CHECKSUMS
20132013
marcel (1.0.4) sha256=0d5649feb64b8f19f3d3468b96c680bae9746335d02194270287868a661516a4
20142014
markly (0.16.0) sha256=6f70d79e385b1efc9e171f74c81628826259039fe6c778e03c3924c71dac5511
20152015
matrix (0.4.3) sha256=a0d5ab7ddcc1973ff690ab361b67f359acbb16958d1dc072b8b956a286564c5b
2016-
mcp (0.16.0) sha256=d8ff1a78826945f952eccf803fae1c086e54e91dac7b876038467f5fb1198617
2016+
mcp (0.17.0) sha256=a66b71254cd8c49c471cfa55f11a9f050817ab7168cadf961555784d365b8474
20172017
md_to_pdf (0.2.6)
20182018
messagebird-rest (5.0.0) sha256=da4cc1efba3d5e4aa021fad07426c2cb6b326ce5670da5104bb8f6056a39d59c
20192019
meta-tags (2.23.0) sha256=ffe78b5bee398de4ff5ac3316f5a786049538a651643b8476def06c3acc762c1

app/components/_index.sass

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
@import "work_packages/details/tab_component"
4040
@import "work_packages/exports/modal_dialog_component"
4141
@import "work_packages/hover_card_component"
42+
@import "work_packages/info_line_component"
4243
@import "work_packages/progress/modal_body_component"
4344
@import "work_packages/reminder/modal_body_component"
4445
@import "work_packages/split_view_component"

app/components/admin/import/jira/import_runs/select_projects/list_header_component.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
scheme: :invisible,
2222
tag: :a,
2323
href: check_all_url,
24-
data: { turbo_stream: true }
24+
data: { action: "click->admin--jira-projects#checkAll" }
2525
)
2626
) do |button|
2727
button.with_leading_visual_icon(icon: :"check-circle")
@@ -34,7 +34,7 @@
3434
scheme: :invisible,
3535
tag: :a,
3636
href: uncheck_all_url,
37-
data: { turbo_stream: true }
37+
data: { action: "click->admin--jira-projects#uncheckAll" }
3838
)
3939
) do |button|
4040
button.with_leading_visual_icon(icon: :"x-circle")

app/components/admin/import/jira/import_runs/select_projects/modal_component.html.erb

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,24 @@
3939
I18n.t(:button_cancel)
4040
end
4141
modal_footer.with_component(
42-
Admin::Import::Jira::ImportRuns::SelectProjects::ModalSubmitComponent.new(
43-
jira_import: @jira_import,
44-
count: selected_count
45-
)
42+
content_tag(:div, data: { "admin--jira-projects-target": "submitButton" }) {
43+
render(Admin::Import::Jira::ImportRuns::SelectProjects::ModalSubmitComponent.new(
44+
jira_import: @jira_import,
45+
count: selected_count
46+
))
47+
}
4648
)
49+
modal_footer.with_component(
50+
Primer::Beta::Button.new(
51+
scheme: :primary,
52+
tag: :a,
53+
hidden: true,
54+
data: { "admin--jira-projects-target": "spinnerButton" }
55+
)
56+
) do |spinner_button|
57+
spinner_button.with_trailing_visual_icon(icon: :sync, animation: :rotate, style: "min-width: 2rem")
58+
I18n.t(:button_continue)
59+
end
4760
end
4861
end
4962
end

app/components/admin/import/jira/import_runs/select_projects/modal_submit_component.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
}
1111
)
1212
) do |button|
13-
button.with_trailing_visual_counter(count: count)
13+
button.with_trailing_visual_counter(count: count, style: "min-width: 2rem")
1414
I18n.t(:button_continue)
1515
end
1616
end %>

0 commit comments

Comments
 (0)