Skip to content

Commit

Permalink
Merge pull request #699 from git-commit-id/674
Browse files Browse the repository at this point in the history
#674: change timeformat from RFC822 to ISO 8601 to support maven's reproducible build feature
  • Loading branch information
TheSnoozer authored Feb 28, 2024
2 parents 4c638aa + fcd414d commit 6ab02b1
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 24 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/default-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
needs: checkstyle
strategy:
matrix:
java_version: ['11', '12', '13', '14', '15', '16', '17', '18', '19', '20']
java_version: ['11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21']

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -59,7 +59,7 @@ jobs:
strategy:
matrix:
java_version: ['11']
maven_version: ['3.2.5', '3.3.9', '3.5.4', '3.6.3', '3.8.8', '3.9.1', '3.9.2', '4.0.0-alpha-7']
maven_version: ['3.2.5', '3.3.9', '3.5.4', '3.6.3', '3.8.8', '3.9.6', '4.0.0-alpha-12']

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>target/testing.properties</generateGitPropertiesFilename>
<dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
<!-- <dateFormat>yyyy-MM-dd'T'HH:mm:ssXXX</dateFormat> -->
<dateFormatTimeZone>GMT-08:00</dateFormatTimeZone>
<useNativeGit>false</useNativeGit>
<abbrevLength>7</abbrevLength>
Expand Down
41 changes: 22 additions & 19 deletions src/main/java/pl/project13/maven/git/GitCommitIdMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@

package pl.project13.maven.git;

