Skip to content

Commit 3702c81

Browse files
committed
Merge remote-tracking branch 'upstream/main' into fix/786
* upstream/main: New study.yml format (JabRef#13844) Separate issue linking workflows, make them run on `edited` (JabRef#14121)
2 parents d742b54 + db1e651 commit 3702c81

24 files changed

+1130
-201
lines changed

.github/ghprcomment.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170
# PR hygiene
171171

172172
- jobName: 'Ensure that contributor is assigned (fails if not commented on issue)'
173-
workflowName: 'On PR opened/updated'
173+
workflowName: 'Link PR to Issue'
174174
message: >
175175
You did not assign yourself to the issue.
176176
Thus, it looks like you skipped reading our [CONTRIBUTING.md](https://github.com/JabRef/jabref/blob/main/CONTRIBUTING.md), which explains exactly how to participate. No worries, it happens to the best of us.
@@ -196,7 +196,7 @@
196196
message: >
197197
Note that your PR will not be reviewed/accepted until you have gone through the mandatory checks in the description and marked each of them them exactly in the format of `[x]` (done), `[ ]` (not done yet) or `[/]` (not applicable).
198198
- jobName: 'Determine issue number'
199-
workflowName: 'On PR opened/updated'
199+
workflowName: 'Link PR to Issue'
200200
always: true
201201
message: |
202202
Your pull request needs to link an issue correctly.

.github/workflows/link-issue.yml

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
name: Link PR to Issue
2+
3+
on:
4+
pull_request_target:
5+
types: [opened, reopened, edited]
6+
7+
jobs:
8+
determine_issue_number:
9+
name: Determine issue number
10+
runs-on: ubuntu-latest
11+
if: >
12+
(github.repository == 'JabRef/jabref') &&
13+
(github.event.pull_request.head.repo.full_name != 'JabRef/jabref') &&
14+
!(
15+
(github.event.pull_request.user.login == 'dependabot[bot]') || (github.event.pull_request.user.login == 'renovate-bot') ||
16+
(
17+
startsWith(github.event.pull_request.title, '[Bot] ') ||
18+
startsWith(github.event.pull_request.title, 'Bump ') ||
19+
startsWith(github.event.pull_request.title, 'New Crowdin updates') ||
20+
startsWith(github.event.pull_request.title, 'Update Gradle Wrapper from')
21+
)
22+
)
23+
permissions:
24+
contents: read
25+
outputs:
26+
issue_number: ${{ steps.get_issue_number.outputs.ticketNumber }}
27+
steps:
28+
- name: echo PR data
29+
run: |
30+
echo "PR Number: ${{ github.event.pull_request.number }}"
31+
echo "PR URL: ${{ github.event.pull_request.html_url }}"
32+
cat <<EOF
33+
PR Body:
34+
${{ github.event.pull_request.body }}
35+
EOF
36+
- name: Determine issue number
37+
id: get_issue_number
38+
uses: koppor/ticket-check-action@add-output
39+
with:
40+
token: ${{ secrets.GITHUB_TOKEN }}
41+
ticketLink: 'https://github.com/JabRef/jabref/issues/%ticketNumber%'
42+
ticketPrefix: '#'
43+
titleRegex: '^#(?<ticketNumber>\d+)'
44+
branchRegex: '^(?<ticketNumber>\d+)'
45+
# Matches GitHub's closes/fixes/resolves #{number}, but does not match our example `Closes #13109` in PULL_REQUEST_TEMPLATE
46+
# Also matches URLs that are wrapped in `<>`.
47+
bodyRegex: '(?<action>fixes|closes|resolves|refs)\s+<?(?:https?:\/\/github\.com\/JabRef\/jabref\/issues\/)?#?(?<ticketNumber>(?!13109\b)\d+)>?'
48+
bodyRegexFlags: 'i'
49+
outputOnly: true
50+
- run: echo "${{ steps.get_issue_number.outputs.ticketNumber }}"
51+
- name: Issue number present
52+
if: steps.get_issue_number.outputs.ticketNumber == '-1'
53+
run: |
54+
echo "No valid ticket number found!"
55+
exit 1
56+
57+
move_issue:
58+
name: Mark issue as in progress
59+
# after determine_issue_number to ensure that there is only one failure because of no ticket number
60+
needs: determine_issue_number
61+
runs-on: ubuntu-latest
62+
permissions:
63+
issues: write
64+
steps:
65+
- name: Move issue to "In Progress" in "Good First Issues"
66+
uses: m7kvqbe1/github-action-move-issues/@main
67+
with:
68+
github-token: ${{ secrets.GH_TOKEN_ACTION_MOVE_ISSUE }}
69+
project-url: "https://github.com/orgs/JabRef/projects/5"
70+
target-labels: "📍 Assigned"
71+
target-column: "In Progress"
72+
ignored-columns: ""
73+
default-column: "In Progress"
74+
issue-number: ${{ needs.determine_issue_number.outputs.issue_number }}
75+
skip-if-not-in-project: true
76+
- name: Move issue to "In Progress" in "Candidates for University Projects"
77+
uses: m7kvqbe1/github-action-move-issues/@main
78+
with:
79+
github-token: ${{ secrets.GH_TOKEN_ACTION_MOVE_ISSUE }}
80+
project-url: "https://github.com/orgs/JabRef/projects/3"
81+
target-labels: "📍 Assigned"
82+
target-column: "In Progress"
83+
ignored-columns: ""
84+
default-column: "In Progress"
85+
issue-number: ${{ needs.determine_issue_number.outputs.issue_number }}
86+
skip-if-not-in-project: true
87+
88+
ensure_assignment:
89+
name: Ensure that contributor is assigned (fails if not commented on issue)
90+
if: github.event.pull_request.head.repo.full_name != 'JabRef/jabref'
91+
# after determine_issue_number to ensure that there is only one failure because of no ticket number
92+
needs: determine_issue_number
93+
runs-on: ubuntu-latest
94+
permissions:
95+
issues: write
96+
steps:
97+
- uses: actions/checkout@v5
98+
with:
99+
show-progress: 'false'
100+
- name: Assign PR creator to issue
101+
run: |
102+
set -e
103+
104+
echo "Updating issue '${{ needs.determine_issue_number.outputs.issue_number }}'"
105+
106+
# "gh issue edit" cannot be used - workaround found at https://github.com/cli/cli/issues/9620#issuecomment-2703135049
107+
108+
ASSIGNEES=$(gh api /repos/JabRef/jabref/issues/${{ needs.determine_issue_number.outputs.issue_number }} --jq '[.assignees[].login]')
109+
110+
# Check if the user is already assigned
111+
if echo "$ASSIGNEES" | jq -e '. | index("${{ github.event.pull_request.user.login }}")' >/dev/null; then
112+
echo "User '${{ github.event.pull_request.user.login }}' is already an assignee. No update needed."
113+
echo "Debug: $ASSIGNEES"
114+
exit 0
115+
fi
116+
117+
# Append the new assignee
118+
UPDATED_ASSIGNEES=$(echo "$ASSIGNEES" | jq --arg new "${{ github.event.pull_request.user.login }}" '. + [$new]')
119+
120+
LABELS=$(gh api repos/${{ github.repository }}/issues/${{ needs.determine_issue_number.outputs.issue_number }}/labels --jq '.[].name')
121+
LABEL=$(echo "$LABELS" | grep -E '^good (first|second|third|forth) issue$' || true)
122+
if [ -n "$LABEL" ]; then
123+
echo "✅ Found label: $LABEL"
124+
SILENT=false
125+
# Apply label
126+
gh issue edit "${{ github.event.pull_request.number }}" --add-label "$LABEL"
127+
else
128+
echo "🚫 Silent fail if not possible to add assignee"
129+
SILENT=true
130+
fi
131+
132+
# Update issue with the new assignee list
133+
echo "Updating issue #${{ needs.determine_issue_number.outputs.issue_number }} updated with assignees: $UPDATED_ASSIGNEES..."
134+
if [ "$SILENT" = true ]; then
135+
gh api -X PATCH /repos/JabRef/jabref/issues/${{ needs.determine_issue_number.outputs.issue_number }} --input <(echo "{\"assignees\": $UPDATED_ASSIGNEES}") || true
136+
else
137+
gh api -X PATCH /repos/JabRef/jabref/issues/${{ needs.determine_issue_number.outputs.issue_number }} --input <(echo "{\"assignees\": $UPDATED_ASSIGNEES}")
138+
fi
139+
env:
140+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
141+
- name: Add label "📌 Pinned"
142+
run: gh issue edit ${{ needs.determine_issue_number.outputs.issue_number }} --add-label "📌 Pinned"
143+
env:
144+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/on-pr-opened-updated.yml

Lines changed: 0 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -6,141 +6,6 @@ on:
66
# default: opened, synchronize, reopened
77

88
jobs:
9-
determine_issue_number:
10-
name: Determine issue number
11-
runs-on: ubuntu-latest
12-
if: >
13-
(github.repository == 'JabRef/jabref') &&
14-
(github.event.pull_request.head.repo.full_name != 'JabRef/jabref') &&
15-
!(
16-
(github.event.pull_request.user.login == 'dependabot[bot]') || (github.event.pull_request.user.login == 'renovate-bot') ||
17-
(
18-
startsWith(github.event.pull_request.title, '[Bot] ') ||
19-
startsWith(github.event.pull_request.title, 'Bump ') ||
20-
startsWith(github.event.pull_request.title, 'New Crowdin updates') ||
21-
startsWith(github.event.pull_request.title, 'Update Gradle Wrapper from')
22-
)
23-
)
24-
permissions:
25-
contents: read
26-
outputs:
27-
issue_number: ${{ steps.get_issue_number.outputs.ticketNumber }}
28-
steps:
29-
- name: echo PR data
30-
run: |
31-
echo "PR Number: ${{ github.event.pull_request.number }}"
32-
echo "PR URL: ${{ github.event.pull_request.html_url }}"
33-
cat <<EOF
34-
PR Body:
35-
${{ github.event.pull_request.body }}
36-
EOF
37-
- name: Determine issue number
38-
id: get_issue_number
39-
uses: koppor/ticket-check-action@add-output
40-
with:
41-
token: ${{ secrets.GITHUB_TOKEN }}
42-
ticketLink: 'https://github.com/JabRef/jabref/issues/%ticketNumber%'
43-
ticketPrefix: '#'
44-
titleRegex: '^#(?<ticketNumber>\d+)'
45-
branchRegex: '^(?<ticketNumber>\d+)'
46-
# Matches GitHub's closes/fixes/resolves #{number}, but does not match our example `Closes #13109` in PULL_REQUEST_TEMPLATE
47-
# Also matches URLs that are wrapped in `<>`.
48-
bodyRegex: '(?<action>fixes|closes|resolves|refs)\s+<?(?:https?:\/\/github\.com\/JabRef\/jabref\/issues\/)?#?(?<ticketNumber>(?!13109\b)\d+)>?'
49-
bodyRegexFlags: 'i'
50-
outputOnly: true
51-
- run: echo "${{ steps.get_issue_number.outputs.ticketNumber }}"
52-
- name: Issue number present
53-
if: steps.get_issue_number.outputs.ticketNumber == '-1'
54-
run: |
55-
echo "No valid ticket number found!"
56-
exit 1
57-
move_issue:
58-
name: Mark issue as in progress
59-
# after determine_issue_number to ensure that there is only one failure because of no ticket number
60-
needs: determine_issue_number
61-
runs-on: ubuntu-latest
62-
permissions:
63-
issues: write
64-
steps:
65-
- name: Move issue to "In Progress" in "Good First Issues"
66-
uses: m7kvqbe1/github-action-move-issues/@main
67-
with:
68-
github-token: ${{ secrets.GH_TOKEN_ACTION_MOVE_ISSUE }}
69-
project-url: "https://github.com/orgs/JabRef/projects/5"
70-
target-labels: "📍 Assigned"
71-
target-column: "In Progress"
72-
ignored-columns: ""
73-
default-column: "In Progress"
74-
issue-number: ${{ needs.determine_issue_number.outputs.issue_number }}
75-
skip-if-not-in-project: true
76-
- name: Move issue to "In Progress" in "Candidates for University Projects"
77-
uses: m7kvqbe1/github-action-move-issues/@main
78-
with:
79-
github-token: ${{ secrets.GH_TOKEN_ACTION_MOVE_ISSUE }}
80-
project-url: "https://github.com/orgs/JabRef/projects/3"
81-
target-labels: "📍 Assigned"
82-
target-column: "In Progress"
83-
ignored-columns: ""
84-
default-column: "In Progress"
85-
issue-number: ${{ needs.determine_issue_number.outputs.issue_number }}
86-
skip-if-not-in-project: true
87-
ensure_assignment:
88-
name: Ensure that contributor is assigned (fails if not commented on issue)
89-
if: github.event.pull_request.head.repo.full_name != 'JabRef/jabref'
90-
# after determine_issue_number to ensure that there is only one failure because of no ticket number
91-
needs: determine_issue_number
92-
runs-on: ubuntu-latest
93-
permissions:
94-
issues: write
95-
steps:
96-
- uses: actions/checkout@v5
97-
with:
98-
show-progress: 'false'
99-
- name: Assign PR creator to issue
100-
run: |
101-
set -e
102-
103-
echo "Updating issue '${{ needs.determine_issue_number.outputs.issue_number }}'"
104-
105-
# "gh issue edit" cannot be used - workaround found at https://github.com/cli/cli/issues/9620#issuecomment-2703135049
106-
107-
ASSIGNEES=$(gh api /repos/JabRef/jabref/issues/${{ needs.determine_issue_number.outputs.issue_number }} --jq '[.assignees[].login]')
108-
109-
# Check if the user is already assigned
110-
if echo "$ASSIGNEES" | jq -e '. | index("${{ github.event.pull_request.user.login }}")' >/dev/null; then
111-
echo "User '${{ github.event.pull_request.user.login }}' is already an assignee. No update needed."
112-
echo "Debug: $ASSIGNEES"
113-
exit 0
114-
fi
115-
116-
# Append the new assignee
117-
UPDATED_ASSIGNEES=$(echo "$ASSIGNEES" | jq --arg new "${{ github.event.pull_request.user.login }}" '. + [$new]')
118-
119-
LABELS=$(gh api repos/${{ github.repository }}/issues/${{ needs.determine_issue_number.outputs.issue_number }}/labels --jq '.[].name')
120-
LABEL=$(echo "$LABELS" | grep -E '^good (first|second|third|forth) issue$' || true)
121-
if [ -n "$LABEL" ]; then
122-
echo "✅ Found label: $LABEL"
123-
SILENT=false
124-
# Apply label
125-
gh issue edit "${{ github.event.pull_request.number }}" --add-label "$LABEL"
126-
else
127-
echo "🚫 Silent fail if not possible to add assignee"
128-
SILENT=true
129-
fi
130-
131-
# Update issue with the new assignee list
132-
echo "Updating issue #${{ needs.determine_issue_number.outputs.issue_number }} updated with assignees: $UPDATED_ASSIGNEES..."
133-
if [ "$SILENT" = true ]; then
134-
gh api -X PATCH /repos/JabRef/jabref/issues/${{ needs.determine_issue_number.outputs.issue_number }} --input <(echo "{\"assignees\": $UPDATED_ASSIGNEES}") || true
135-
else
136-
gh api -X PATCH /repos/JabRef/jabref/issues/${{ needs.determine_issue_number.outputs.issue_number }} --input <(echo "{\"assignees\": $UPDATED_ASSIGNEES}")
137-
fi
138-
env:
139-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
140-
- name: Add label "📌 Pinned"
141-
run: gh issue edit ${{ needs.determine_issue_number.outputs.issue_number }} --add-label "📌 Pinned"
142-
env:
143-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1449
conflicts_with_target:
14510
if: github.repository == 'JabRef/jabref'
14611
name: Conflicts with target branch

.github/workflows/pr-comment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ name: Comment on PR
88
on:
99
workflow_run:
1010
# note when updating via a PR and testing - `workflow_run` executes from the `main` branch and not the PR branch
11-
workflows: ["Source Code Tests", "On PR opened/updated", "Check PR Format", "Check PR Modifications", "Check PR CHANGELOG.md"]
11+
workflows: ["Source Code Tests", "On PR opened/updated", "Check PR Format", "Link PR to Issue", "Check PR Modifications", "Check PR CHANGELOG.md"]
1212
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#running-a-workflow-based-on-the-conclusion-of-another-workflow
1313
types: [completed]
1414
workflow_dispatch:

jabgui/src/main/java/org/jabref/gui/slr/EditExistingStudyAction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import org.jabref.gui.actions.ActionHelper;
99
import org.jabref.gui.actions.SimpleCommand;
1010
import org.jabref.logic.crawler.StudyRepository;
11-
import org.jabref.logic.crawler.StudyYamlParser;
11+
import org.jabref.logic.crawler.StudyYamlService;
1212
import org.jabref.logic.l10n.Localization;
1313
import org.jabref.model.database.BibDatabaseContext;
1414
import org.jabref.model.study.Study;
@@ -51,7 +51,7 @@ public void execute() {
5151

5252
Study study;
5353
try {
54-
study = new StudyYamlParser().parseStudyYamlFile(studyDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME));
54+
study = new StudyYamlService().parseStudyYamlFile(studyDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME));
5555
} catch (IOException e) {
5656
dialogService.showErrorDialogAndWait(Localization.lang("Error opening file"), e);
5757
return;

jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import org.jabref.gui.DialogService;
1818
import org.jabref.gui.WorkspacePreferences;
1919
import org.jabref.logic.crawler.StudyRepository;
20-
import org.jabref.logic.crawler.StudyYamlParser;
20+
import org.jabref.logic.crawler.StudyYamlService;
2121
import org.jabref.logic.git.GitHandler;
2222
import org.jabref.logic.importer.ImportFormatPreferences;
2323
import org.jabref.logic.importer.ImporterPreferences;
@@ -30,7 +30,7 @@
3030
import org.jabref.logic.importer.fetcher.SpringerNatureWebFetcher;
3131
import org.jabref.logic.l10n.Localization;
3232
import org.jabref.model.study.Study;
33-
import org.jabref.model.study.StudyDatabase;
33+
import org.jabref.model.study.StudyCatalog;
3434
import org.jabref.model.study.StudyQuery;
3535

3636
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -103,15 +103,15 @@ public ManageStudyDefinitionViewModel(@NonNull Study study,
103103
title.setValue(study.getTitle());
104104
researchQuestions.addAll(study.getResearchQuestions());
105105
queries.addAll(study.getQueries().stream().map(StudyQuery::getQuery).toList());
106-
List<StudyDatabase> studyDatabases = study.getDatabases();
106+
List<StudyCatalog> studyCatalogs = study.getCatalogs();
107107
databases.addAll(WebFetchers.getSearchBasedFetchers(importFormatPreferences, importerPreferences)
108108
.stream()
109109
.map(SearchBasedFetcher::getName)
110110
// The user wants to select specific fetchers
111111
// The fetcher summarizing ALL fetchers can be emulated by selecting ALL fetchers (which happens rarely when doing an SLR)
112112
.filter(name -> !CompositeSearchBasedFetcher.FETCHER_NAME.equals(name))
113113
.map(name -> {
114-
boolean enabled = studyDatabases.contains(new StudyDatabase(name, true));
114+
boolean enabled = studyCatalogs.contains(new StudyCatalog(name, true));
115115
return new StudyCatalogItem(name, enabled);
116116
})
117117
.toList());
@@ -172,7 +172,7 @@ public SlrStudyAndDirectory saveStudy() {
172172
title.getValueSafe(),
173173
researchQuestions,
174174
queries.stream().map(StudyQuery::new).collect(Collectors.toList()),
175-
databases.stream().map(studyDatabaseItem -> new StudyDatabase(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).filter(StudyDatabase::isEnabled).collect(Collectors.toList()));
175+
databases.stream().map(studyDatabaseItem -> new StudyCatalog(studyDatabaseItem.getName(), studyDatabaseItem.isEnabled())).filter(StudyCatalog::isEnabled).collect(Collectors.toList()));
176176
Path studyDirectory;
177177
final String studyDirectoryAsString = directory.getValueSafe();
178178
try {
@@ -185,7 +185,7 @@ public SlrStudyAndDirectory saveStudy() {
185185
}
186186
Path studyDefinitionFile = studyDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME);
187187
try {
188-
new StudyYamlParser().writeStudyYamlFile(study, studyDefinitionFile);
188+
new StudyYamlService().writeStudyYamlFile(study, studyDefinitionFile);
189189
} catch (IOException e) {
190190
LOGGER.error("Could not write study file {}", studyDefinitionFile, e);
191191
dialogService.notify(Localization.lang("Please enter a valid file path.") +

0 commit comments

Comments
 (0)