Initial import

This commit is contained in:
Paul Campbell 2020-04-02 20:04:14 +01:00
parent 865b7ed1d5
commit 9929bfe5e1
11 changed files with 410 additions and 0 deletions

41
.github/GitHub-Actions.org vendored Normal file
View file

@ -0,0 +1,41 @@
* Deploying using Github Actions
** Actions definition: workflow/sonatype-deploy.yml
When a GitHub Release is created, usually from a tag, this action will trigger.
Using JDK8 the software will be packaged, including running any tests.
Then the Deploy script will sign the created artifacts then deploy them according to the distributionManagement configuration in the `pom.xml`.
** Deploy Script
Uses a signing key provided from the GitHub Actions Secrets as an environment variable to sign the artifact(s) before they are then deployed.
*** Inputs
**** DEPLOY_PROJECTS (optional)
An optional list of modules in a multi-module project to be deployed. If this value is not specified, then all projects will be deployed.
** Maven Configuration
Picks up the credentials from Environment variables for authenticating both with GPG and with the target deployment server (e.g. sonatype-nexus).
*** Inputs
**** NEXUS_USERNAME
The username for your account on the deployment server.
**** NEXUS_PASSWORD
The password for your account on the deployement server.
**** GPG_KEYNAME
The key to use when signing.
**** GPG_PASSPHRASE
The passphrase to unlock the key to use when signing.

53
.github/NOTES vendored Normal file
View file

@ -0,0 +1,53 @@
Add subkeys:
????
Publish:
gpg --send-keys --keyserver keyserver.ubuntu.com $KEYID
gpg --send-keys --keyserver pgp.mit.edu $KEYID
gpg --send-keys --keyserver pool.sks-keyservers.net $KEYID
Backup:
gpg --export --armor pcampbell@kemitix.net > gpg-key-backup.asc
gpg --export-secret-keys --armor pcampbell@kemitix.net >> gpg-key-backup.asc
Export sub-keys:
gpg --export-secret-subkeys pcampbell@kemitix.net > subkeys
Remove master keys:
gpg --delete-secret-key pcampbell@kemitix.net
Import sub-keys and clean up:
gpg --import subkeys
shred --remove subkeys
Delete any encryption subkeys:
gpg --edit-key pcampbell@kemitix.net
2
delkey
save
Change passphrase:
gpg --edit-key pcampbell@kemitix.net
passwd
save
Export keys:
gpg --export --armor pcampbell@kemitix.net > codesigning.asc
gpg --export-secret-keys --armor pcampbell@kemitix.net >> codesigning.asc
Encrypt keys:
gpg --symmetric --cipher-algo AES256 codesigning.asc
shred codesigning.asc

BIN
.github/codesigning.asc.gpg vendored Normal file

Binary file not shown.

28
.github/settings.xml vendored Normal file
View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" ?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
<servers>
<server>
<id>sonatype-nexus-snapshots</id>
<username>${env.NEXUS_USERNAME}</username>
<password>${env.NEXUS_PASSWORD}</password>
</server>
<server>
<id>sonatype-nexus-staging</id>
<username>${env.NEXUS_USERNAME}</username>
<password>${env.NEXUS_PASSWORD}</password>
</server>
</servers>
<profiles>
<profile>
<id>gpg-sign</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<gpg.executable>gpg</gpg.executable>
<gpg.keyname>${env.GPG_KEYNAME}</gpg.keyname>
<gpg.passphrase>${env.GPG_PASSPHRASE}</gpg.passphrase>
</properties>
</profile>
</profiles>
</settings>

25
.github/workflows/maven-build.yml vendored Normal file
View file

@ -0,0 +1,25 @@
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Java CI with Maven
on:
push:
branches: '*'
pull_request:
branches: '*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
java: [ 8, 11, 13 ]
steps:
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- name: Build with Maven
run: mvn -B install

38
.github/workflows/sonatype-deploy.yml vendored Normal file
View file

@ -0,0 +1,38 @@
name: Deploy to Sonatype Nexus
on:
release:
types: [created]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Maven
run: mvn -B install
- name: Nexus Repo Publish
run: |
gpg --quiet \
--batch \
--yes \
--decrypt \
--passphrase="${{ secrets.GPG_PASSPHRASE }}" \
--output codesigning.asc \
.github/codesigning.asc.gpg
gpg --batch \
--fast-import codesigning.asc
mvn --settings .github/settings.xml \
-Dskip-Tests=true \
-P release \
-B \
deploy
env:
NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }}
NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
GPG_KEYNAME: ${{ secrets.GPG_KEYNAME }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}

