switch to spring boot, change some structure

master
Josha von Gizycki 4 weeks ago
parent 3873c8ae6d
commit beff30babf

@ -1,4 +0,0 @@
*
!target/*-runner
!target/*-runner.jar
!target/lib/*

2
.gitattributes vendored

@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

56
.gitignore vendored

@ -1,35 +1,33 @@
# Eclipse HELP.md
.project target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath .classpath
.settings/ .factorypath
bin/ .project
.settings
.springBeans
.sts4-cache
# IntelliJ ### IntelliJ IDEA ###
.idea .idea
*.ipr
*.iml
*.iws *.iws
*.iml
*.ipr
# NetBeans ### NetBeans ###
nb-configuration.xml /nbproject/private/
/nbbuild/
# Visual Studio Code /dist/
.vscode /nbdist/
/.nb-gradle/
# OSX build/
.DS_Store !**/src/main/**/build/
!**/src/test/**/build/
# Vim
*.swp
*.swo
# patch
*.orig
*.rej
# Maven ### VS Code ###
target/ .vscode/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
release.properties

@ -1,117 +0,0 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.5";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

@ -1,2 +1,20 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip # Licensed to the Apache Software Foundation (ASF) under one
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar # or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
distributionSha256Sum=4ec3f26fb1a692473aea0235c300bd20f0f9fe741947c82c1234cefd76ac3a3c

@ -1,30 +1,56 @@
# alfred project # In buildable Repository:
This project uses Quarkus, the Supersonic Subatomic Java Framework. ## If configured as script build
If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ . Configure script that shall be executed by alfred relative to project root.
## Running the application in dev mode ## If no script is configured
You can run your application in dev mode that enables live coding using: ```text
``` .alfred
./mvnw quarkus:dev |- pre.sh
|- job.sh
|- post.sh
``` ```
## Packaging and running the application - Scripts are run in the mentioned order
- No further semantics are connected to them
- If single files are missing they are skipped
## Environment variables
The application is packageable using `./mvnw package`. - `ALFRED_LOG_FILE`: Path to the log file of the current build
It produces the executable `alfred-1-runner.jar` file in `/target` directory. - `ALFRED_REV`: Revision string passed to the trigger URL
Be aware that its not an _über-jar_ as the dependencies are copied into the `target/lib` directory. - All environment variables configured in the build config on the alfred server
The application is now runnable using `java -jar target/alfred-1-runner.jar`. # On Alfred server
```text
$ALFRED_HOME
|- builds
|- $buildId.properties
|- $buildId2.properties
```
## Creating a native executable ## $buildId.properties
You can create a native executable using: `./mvnw package -Pnative`. Example: `static-site.properties`
Or you can use Docker to build the native executable using: `./mvnw package -Pnative -Dquarkus.native.container-build=true`. ```properties
user=nonroot
apikey=4711
You can then execute your binary: `./target/alfred-1-runner` # single script execution
script=/home/nonroot/static-site/build.sh
# git based execution
git.repo.url=https://some-git-server.tld/some-git-repo/url
git.clone.timeout=30
git.workspace=/tmp/workspaces/static-site
# environment variables
SOME_ENV=SOME_ENV_VALUE
FOO=BAR
```
If you want to learn more about building native executables, please consult https://quarkus.io/guides/building-native-image-guide . In this case the executable configured by `script` will be called. Otherwise, alfred would try to clone the repository configured by `gitrepo` under the path configured by `workspace` and the scripts `.alfred/pre.sh`, `.alfred/job.sh` and `.alfred/post.sh` will be called,

447
mvnw vendored

