Skip to content
Merged
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
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 pepperkit
Copyright (c) 2023 pepperkit

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
21 changes: 7 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=pepperkit_git-hooks-maven-plugin&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=pepperkit_git-hooks-maven-plugin)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=pepperkit_git-hooks-maven-plugin&metric=security_rating)](https://sonarcloud.io/dashboard?id=pepperkit_git-hooks-maven-plugin)

Maven plugin for easy git hooks configuration. Provides three goals to work with git hooks:
1. `initHooks` - installs configured git hooks;
2. `printHooks` - prints all or specific hooks installed at the moment, to make sure that the plugin was configured correctly;
3. `executeHooks` - executes all or specific hooks installed at the moment, to make sure that the hooks work as expected,
without the need to actually trigger the hook with git action.
Maven plugin for easy git hooks configuration.

## Usage
Add the plugin into your `pom.xml`, configure the hooks, and optionally set the execution to install the hooks each time
the project is rebuild.
Add the plugin into your `pom.xml`, configure the hooks, and set the execution to install the hooks each time
the project is rebuild. Be aware that for hooks to be installed to git, any `mvn` goal should be first executed,
like `compile` or `test`. It means that after editing git-hooks-maven-plugin configuration in `pom.xml`,
it's necessary to manually run `mvn compile` or any other maven goal, on the initializing step of which git hooks will be installed.

The example with *pre-commit* and *pre-push* hooks configured, will look like it:
```xml
Expand Down Expand Up @@ -43,13 +41,6 @@ The example with *pre-commit* and *pre-push* hooks configured, will look like it
Hook's content is any command line script, which is considered successful if exit code is equal to `0`, and not otherwise.
If execution of the script is successful, git action will be proceeded, if not - it will be cancelled.

Then you can execute one of the following goals manually:
1. `mvn io.github.pepperkit:git-hooks-maven-plugin:initHooks` - to manually install configured git hooks;
2. `mvn io.github.pepperkit:git-hooks-maven-plugin:printHooks` - print all the installed hooks to the console;
3. `mvn -DhookName=<hookName> io.github.pepperkit:git-hooks-maven-plugin:printHooks` - print only the specified hook;
4. `mvn io.github.pepperkit:git-hooks-maven-plugin:executeHooks` - execute all the installed hooks;
5. `mvn -DhookName=<hookName> io.github.pepperkit:git-hooks-maven-plugin:executeHooks` - execute only the specified hook.

## Project's structure
```
└── src
Expand All @@ -58,3 +49,5 @@ Then you can execute one of the following goals manually:
└── system-test # system tests
└── resources # system tests scenarios and pre-configured pom files needed for the tests
```

More about pepperkit projects could be found on its website: https://pepperkit.github.io/
3 changes: 1 addition & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.3.0</version>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -210,7 +210,6 @@
</dependencies>
<configuration>
<configLocation>${checkstyle.url}</configLocation>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<linkXRef>false</linkXRef>
Expand Down
45 changes: 7 additions & 38 deletions src/main/java/io/github/pepperkit/githooks/GitHooksManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import net.lingala.zip4j.ZipFile;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugin.logging.SystemStreamLog;

Expand Down Expand Up @@ -131,41 +135,6 @@ List<File> getExistingHookFiles() {
.collect(Collectors.toList());
}

/**
* Checks if the plugin is launched the first time (`archived` directory is already created).
* @return true if it's launched first time, false - otherwise
*/
boolean isFirstLaunchOfPlugin() {
return !Files.exists(ARCHIVES_PATH);
}

/**
* Backups existing hook files into a zip file.
* @param hookFiles hook files to back up
* @throws IllegalStateException if an error occurs on writing the backup file
*/
void backupExistingHooks(List<File> hookFiles) {
try {
Files.createDirectories(ARCHIVES_PATH);
zipFiles(hookFiles, ARCHIVES_PATH.resolve("hooks_" + formatter.format(Instant.now()) + ".zip").toString());
} catch (IOException e) {
throw new IllegalStateException("Cannot create backup for existing hooks", e);
}
}

private void zipFiles(List<File> srcFiles, String outputFileName) throws IOException {
if (srcFiles.isEmpty()) {
logger.debug("No hooks existed, nothing to backup");
return;
}

logger.info("Making backup of the existing hooks. "
+ "They will be available in directory: " + ARCHIVES_PATH);
try (ZipFile backup = new ZipFile(outputFileName)) {
backup.addFiles(srcFiles);
}
}

/**
* Writes hook file with the specified name and value.
* @param hookName hook's name
Expand Down
10 changes: 0 additions & 10 deletions src/main/java/io/github/pepperkit/githooks/InitHooksMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,13 @@ public void setHooks(String hooks) {
public void execute() throws MojoExecutionException {
List<File> existingHookFiles = gitHooksManager.getExistingHookFiles();
if (hooks == null) {
gitHooksManager.backupExistingHooks(existingHookFiles);
existingHookFiles.forEach(File::delete);
return;
}

if (gitHooksManager.isFirstLaunchOfPlugin() && !existingHookFiles.isEmpty()) {
throw new MojoExecutionException("There are existing hooks detected, which were not created using this"
+ " plugin. Please, make sure that you transferred them to plugin's configuration "
+ "and delete them manually.");
}

gitHooksManager.checkProvidedHookNamesCorrectness(hooks);
gitHooksManager.checkGitHooksDirAndCreateIfMissing();

List<File> hookFiles = gitHooksManager.getExistingHookFiles();
gitHooksManager.backupExistingHooks(hookFiles);

String hookToBeCreated = null;
try {
for (Map.Entry<String, String> hook : hooks.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 PepperKit
* Copyright (C) 2023 PepperKit
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 PepperKit
* Copyright (C) 2023 PepperKit
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
Expand Down Expand Up @@ -57,6 +57,13 @@ public void previouslyAddedHooksAreArchived() throws IOException, InterruptedExc
.hasSize(1);
}

@Then("previously added hooks are not archived")
public void previouslyAddedHooksAreNotArchived() throws IOException, InterruptedException {
cmdResult = container.execInContainer("ls", ".git/hooks/archived");
assertThat(cmdResult.getStdout().split(" "))
.hasSize(0);
}

@Then("it prints all the hooks installed at the moment")
public void printsAllHooksInstalled() {
assertThat(cmdResult.getStdout())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 PepperKit
* Copyright (C) 2023 PepperKit
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
Expand Down Expand Up @@ -52,4 +52,16 @@ public void testGoalLaunchedWithPrePushHookSpecified() throws IOException, Inter
cmdResult = container.execInContainer("mvn", "-f", "pre_commit_push_hooks-pom.xml",
"-DhookName=pre-push", "io.github.pepperkit:git-hooks-maven-plugin:executeHooks");
}

@When("initHooks goal of the plugin is launched with the same plugin's configuration")
public void initWithHooksConfigured() throws IOException, InterruptedException {
cmdResult = container.execInContainer("mvn", "-f", "pre_commit_push_hooks-pom.xml",
"io.github.pepperkit:git-hooks-maven-plugin:initHooks");
assertThat(cmdResult.getStdout())
.contains("BUILD SUCCESS");

cmdResult = container.execInContainer("cat", ".git/hooks/pre-commit");
assertThat(cmdResult.getStdout())
.contains("pre-commit hook is invoked");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,3 @@ Feature: Initialize git hooks via initHooks goal
And initHooks goal was launched before with hooks presented in configuration
When initHooks goal of the plugin is launched with hooks deleted from plugin's configuration
Then previously added hooks are deleted

Scenario: Archives previously installed hooks
Given there's a maven project with git-hooks plugin configured
And git repository is set up for the project
And initHooks goal was launched before with hooks presented in configuration
When initHooks goal of the plugin is launched with another plugin's configuration
Then previously added hooks are archived
14 changes: 0 additions & 14 deletions src/test/java/io/github/pepperkit/githooks/InitHooksMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,6 @@ void initThrowsMojoExecutionExceptionIfCreatingOfHookFails() throws MojoExecutio
assertThat(excThrown.getMessage()).contains("pre-push");
}

@Test
void initThrowsExceptionIfItIsFirstLaunchAndThereAreExistingHooks() throws MojoExecutionException {
Map<String, String> hooks = new HashMap<>();
hooks.put("pre-commit", "mvn -B checkstyle:checkstyle");
initHooksMojo.hooks = hooks;

when(gitHooksManagerMock.getExistingHookFiles())
.thenReturn(Collections.singletonList(new File("pre-commit")));
when(gitHooksManagerMock.isFirstLaunchOfPlugin()).thenReturn(true);

MojoExecutionException excThrown = assertThrows(MojoExecutionException.class, initHooksMojo::execute);
assertThat(excThrown.getMessage()).containsIgnoringCase("there are existing hooks detected");
}

@Test
void setHooksToNullIfNullStringProvidedInConfiguration() {
initHooksMojo.setHooks("null");
Expand Down