Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions doc/changes/changelog.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 59 additions & 0 deletions doc/changes/changes_5.2.4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Project Keeper 5.2.4, released 2025-11-19

Code name: Early detection of the wrong issue number in the changelog

## Summary

Wrong issue number in the changelog is only detected during release

## Features

* #695: Wrong issue number in the changelog is only detected during release

## Dependency Updates

### Project Keeper Core

#### Compile Dependency Updates

* Updated `com.exasol:project-keeper-shared-model-classes:5.2.3` to `5.2.4`

#### Runtime Dependency Updates

* Updated `com.exasol:project-keeper-java-project-crawler:5.2.3` to `5.2.4`

#### Test Dependency Updates

* Updated `com.exasol:project-keeper-shared-test-setup:5.2.3` to `5.2.4`

### Project Keeper Command Line Interface

#### Compile Dependency Updates

* Updated `com.exasol:project-keeper-core:5.2.3` to `5.2.4`

#### Test Dependency Updates

* Updated `com.exasol:project-keeper-shared-test-setup:5.2.3` to `5.2.4`

### Project Keeper Maven Plugin

#### Compile Dependency Updates

* Updated `com.exasol:project-keeper-core:5.2.3` to `5.2.4`

### Project Keeper Java Project Crawler

#### Compile Dependency Updates

* Updated `com.exasol:project-keeper-shared-model-classes:5.2.3` to `5.2.4`

#### Test Dependency Updates

* Updated `com.exasol:project-keeper-shared-test-setup:5.2.3` to `5.2.4`

### Project Keeper Shared Test Setup

#### Compile Dependency Updates

* Updated `com.exasol:project-keeper-shared-model-classes:5.2.3` to `5.2.4`
2 changes: 1 addition & 1 deletion parent-pom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</license>
</licenses>
<properties>
<revision>5.2.3</revision>
<revision>5.2.4</revision>
<!-- Integration test ProjectKeeperMojoIT starts a Maven build which requires Java 17. -->
<java.version>17</java.version>
<maven.version>3.9.11</maven.version>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package com.exasol.projectkeeper.validators.changesfile;

import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import com.exasol.errorreporting.ExaError;
import com.exasol.projectkeeper.Logger;
import com.exasol.projectkeeper.shared.ExasolVersionMatcher;
import com.exasol.projectkeeper.sources.AnalyzedSource;
import com.exasol.projectkeeper.sources.analyze.generic.RepoNameReader;
import com.exasol.projectkeeper.validators.AbstractFileValidator;
import com.exasol.projectkeeper.validators.finding.SimpleValidationFinding;
import com.exasol.projectkeeper.validators.finding.SimpleValidationFinding.Fix;
import com.exasol.projectkeeper.validators.finding.ValidationFinding;
import com.exasol.projectkeeper.validators.release.github.GitHubAdapter;
import com.exasol.projectkeeper.validators.release.github.IssueState;

import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toSet;

/**
* Validator that checks the existence of the doc/changes/changes_X.X.X.md file for the current project's version.
Expand All @@ -27,6 +31,9 @@ public class ChangesFileValidator extends AbstractFileValidator {
private final List<AnalyzedSource> sources;
private final String projectVersion;
private final ChangesFileIO changesFileIO;
private final GitHubAdapter gitHubAdapter;
private final Path changesFilePath;
private final ChangesFile changesFile;

/**
* Create a new instance of {@link ChangesFileValidator}
Expand All @@ -48,6 +55,14 @@ public ChangesFileValidator(final String projectVersion, final String projectNam
this.projectName = projectName;
this.sources = sources;
this.changesFileIO = changesFileIO;
this.gitHubAdapter = getGithubAdapter(projectDirectory);
this.changesFilePath = projectDirectory.resolve(ChangesFile.getPathForVersion(projectVersion));
this.changesFile = changesFileIO.read(changesFilePath);
}

private GitHubAdapter getGithubAdapter(final Path projectDirectory) {
final String repoName = RepoNameReader.getRepoName(projectDirectory);
return GitHubAdapter.connect(repoName);
}

@Override
Expand All @@ -66,7 +81,7 @@ protected List<ValidationFinding> validateContent(final Path file) {
final ChangesFile changesFile = changesFileIO.read(file);
return Stream
.of(validateDependencySection(file, changesFile), validateSummarySection(changesFile),
validateProjectName(changesFile))
validateProjectName(changesFile), validateIssuesClosed())
.filter(Optional::isPresent) //
.map(Optional::get) //
.toList();
Expand Down Expand Up @@ -111,6 +126,36 @@ private Optional<ValidationFinding> validateProjectName(final ChangesFile change
}
}

// [impl->dsn~verify-release-mode.verify-issues-closed~1]
private Optional<ValidationFinding> validateIssuesClosed() {
final List<Integer> wrongIssues = getIssuesWronglyMarkedAsClosed();
if (!wrongIssues.isEmpty()) {
return finding(ExaError.messageBuilder("E-PK-CORE-186").message(
"The following GitHub issues are marked as fixed in {{changes file}} but are not closed in GitHub: {{issue numbers}}",
changesFilePath, wrongIssues).toString());
}
return noFinding();
}

private List<Integer> getIssuesWronglyMarkedAsClosed() {
final Set<Integer> mentionedTickets = changesFile.getFixedIssues().stream().map(FixedIssue::issueNumber)
.collect(toSet());
final Set<Integer> stillOpenIssues = new HashSet<>();
for (final Integer issue : mentionedTickets) {
final IssueState state = gitHubAdapter.getIssueState(issue);
if (state != IssueState.CLOSED) {
stillOpenIssues.add(issue);
}
}
return sort(stillOpenIssues);
}

private List<Integer> sort(final Set<Integer> numbers) {
final ArrayList<Integer> list = new ArrayList<>(numbers);
list.sort(Comparator.naturalOrder());
return list;
}

private Optional<ValidationFinding> finding(final String message) {
return Optional.of(SimpleValidationFinding.withMessage(message).build());
}
Expand Down