@ -19,292 +19,241 @@
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Maven2 Start Up Batch script # Apache Maven Wrapper startup batch script, version 3.3.2
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
# #
# Optional ENV vars # Optional ENV vars
# ----------------- # -----------------
# M2_HOME - location of maven2's installed home dir # JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MAVEN_OPTS - parameters passed to the Java VM when running Maven # MVNW_REPOURL - repo url base for downloading maven distribution
# e.g. to debug Maven itself, use # MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 # MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false. # OS specific support.
cygwin=false; native_path() { printf %s\\n "$1"; }
darwin=false; case "$(uname)" in
mingw=false CYGWIN* | MINGW*)
case "`uname`" in [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
CYGWIN*) cygwin=true ;; native_path() { cygpath --path --windows "$1"; }
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;; ;;
esac esac
if [ -z "$JAVA_HOME" ] ; then # set JAVACMD and JAVACCMD
if [ -r /etc/gentoo-release ] ; then set_java_home() {
JAVA_HOME=`java-config --jre-home` # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
fi if [ -n "${JAVA_HOME-}" ]; then
fi if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
if [ -z "$M2_HOME" ] ; then JAVACMD="$JAVA_HOME/jre/sh/java"
## resolve links - $0 may be a link to maven's home JAVACCMD="$JAVA_HOME/jre/sh/javac"
PRG="$0" else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
# need this for relative symlinks if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
while [ -h "$PRG" ] ; do echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
ls=`ls -ld "$PRG"` echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
link=`expr "$ls" : '.*-> \(.*\)$'` return 1
if expr "$link" : '/.*' > /dev/null; then fi
PRG="$link" fi
else else
PRG="`dirname "$PRG"`/$link" JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi fi
done fi
}
saveddir=`pwd` # hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
M2_HOME=`dirname "$PRG"`/.. verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
# make it fully qualified die() {
M2_HOME=`cd "$M2_HOME" && pwd` printf %s\\n "$1" >&2
exit 1
}
cd "$saveddir" trim() {
# echo Using m2 at $M2_HOME # MWRAPPER-139:
fi # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
# For Cygwin, ensure paths are in UNIX format before anything is touched # parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
if $cygwin ; then while IFS="=" read -r key value; do
[ -n "$M2_HOME" ] && case "${key-}" in
M2_HOME=`cygpath --unix "$M2_HOME"` distributionUrl) distributionUrl=$(trim "${value-}") ;;
[ -n "$JAVA_HOME" ] && distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
JAVA_HOME=`cygpath --unix "$JAVA_HOME"` esac
[ -n "$CLASSPATH" ] && done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
CLASSPATH=`cygpath --path --unix "$CLASSPATH"` [ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
fi
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# For Mingw, ensure paths are in UNIX format before anything is touched # apply MVNW_REPOURL and calculate MAVEN_HOME
if $mingw ; then # maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -n "$M2_HOME" ] && [ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
M2_HOME="`(cd "$M2_HOME"; pwd)`" distributionUrlName="${distributionUrl##*/}"
[ -n "$JAVA_HOME" ] && distributionUrlNameMain="${distributionUrlName%.*}"
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" distributionUrlNameMain="${distributionUrlNameMain%-bin}"
fi MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -z "$JAVA_HOME" ]; then if [ -d "$MAVEN_HOME" ]; then
javaExecutable="`which javac`" verbose "found existing MAVEN_HOME at $MAVEN_HOME"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then exec_maven "$@"
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi fi
if [ -z "$JAVACMD" ] ; then case "${distributionUrl-}" in
if [ -n "$JAVA_HOME" ] ; then *?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then *) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
# IBM's JDK on AIX uses strange locations for the executables esac
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then # prepare tmp dir
echo "Error: JAVA_HOME is not defined correctly." >&2 if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
echo " We cannot execute $JAVACMD" >&2 clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
exit 1 trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi fi
if [ -z "$JAVA_HOME" ] ; then mkdir -p -- "${MAVEN_HOME%/*}"
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher # Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# traverses directory structure from process work directory to filesystem root # select .zip or .tar.gz
# first directory with .mvn subdirectory is considered project base directory if ! command -v unzip >/dev/null; then
find_maven_basedir() { distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
if [ -z "$1" ] # verbose opt
then __MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
echo "Path not specified to find_maven_basedir" [ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
return 1
fi
basedir="$1" # normalize http auth
wdir="$1" case "${MVNW_PASSWORD:+has-password}" in
while [ "$wdir" != '/' ] ; do '') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
if [ -d "$wdir"/.mvn ] ; then has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
basedir=$wdir esac
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"` if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
if [ -z "$BASE_DIR" ]; then verbose "Found wget ... using wget"
exit 1; wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi fi
########################################################################################## # If specified, validate the SHA-256 sum of the Maven distribution zip file
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central if [ -n "${distributionSha256Sum-}" ]; then
# This allows using the maven wrapper in projects that prohibit checking in binary data. distributionSha256Result=false
########################################################################################## if [ "$MVN_CMD" = mvnd.sh ]; then
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then echo "Checksum validation is not supported for maven-mvnd." >&2
if [ "$MVNW_VERBOSE" = true ]; then echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
echo "Found .mvn/wrapper/maven-wrapper.jar" exit 1
fi elif command -v sha256sum >/dev/null; then
else if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
if [ "$MVNW_VERBOSE" = true ]; then distributionSha256Result=true
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then elif command -v shasum >/dev/null; then
curl -o "$wrapperJarPath" "$jarUrl" -f if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
else distributionSha256Result=true
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi fi
else else
if [ "$MVNW_VERBOSE" = true ]; then echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Falling back to using Java to download" echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
fi exit 1
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi fi
fi fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} # unzip and move
if [ "$MVNW_VERBOSE" = true ]; then if command -v unzip >/dev/null; then
echo $MAVEN_PROJECTBASEDIR unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
fi else
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi fi
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
# Provide a "standardized" way to retrieve the CLI args that will clean || :
# work with both Windows and non-Windows executions. exec_maven "$@"
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