import com.google.common.annotations.VisibleForTesting;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Collections;
import java.util.Date;
import java.util.List;
Expand All @@ -44,6 +44,7 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Settings;
import org.joda.time.DateTime;
import org.sonatype.plexus.build.incremental.BuildContext;
import pl.project13.core.CommitIdGenerationMode;
import pl.project13.core.CommitIdPropertiesOutputFormat;
Expand Down Expand Up @@ -497,20 +498,28 @@ public class GitCommitIdMojo extends AbstractMojo {
* represents dates or times exported by this plugin (e.g. {@code git.commit.time}, {@code
* git.build.time}). It should be a valid {@link SimpleDateFormat} string.
*
* <p>The current dateFormat is set to match maven's default {@code yyyy-MM-dd'T'HH:mm:ssZ}.
* Please note that in previous versions (2.2.0 - 2.2.2) the default dateFormat was set to: {@code
* dd.MM.yyyy '@' HH:mm:ss z}. However the {@code RFC 822 time zone} seems to give a more reliable
* option in parsing the date and it's being used in maven as default.
* <p>The current dateFormat will be formatted as ISO 8601
* {@code yyyy-MM-dd'T'HH:mm:ssXXX} and therefore can be used as input to maven's
* <a href="https://maven.apache.org/guides/mini/guide-reproducible-builds.html">
* reproducible build</a> feature.
*
* Please note that in previous versions
* (2.2.2 - 7.0.1) the default format was set to {@code yyyy-MM-dd'T'HH:mm:ssZ}
* which produces a {@code RFC 822 time zone}. While such format gives reliable
* options in parsing the date, it does not comply with the requirements of
* the reproducible build feature.
* (2.2.0 - 2.2.2) the default dateFormat was set to: {@code
* dd.MM.yyyy '@' HH:mm:ss z}.
*
* <p>Example:
*
* <pre>{@code
* <dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
* <dateFormat>yyyy-MM-dd'T'HH:mm:ssXXX</dateFormat>
* }</pre>
*
* @since 2.2.0
*/
@Parameter(defaultValue = "yyyy-MM-dd'T'HH:mm:ssZ")
@Parameter(defaultValue = "yyyy-MM-dd'T'HH:mm:ssXXX")
String dateFormat;

/**
Expand Down Expand Up @@ -1454,32 +1463,26 @@ private Properties getContextProperties(MavenProject project) {
* href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>.
*
* <p>Inspired by
* https://github.com/apache/maven-archiver/blob/a3103d99396cd8d3440b907ef932a33563225265/src/main/java/org/apache/maven/archiver/MavenArchiver.java#L765
* https://github.com/apache/maven-archiver/blob/7acb1db4a9754beacde3f21a69e5523ee901abd5/src/main/java/org/apache/maven/archiver/MavenArchiver.java#L755
*
* @param outputTimestamp the value of <code>${project.build.outputTimestamp}</code> (may be
* <code>null</code>)
* @return the parsed timestamp, may be <code>null</code> if <code>null</code> input or input
* contains only 1 character
*/
private Date parseOutputTimestamp(String outputTimestamp) throws GitCommitIdExecutionException {
@VisibleForTesting
protected static Date parseOutputTimestamp(String outputTimestamp) {
if (outputTimestamp != null
&& !outputTimestamp.trim().isEmpty()
&& outputTimestamp.chars().allMatch(Character::isDigit)) {
return new Date(Long.parseLong(outputTimestamp) * 1000);
return Date.from(Instant.ofEpochSecond(Long.parseLong(outputTimestamp)));
}

if ((outputTimestamp == null) || (outputTimestamp.length() < 2)) {
// no timestamp configured
return null;
}

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
try {
return df.parse(outputTimestamp);
} catch (ParseException pe) {
throw new GitCommitIdExecutionException(
"Invalid 'project.build.outputTimestamp' value '" + outputTimestamp + "'", pe);
}
return new DateTime(outputTimestamp).toDate();
}

private void publishPropertiesInto(Properties propertiesToPublish, Properties propertiesTarget) {
Expand Down
69 changes: 69 additions & 0 deletions src/test/java/pl/project13/maven/git/GitCommitIdMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@

import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.util.Date;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.joda.time.DateTime;
import org.junit.Test;
import org.junit.runner.RunWith;
import pl.project13.core.PropertiesFileGenerator;

/**
* Testcases to verify that the git-commit-id works properly.
*/
@RunWith(JUnitParamsRunner.class)
public class GitCommitIdMojoTest {
@Test
public void testCraftPropertiesOutputFileWithRelativePath() throws IOException {
Expand Down Expand Up @@ -66,4 +73,66 @@ public void testCraftPropertiesOutputFileWithFullPath() throws IOException {
.toFile()
.getCanonicalPath());
}

/**
* test cases for output timestamp parsing.
* This timestamp is configured for Reproducible Builds' archive entries
* (https://maven.apache.org/guides/mini/guide-reproducible-builds.html). The value from <code>
* ${project.build.outputTimestamp}</code> is either formatted as ISO 8601 <code>
* yyyy-MM-dd'T'HH:mm:ssXXX</code> or as an int representing seconds since the epoch (like <a
* href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>.
* When using ISO 8601 formatting please note that the entire expression must be entirely either
* in the basic format (20240215T135459+0100) or in the
* extended format (e.g. 2024-02-15T13:54:59+01:00).
* The maven plugin only supports the extended format.
*/
private Object[] parametersParseOutputTimestamp() {
return new Object[] {
// long since epoch
new Object[] {
"1644689403"
},
// Date and time with timezone:
new Object[] {
"2022-02-12T15:30+00:00"
},
new Object[] {
"2022-02-12T15:30:45-05:00"
},
new Object[] {
"2022-02-12T15:30:00+00:00"
},
new Object[] {
"2023-11-30T09:17:06+05:30"
},
new Object[] {
"2024-08-15T20:45:30-03:00"
},
new Object[] {
"2022-02-12T15:30:00Z"
},
new Object[] {
"2023-11-30T09:17:06+0100"
},
// Lowercase time designator
new Object[] {
"2019-03-26t14:00Z"
},
// Lowercase UTC designator
new Object[] {
"2019-03-26T14:00z"
},
// Hours-only offset
new Object[] {
"2019-03-26T10:00-04"
},
};
}

@Test
@Parameters(method = "parametersParseOutputTimestamp")
public void testParseOutputTimestamp(String input) {
Date actual = GitCommitIdMojo.parseOutputTimestamp(input);
assertThat(actual).isNotNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public class NativeAndJGitProviderTest extends GitIntegrationTest {
"git.local.branch.behind",
};

private static final String DEFAULT_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ssZ";
private static final String ISO8601_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ssZZ";
private static final String DEFAULT_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ssXXX";
private static final String ISO8601_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ssXXX";

@Test
public void testCompareBasic() throws Exception {
Expand Down

0 comments on commit 6ab02b1

Please sign in to comment.