16
.gitignore vendored Normal file
View file

@ -0,0 +1,16 @@
*.jqwik-database*
*.iml
.idea/
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)
!/.mvn/wrapper/maven-wrapper.jar

37
README.md Normal file
View file

@ -0,0 +1,37 @@
# List Head/Tail
![Sonatype Nexus (Release)](https://img.shields.io/nexus/r/https/oss.sonatype.org/net.kemitix/list-head-tail.svg?style=for-the-badge)
![Maven Central](https://img.shields.io/maven-central/v/net.kemitix/list-head-tail.svg?style=for-the-badge)
Provides a `head()` and `tail()` implementation for `List<>` objects in Java.
## Usage
```java
import net.kemitix.list.HeadTail;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class Usage {
List<String> list = Arrays.asList("a", "b", "c");
Optional<String> head = HeadTail.head(list); // head()
assertThat(head).contains("a");
List<String> tail = HeadTail.tail(list); // tail()
assertThat(tail).containsExactly("b", "c");
}
```
Statically importing the `head()` and `tail()` methods will be more
readable and idiomatically FP.
```java
import static net.kemitix.list.HeadTail.*;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class Usage {
List<String> list = Arrays.asList("a", "b", "c");
Optional<String> head = head(list); // head()
assertThat(head).contains("a");
List<String> tail = tail(list); // tail()
assertThat(tail).containsExactly("b", "c");
}
```

59
pom.xml Normal file
View file

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.kemitix</groupId>
<artifactId>kemitix-parent</artifactId>
<version>5.3.0</version>
<relativePath/>
</parent>
<artifactId>list-head-tail</artifactId>
<version>DEV-SNAPSHOT</version>
<inceptionYear>2020</inceptionYear>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<tiles-maven-plugin.version>2.16</tiles-maven-plugin.version>
<kemitix-maven-tiles.version>2.5.0</kemitix-maven-tiles.version>
<kemitix-checkstyle-ruleset.version>5.4.0</kemitix-checkstyle-ruleset.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.15.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>${tiles-maven-plugin.version}</version>
<extensions>true</extensions>
<configuration>
<tiles>
<tile>net.kemitix.tiles:all:${kemitix-maven-tiles.version}</tile>
<tile>net.kemitix.checkstyle:tile:${kemitix-checkstyle-ruleset.version}</tile>
</tiles>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,62 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2020 Paul Campbell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package net.kemitix.list;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
/**
* Provides a simple implementation of head() and tail() for {@link List}s.
*/
public interface HeadTail {
/**
* Returns the first item in the list as an {@link Optional}.
*
* @param list the list
* @param <X> the type of the lists contents
* @return an Optional containing the first item in the list, or empty if
* the list is empty.
*/
static <X> Optional<X> head(final List<X> list) {
if (list.isEmpty()) {
return Optional.empty();
}
return Optional.ofNullable(list.get(0));
}
/**
* Returns the list, minus the first item.
*
* @param list the list
* @param <X> the type of the lists contents
* @return a view of the list starting with the second item, or an empty
* list if the original list has less than two items.
*/
static <X> List<X> tail(final List<X> list) {
if (list.size() < 1) {
return Collections.emptyList();
}
return list.subList(1, list.size());
}
}

View file

@ -0,0 +1,51 @@
package net.kemitix.list;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
public class HeadTailTest {
private String headValue = "1-" + UUID.randomUUID().toString();
private String secondValue = "2-" + UUID.randomUUID().toString();
private String thirdValue = "3-" + UUID.randomUUID().toString();
private List<String> emptyList = Collections.emptyList();
private List<String> singletonList = Collections.singletonList(headValue);
private List<String> aList = Arrays.asList(
headValue, secondValue, thirdValue
);
private List<String> tailValue = Arrays.asList(
secondValue, thirdValue
);
@Test
public void headOfAnEmptyListIsEmpty() {
assertThat(HeadTail.head(emptyList)).isEmpty();
}
@Test
public void headOfASingletonListIsTheItem() {
assertThat(HeadTail.head(singletonList)).contains(headValue);
}
@Test
public void headOfAListIsTheFirstItem() {
assertThat(HeadTail.head(aList)).contains(headValue);
}
@Test
public void tailOfAnEmptyListIsEmpty() {
assertThat(HeadTail.tail(emptyList)).isEmpty();
}
@Test
public void tailOfASingletonListIsEmpty() {
assertThat(HeadTail.tail(singletonList)).isEmpty();
}
@Test
public void tailOfAListIsMinusTheHead() {
assertThat(HeadTail.tail(aList)).isEqualTo(tailValue);
}
}