182
mvnw.cmd vendored

@ -1,182 +0,0 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

@ -1,120 +1,94 @@
<?xml version="1.0"?> <?xml version="1.0" encoding="UTF-8"?>
<project <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" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>de.joshavg</groupId> <parent>
<artifactId>alfred</artifactId> <groupId>org.springframework.boot</groupId>
<version>1</version> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>alfred</groupId>
<artifactId>web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>web</name>
<description>Alfred CI</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties> <properties>
<compiler-plugin.version>3.8.1</compiler-plugin.version> <java.version>17</java.version>
<kotlin.version>1.4.30</kotlin.version> <kotlin.version>1.9.25</kotlin.version>
<maven.compiler.parameters>true</maven.compiler.parameters>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus-plugin.version>1.13.2.Final</quarkus-plugin.version>
<quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
<quarkus.platform.version>1.13.2.Final</quarkus.platform.version>
<surefire-plugin.version>2.22.1</surefire-plugin.version>
</properties> </properties>
<dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>${quarkus.platform.group-id}</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency> </dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>quarkus-resteasy</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>com.fasterxml.jackson.module</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId> <artifactId>jackson-module-kotlin</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId> <artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.rest-assured</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>rest-assured</artifactId> <artifactId>kotlin-stdlib</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>quarkus-kotlin</artifactId> <artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>quarkus-undertow</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>quarkus-scheduler</artifactId> <artifactId>kotlin-test-junit5</artifactId>
<scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<sourceDirectory>src/main/kotlin</sourceDirectory> <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory> <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins> <plugins>
<plugin> <plugin>
<groupId>io.quarkus</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>quarkus-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<version>${quarkus-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemProperties>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</systemProperties>
</configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId> <artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version> <configuration>
<executions> <args>
<execution> <arg>-Xjsr305=strict</arg>
<id>compile</id> </args>
<goals> <compilerPlugins>
<goal>compile</goal> <plugin>spring</plugin>
</goals> </compilerPlugins>
</execution> </configuration>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
@ -122,52 +96,8 @@
<version>${kotlin.version}</version> <version>${kotlin.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<configuration>
<compilerPlugins>
<plugin>all-open</plugin>
</compilerPlugins>
<pluginOptions>
<option>all-open:annotation=javax.ws.rs.Path</option>
<option>all-open:annotation=javax.enterprise.context.ApplicationScoped</option>
</pluginOptions>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemProperties>
<native.image.path>
${project.build.directory}/${project.build.finalName}-runner
</native.image.path>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
</profiles>
</project> </project>

@ -1,86 +0,0 @@
package alfred.http
import alfred.*
import alfred.running.GitRunner
import alfred.running.Handles
import alfred.running.ScriptRunner
import javax.enterprise.inject.Default
import javax.inject.Inject
import javax.ws.rs.*
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response
import javax.ws.rs.core.Response.Status.PRECONDITION_REQUIRED
@Path("build")
class Endpoints {
@field:Inject
lateinit var builds: Builds
@field:Inject
lateinit var security: Security
@field:Inject
lateinit var scriptRunner: ScriptRunner
@field:Inject
lateinit var gitRunner: GitRunner
@field:Inject
lateinit var handles: Handles
@GET
@Path("{build}/info")
@Produces(MediaType.APPLICATION_JSON)
fun info(
@PathParam("build")
build: BuildId,
@QueryParam("key")
key: String?
) = security.requireKey(build, key) {
it
}
@POST
@Path("{build}/trigger")
@Produces(MediaType.APPLICATION_JSON)
fun trigger(
@PathParam("build")
build: BuildId,
@QueryParam("key")
key: String?,
@QueryParam("rev")
rev: String?
) = security.requireKey(build, key) {
if (rev == null) {
return@requireKey Response.status(PRECONDITION_REQUIRED).build()
}
val info = if (builds.buildConfig(build).script != null) {
scriptRunner.run(build, rev)
} else {
gitRunner.run(build, rev)
}
Response.ok(
mapOf(
"log" to info.logFile.absolutePath,
"pid" to info.pid
)
).build()
}
@GET
@Path("{build}/handles")
@Produces(MediaType.APPLICATION_JSON)
fun handles(
@PathParam("build")
build: BuildId,
@QueryParam("key")
key: String?
) = security.requireKey(build, key) {
handles.active(build)
}
}

@ -1,30 +0,0 @@
package alfred.http
import alfred.BuildConfig
import alfred.BuildId
import alfred.Builds
import javax.enterprise.context.ApplicationScoped
import javax.inject.Inject
import javax.ws.rs.core.Response
@ApplicationScoped
class Security {
@field:Inject
lateinit var builds: Builds
fun requireKey(build: BuildId, apikey: String?, block: (BuildConfig) -> Any): Response {
val buildConfig = builds.buildConfig(build)
if (buildConfig.apikey != "" && buildConfig.apikey != apikey) {
return Response.status(Response.Status.UNAUTHORIZED).build()
}
val entity = block(buildConfig)
if (entity is Response) {
return entity
}
return Response.ok(entity).build()
}
}

@ -0,0 +1,11 @@
package alfred.web
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class WebApplication
fun main(args: Array<String>) {
runApplication<WebApplication>(*args)
}

@ -1,23 +1,22 @@
package alfred package alfred.web.core
import alfred.running.LogFile
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import io.quarkus.runtime.annotations.RegisterForReflection
import org.eclipse.microprofile.config.inject.ConfigProperty
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File import org.springframework.beans.factory.annotation.Value
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.web.bind.annotation.ResponseStatus
import java.lang.RuntimeException import java.lang.RuntimeException
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.* import java.util.*
import javax.enterprise.context.ApplicationScoped
@ApplicationScoped @Service
class Builds( class Builds(
@ConfigProperty(name = "ALFRED_HOME") @Value("\${ALFRED_HOME}")
private val home: String private val home: String
) { ) {
@ -39,15 +38,17 @@ class Builds(
val env = props val env = props
.entries .entries
.filter { it.key.toString() == it.key.toString().toUpperCase() } .filter { it.key.toString() == it.key.toString().uppercase() }
.associate { Pair(it.key.toString(), it.value.toString()) } .associate { Pair(it.key.toString(), it.value.toString()) }
// diverge into ScriptedBasedConfig and GitBasedConfig
return BuildConfig( return BuildConfig(
user = props.getProperty("user"), user = props.getProperty("user"),
workspace = props.getProperty("workspace"), gitWorkspace = props.getProperty("workspace") ?: "",
apikey = props.getProperty("apikey") ?: "", apikey = props.getProperty("apikey") ?: "",
script = props.getProperty("script"), script = props.getProperty("script"),
gitRepo = props.getProperty("gitrepo"), gitRepo = props.getProperty("git.repo.url"),
gitCloneTimeout = props.getProperty("git.close.timeout")?.toLong() ?: 30L,
env = env env = env
) )
} }
@ -64,19 +65,20 @@ class Builds(
} }
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Unknown Build Id")
class UnknownBuild(val build: BuildId) : RuntimeException() { class UnknownBuild(val build: BuildId) : RuntimeException() {
override fun toString() = override fun toString() =
"unknown build: $build" "unknown build: $build"
} }
@RegisterForReflection
data class BuildConfig( data class BuildConfig(
val user: String, val user: String,
val workspace: String,
@field:JsonIgnore @field:JsonIgnore
val apikey: String, val apikey: String,
val script: String?, val script: String?,
val gitRepo: String?, val gitRepo: String?,
val gitCloneTimeout: Long,
val gitWorkspace: String,
@field:JsonIgnore @field:JsonIgnore
val env: Map<String, String> val env: Map<String, String>
) )

@ -1,25 +1,17 @@
package alfred.running package alfred.web.core
import alfred.BuildConfig
import alfred.BuildId
import alfred.Builds
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.enterprise.context.ApplicationScoped
import javax.inject.Inject
@ApplicationScoped @Service
class GitRunner { class GitRunner(
val builds: Builds,
@field:Inject val handles: Handles,
lateinit var builds: Builds val workspaces: Workspaces
) {
@field:Inject
lateinit var handles: Handles
val scriptsDir = ".alfred" val scriptsDir = ".alfred"
@ -33,42 +25,34 @@ class GitRunner {
val ctx = BuildContext( val ctx = BuildContext(
buildId = buildId, buildId = buildId,
config = config, config = config,
wsId = UUID.randomUUID().toString(),
logFile = logFile, logFile = logFile,
rev = rev rev = rev
) )
logFile.header(buildId, rev, ctx.workspace)
assertEmptyWorkspace(ctx)
Thread { Thread {
try { workspaces.withWorkspace(ctx) { wsPath ->
clone(ctx) clone(ctx, wsPath)
execScripts(ctx) execScripts(ctx, wsPath)
} finally {
deleteWorkspace(ctx)
logFile.footer()
} }
}.start() }.start()
return ProcessInfo(-1, logFile) return ProcessInfo(-1, logFile)
} }
private fun clone(ctx: BuildContext) { private fun clone(ctx: BuildContext, wsPath: Path) {
logger.info("build ${ctx.buildId}: cloning ${ctx.config.gitRepo} into ${ctx.workspace}") logger.info("build ${ctx.buildId}: cloning ${ctx.config.gitRepo} into $wsPath")
val process = processBuilder(ctx.config, ctx.logFile, "") val process = processBuilder(ctx.config, ctx.logFile, "")
.command("git", "clone", ctx.config.gitRepo, ".") .command("git", "clone", ctx.config.gitRepo, ".")
.directory(ctx.workspace.toFile()) .directory(wsPath.toFile())
.start() .start()
handles.add(Handle(process.toHandle(), ctx.buildId)) handles.add(Handle(process.toHandle(), ctx.buildId))
val cloneSuccess = process.waitFor(30, TimeUnit.SECONDS) val cloneSuccess = process.waitFor(ctx.config.gitCloneTimeout, TimeUnit.SECONDS)
logger.info("build ${ctx.buildId}: checkout rev ${ctx.rev}") logger.info("build ${ctx.buildId}: checkout rev ${ctx.rev}")
processBuilder(ctx.config, ctx.logFile, "") processBuilder(ctx.config, ctx.logFile, "")
.command("git", "checkout", ctx.rev) .command("git", "checkout", ctx.rev)
.directory(ctx.workspace.toFile()) .directory(wsPath.toFile())
.start() .start()
.waitFor() .waitFor()
@ -77,13 +61,13 @@ class GitRunner {
} }
} }
private fun execScripts(ctx: BuildContext) { private fun execScripts(ctx: BuildContext, wsPath: Path) {
val scriptFiles = listOf("pre.sh", "job.sh", "post.sh") val scriptFiles = listOf("pre.sh", "job.sh", "post.sh")
logger.info("build ${ctx.buildId}: looking for scripts $scriptFiles in $scriptsDir/") logger.info("build ${ctx.buildId}: looking for scripts $scriptFiles in $scriptsDir/")
scriptFiles.forEach { script -> scriptFiles.forEach { script ->
val scriptFile = shFile(ctx, script) val scriptFile = shFile(wsPath, script)
if (scriptFile.exists()) { if (scriptFile.exists()) {
logger.info("build ${ctx.buildId}: found script $script, running it") logger.info("build ${ctx.buildId}: found script $script, running it")
@ -91,7 +75,7 @@ class GitRunner {
val scriptProcess = processBuilder(ctx.config, ctx.logFile, ctx.rev) val scriptProcess = processBuilder(ctx.config, ctx.logFile, ctx.rev)
.command(scriptFile.absolutePath) .command(scriptFile.absolutePath)
.directory(ctx.workspace.toFile()) .directory(wsPath.toFile())
.start() .start()
handles.add(Handle(scriptProcess.toHandle(), ctx.buildId)) handles.add(Handle(scriptProcess.toHandle(), ctx.buildId))
@ -105,25 +89,8 @@ class GitRunner {
} }
} }
private fun shFile(ctx: BuildContext, name: String) = private fun shFile(wsPath: Path, name: String) =
ctx.workspace.resolve(scriptsDir).resolve(name).toFile() wsPath.resolve(scriptsDir).resolve(name).toFile()
private fun deleteWorkspace(ctx: BuildContext) {
ctx.workspace.toFile().deleteRecursively()
}
private fun assertEmptyWorkspace(config: BuildContext) {
val workspace = config.workspace.toFile()
if (!workspace.exists()) {
workspace.mkdirs()
}
val wsList = workspace.list()
if (wsList != null && wsList.isNotEmpty()) {
throw WorkspaceIsNotEmpty(config.workspace.toString())
}
}
val logger: Logger = LoggerFactory.getLogger(this::class.java) val logger: Logger = LoggerFactory.getLogger(this::class.java)
@ -131,13 +98,10 @@ class GitRunner {
data class BuildContext( data class BuildContext(
val config: BuildConfig, val config: BuildConfig,
val wsId: String,
val logFile: LogFile, val logFile: LogFile,
val rev: String, val rev: String,
val buildId: BuildId val buildId: BuildId
) { )
val workspace: Path = Paths.get(config.workspace, wsId)
}
class WorkspaceIsNotEmpty( class WorkspaceIsNotEmpty(
private val ws: String private val ws: String

@ -1,12 +1,10 @@
package alfred.running package alfred.web.core
import alfred.BuildId import org.springframework.scheduling.annotation.Scheduled
import io.quarkus.runtime.annotations.RegisterForReflection import org.springframework.stereotype.Service
import io.quarkus.scheduler.Scheduled
import java.time.Instant import java.time.Instant
import javax.enterprise.context.ApplicationScoped
@ApplicationScoped @Service
class Handles { class Handles {
private val handles = mutableListOf<Handle>() private val handles = mutableListOf<Handle>()
@ -26,7 +24,7 @@ class Handles {
) )
} }
@Scheduled(every = "60s") @Scheduled(fixedDelay = 60_000)
fun cleanup() { fun cleanup() {
handles.removeIf { !it.handle.isAlive } handles.removeIf { !it.handle.isAlive }
} }
@ -42,7 +40,6 @@ data class Handle(
val user: String? = handle.info().user().orElse(null) val user: String? = handle.info().user().orElse(null)
} }
@RegisterForReflection
data class HandleInfo( data class HandleInfo(
val command: String, val command: String,
val startedAt: Instant?, val startedAt: Instant?,

@ -1,23 +1,16 @@
package alfred.running package alfred.web.core
import alfred.BuildId
import alfred.Builds
import alfred.http.Security
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import java.io.File import java.io.File
import java.nio.file.Paths import java.nio.file.Paths
import javax.enterprise.context.ApplicationScoped
import javax.inject.Inject
@ApplicationScoped @Service
class ScriptRunner { class ScriptRunner(
val builds: Builds,
@field:Inject val handles: Handles
lateinit var builds: Builds ) {
@field:Inject
lateinit var handles: Handles
fun run(buildId: BuildId, rev: String): ProcessInfo { fun run(buildId: BuildId, rev: String): ProcessInfo {
val config = builds.buildConfig(buildId) val config = builds.buildConfig(buildId)
@ -26,11 +19,10 @@ class ScriptRunner {
logger.info("preparing process for build $buildId with config $config") logger.info("preparing process for build $buildId with config $config")
logger.info("log file: $logFile") logger.info("log file: $logFile")
logFile.header(buildId, rev, Paths.get(config.workspace)) logFile.header(buildId, rev, Paths.get(config.gitWorkspace))
val process = processBuilder(config, logFile, rev) val process = processBuilder(config, logFile, rev)
.command(config.script) .command(config.script)
.directory(File(config.workspace))
.start() .start()
handles.add(Handle(process.toHandle(), buildId)) handles.add(Handle(process.toHandle(), buildId))
process.onExit().whenComplete { _, _ -> logFile.footer() } process.onExit().whenComplete { _, _ -> logFile.footer() }

@ -0,0 +1,37 @@
package alfred.web.core
import org.springframework.stereotype.Service
import java.nio.file.Path
import java.nio.file.Paths
import java.util.UUID
import kotlin.collections.isNotEmpty
@Service
class Workspaces {
fun withWorkspace(ctx: BuildContext, block: (Path) -> Unit) {
val workspacePath = Paths.get(
ctx.config.gitWorkspace, UUID.randomUUID().toString()
)
val workspaceDir = workspacePath.toFile()
ctx.logFile.header(ctx.buildId, ctx.rev, workspacePath)
if (!workspaceDir.exists()) {
workspaceDir.mkdirs()
}
val wsList = workspaceDir.list()
if (wsList != null && wsList.isNotEmpty()) {
throw WorkspaceIsNotEmpty(workspaceDir.toString())
}
try {
block(workspaceDir.toPath())
} finally {
ctx.logFile.footer()
workspaceDir.deleteRecursively()
}
}
}

@ -1,7 +1,5 @@
package alfred.running package alfred.web.core
import alfred.BuildConfig
import alfred.BuildId
import java.io.File import java.io.File
import java.nio.file.Path import java.nio.file.Path
import java.time.ZonedDateTime import java.time.ZonedDateTime

@ -0,0 +1,80 @@
package alfred.web.http
import alfred.web.core.BuildId
import alfred.web.core.Builds
import alfred.web.core.GitRunner
import alfred.web.core.Handles
import alfred.web.core.ScriptRunner
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("build")
class Endpoints(
val builds: Builds,
val security: Security,
val scriptRunner: ScriptRunner,
val gitRunner: GitRunner,
val handles: Handles
) {
@GetMapping(
"{build}/info",
produces = [MediaType.APPLICATION_JSON_VALUE]
)
fun info(
@PathVariable("build")
build: BuildId,
@RequestParam("key")
key: String?
) = security.requireKey(build, key) {
it
}
@PostMapping(
"{build}/trigger",
produces = [MediaType.APPLICATION_JSON_VALUE]
)
fun trigger(
@PathVariable("build")
build: BuildId,
@RequestParam("key")
key: String?,
@RequestParam("rev")
rev: String
) = security.requireKey(build, key) {
val info = if (builds.buildConfig(build).script != null) {
scriptRunner.run(build, rev)
} else {
gitRunner.run(build, rev)
}
ResponseEntity.ok(
mapOf(
"log" to info.logFile.absolutePath,
"pid" to info.pid
)
)
}
@GetMapping(
"{build}/handles",
produces = [MediaType.APPLICATION_JSON_VALUE]
)
fun handles(
@PathVariable("build")
build: BuildId,
@RequestParam("key")
key: String?
) = security.requireKey(build, key) {
handles.active(build)
}
}

@ -0,0 +1,29 @@
package alfred.web.http
import alfred.web.core.BuildConfig
import alfred.web.core.BuildId
import alfred.web.core.Builds
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Service
@Service
class Security(
val builds: Builds
) {
fun <T> requireKey(build: BuildId, apikey: String?, block: (BuildConfig) -> T): ResponseEntity<*> {
val buildConfig = builds.buildConfig(build)
if (buildConfig.apikey != "" && buildConfig.apikey != apikey) {
return ResponseEntity<T>(HttpStatus.UNAUTHORIZED)
}
val entity = block(buildConfig)
if (entity is ResponseEntity<*>) {
return entity
}
return ResponseEntity.ok(entity)
}
}

@ -3,4 +3,6 @@
ALFRED_HOME=/tmp/alfred ALFRED_HOME=/tmp/alfred
ALFRED_PORT=8080 ALFRED_PORT=8080
quarkus.http.port=${ALFRED_PORT}
server.port=${ALFRED_PORT}
spring.application.name=Alfred - RCE AAS

@ -0,0 +1,13 @@
package alfred.web
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest
class WebApplicationTests {
@Test
fun contextLoads() {
}
}
Loading…
Cancel
Save