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,

451
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 # OS specific support.
. "$HOME/.mavenrc" native_path() { printf %s\\n "$1"; }
fi case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
fi # set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
# OS specific support. $var _must_ be set to either true or false. if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
cygwin=false; echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
darwin=false; echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
mingw=false return 1
case "`uname`" in
CYGWIN*) cygwin=true ;;
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
fi fi
;; else
esac JAVACMD="$(
'set' +e
if [ -z "$JAVA_HOME" ] ; then 'unset' -f command 2>/dev/null
if [ -r /etc/gentoo-release ] ; then 'command' -v java
JAVA_HOME=`java-config --jre-home` )" || :
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 fi
fi }
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks # hash string like Java String::hashCode
while [ -h "$PRG" ] ; do hash_string() {
ls=`ls -ld "$PRG"` str="${1:-}" h=0
link=`expr "$ls" : '.*-> \(.*\)$'` while [ -n "$str" ]; do
if expr "$link" : '/.*' > /dev/null; then char="${str%"${str#?}"}"
PRG="$link" h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
else str="${str#?}"
PRG="`dirname "$PRG"`/$link"
fi
done done
printf %x\\n $h
}
saveddir=`pwd` verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
M2_HOME=`dirname "$PRG"`/.. die() {
printf %s\\n "$1" >&2
exit 1
}
# make it fully qualified trim() {
M2_HOME=`cd "$M2_HOME" && pwd` # MWRAPPER-139:
# 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:]'
}
cd "$saveddir" # parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
# echo Using m2 at $M2_HOME while IFS="=" read -r key value; do
fi case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
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 Cygwin, ensure paths are in UNIX format before anything is touched # apply MVNW_REPOURL and calculate MAVEN_HOME
if $cygwin ; 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=`cygpath --unix "$M2_HOME"` distributionUrlName="${distributionUrl##*/}"
[ -n "$JAVA_HOME" ] && distributionUrlNameMain="${distributionUrlName%.*}"
JAVA_HOME=`cygpath --unix "$JAVA_HOME"` distributionUrlNameMain="${distributionUrlNameMain%-bin}"
[ -n "$CLASSPATH" ] && MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
CLASSPATH=`cygpath --path --unix "$CLASSPATH"` MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
fi
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"
}
# For Mingw, ensure paths are in UNIX format before anything is touched if [ -d "$MAVEN_HOME" ]; then
if $mingw ; then verbose "found existing MAVEN_HOME at $MAVEN_HOME"
[ -n "$M2_HOME" ] && exec_maven "$@"
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi fi
if [ -z "$JAVA_HOME" ]; then case "${distributionUrl-}" in
javaExecutable="`which javac`" *?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then *) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
# readlink(1) is not available as standard on Solaris 10. esac
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
if [ -z "$JAVACMD" ] ; then # prepare tmp dir
if [ -n "$JAVA_HOME" ] ; then if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
# IBM's JDK on AIX uses strange locations for the executables trap clean HUP INT TERM EXIT
JAVACMD="$JAVA_HOME/jre/sh/java" else
else die "cannot create temp dir"
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi fi
if [ ! -x "$JAVACMD" ] ; then mkdir -p -- "${MAVEN_HOME%/*}"
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2 # Download and Install Apache Maven
exit 1 verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
fi verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
if [ -z "$JAVA_HOME" ] ; then # select .zip or .tar.gz
echo "Warning: JAVA_HOME environment variable is not set." if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher # verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# traverses directory structure from process work directory to filesystem root # normalize http auth
# first directory with .mvn subdirectory is considered project base directory case "${MVNW_PASSWORD:+has-password}" in
find_maven_basedir() { '') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "$1" ] if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
then verbose "Found wget ... using wget"
echo "Path not specified to find_maven_basedir" wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
return 1 elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
fi 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
basedir="$1" # If specified, validate the SHA-256 sum of the Maven distribution zip file
wdir="$1" if [ -n "${distributionSha256Sum-}" ]; then
while [ "$wdir" != '/' ] ; do distributionSha256Result=false
if [ -d "$wdir"/.mvn ] ; then if [ "$MVN_CMD" = mvnd.sh ]; then
basedir=$wdir echo "Checksum validation is not supported for maven-mvnd." >&2
break echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
distributionSha256Result=true
fi fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc) elif command -v shasum >/dev/null; then
if [ -d "${wdir}" ]; then if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
wdir=`cd "$wdir/.."; pwd` distributionSha256Result=true
fi fi
# end of workaround else
done echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "${basedir}" echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
} exit 1
fi
# concatenates all lines of a file if [ $distributionSha256Result = false ]; then
concat_lines() { echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
if [ -f "$1" ]; then echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
echo "$(tr -s '\n' ' ' < "$1")" exit 1
fi fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi fi
########################################################################################## # unzip and move
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central if command -v unzip >/dev/null; then
# This allows using the maven wrapper in projects that prohibit checking in binary data. unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else else
if [ "$MVNW_VERBOSE" = true ]; then tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
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
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
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
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 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"
# 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
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \ clean || :
$MAVEN_OPTS \ exec_maven "$@"
-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,173 +1,103 @@
<?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" <modelVersion>4.0.0</modelVersion>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <parent>
<modelVersion>4.0.0</modelVersion> <groupId>org.springframework.boot</groupId>
<groupId>de.joshavg</groupId> <artifactId>spring-boot-starter-parent</artifactId>
<artifactId>alfred</artifactId> <version>3.3.4</version>
<version>1</version> <relativePath/> <!-- lookup parent from repository -->
<properties> </parent>
<compiler-plugin.version>3.8.1</compiler-plugin.version> <groupId>alfred</groupId>
<kotlin.version>1.4.30</kotlin.version> <artifactId>web</artifactId>
<maven.compiler.parameters>true</maven.compiler.parameters> <version>0.0.1-SNAPSHOT</version>
<maven.compiler.source>1.8</maven.compiler.source> <name>web</name>
<maven.compiler.target>1.8</maven.compiler.target> <description>Alfred CI</description>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <url/>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <licenses>
<quarkus-plugin.version>1.13.2.Final</quarkus-plugin.version> <license/>
<quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id> </licenses>
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id> <developers>
<quarkus.platform.version>1.13.2.Final</quarkus.platform.version> <developer/>
<surefire-plugin.version>2.22.1</surefire-plugin.version> </developers>
</properties> <scm>
<dependencyManagement> <connection/>
<dependencies> <developerConnection/>
<dependency> <tag/>
<groupId>${quarkus.platform.group-id}</groupId> <url/>
<artifactId>${quarkus.platform.artifact-id}</artifactId> </scm>
<version>${quarkus.platform.version}</version> <properties>
<type>pom</type> <java.version>17</java.version>
<scope>import</scope> <kotlin.version>1.9.25</kotlin.version>
</dependency> </properties>
</dependencies> <dependencies>
</dependencyManagement> <dependency>
<dependencies> <groupId>org.springframework.boot</groupId>
<dependency> <artifactId>spring-boot-starter-actuator</artifactId>
<groupId>io.quarkus</groupId> </dependency>
<artifactId>quarkus-resteasy</artifactId> <dependency>
</dependency> <groupId>org.springframework.boot</groupId>
<dependency> <artifactId>spring-boot-starter-web</artifactId>
<groupId>io.quarkus</groupId> </dependency>
<artifactId>quarkus-resteasy-jackson</artifactId> <dependency>
</dependency> <groupId>com.fasterxml.jackson.module</groupId>
<dependency> <artifactId>jackson-module-kotlin</artifactId>
<groupId>org.jetbrains.kotlin</groupId> </dependency>
<artifactId>kotlin-stdlib-jdk8</artifactId> <dependency>
</dependency> <groupId>org.jetbrains.kotlin</groupId>
<dependency> <artifactId>kotlin-reflect</artifactId>
<groupId>io.quarkus</groupId> </dependency>
<artifactId>quarkus-junit5</artifactId> <dependency>
<scope>test</scope> <groupId>org.jetbrains.kotlin</groupId>
</dependency> <artifactId>kotlin-stdlib</artifactId>
<dependency> </dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId> <dependency>
<scope>test</scope> <groupId>org.springframework.boot</groupId>
</dependency> <artifactId>spring-boot-devtools</artifactId>
<dependency> <scope>runtime</scope>
<groupId>io.quarkus</groupId> <optional>true</optional>
<artifactId>quarkus-kotlin</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<groupId>io.quarkus</groupId> <artifactId>spring-boot-starter-test</artifactId>
<artifactId>quarkus-undertow</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>
</dependency> <scope>test</scope>
</dependencies> </dependency>
<build> </dependencies>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory> <build>
<plugins> <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<plugin> <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<groupId>io.quarkus</groupId> <plugins>
<artifactId>quarkus-maven-plugin</artifactId> <plugin>
<version>${quarkus-plugin.version}</version> <groupId>org.springframework.boot</groupId>
<executions> <artifactId>spring-boot-maven-plugin</artifactId>
<execution> </plugin>
<goals> <plugin>
<goal>build</goal> <groupId>org.jetbrains.kotlin</groupId>
</goals> <artifactId>kotlin-maven-plugin</artifactId>
</execution> <configuration>
</executions> <args>
</plugin> <arg>-Xjsr305=strict</arg>
<plugin> </args>
<artifactId>maven-compiler-plugin</artifactId> <compilerPlugins>
<version>${compiler-plugin.version}</version> <plugin>spring</plugin>
</plugin> </compilerPlugins>
<plugin> </configuration>
<artifactId>maven-surefire-plugin</artifactId> <dependencies>
<version>${surefire-plugin.version}</version> <dependency>
<configuration> <groupId>org.jetbrains.kotlin</groupId>
<systemProperties> <artifactId>kotlin-maven-allopen</artifactId>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> <version>${kotlin.version}</version>
</systemProperties> </dependency>
</configuration> </dependencies>
</plugin> </plugin>
<plugin> </plugins>
<groupId>org.jetbrains.kotlin</groupId> </build>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</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>
</plugins>
</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