diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d334c4..ae071c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,6 @@ jobs: image: ${{ matrix.image }} steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Test run: swift test diff --git a/.gitignore b/.gitignore index a7aa374..6a2360b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,3 @@ /Packages /*.xcodeproj xcuserdata/ -/Package.resolved \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 4bb787f..bb991e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # ================================ # Build image # ================================ -FROM swift:5.9 as build +FROM swift:5.10 as build # Install OS updates RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ @@ -23,13 +23,13 @@ RUN swift package resolve COPY . . # Build everything, with optimizations and test discovery -RUN swift build --enable-test-discovery -c release +RUN swift build -c release # Switch to the staging area WORKDIR /staging # Copy main executable to staging area -RUN cp "$(swift build --package-path /build -c release --show-bin-path)/App" ./ +RUN cp "$(swift build --package-path /build -c release --show-bin-path)/{{HB_EXECUTABLE_NAME}}" ./ # Copy any resouces from the public directory and views directory if the directories exist # Ensure that by default, neither the directory nor any of its contents are writable. @@ -38,7 +38,7 @@ RUN [ -d /build/public ] && { mv /build/public ./public && chmod -R a-w ./public # ================================ # Run image # ================================ -FROM swift:5.9-slim +FROM swift:5.10-slim # Make sure all system packages are up to date. RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true && \ @@ -60,5 +60,5 @@ USER hummingbird:hummingbird EXPOSE 8080 # Start the Vapor service when the image is run, default to listening on 8080 in production environment -ENTRYPOINT ["./App"] +ENTRYPOINT ["./{{HB_EXECUTABLE_NAME}}"] CMD ["--hostname", "0.0.0.0", "--port", "8080"] diff --git a/Package.swift b/Package.swift index a0c0b62..4a484bd 100644 --- a/Package.swift +++ b/Package.swift @@ -4,21 +4,22 @@ import PackageDescription let package = Package( - name: "hummingbird-template", + name: "{{HB_PACKAGE_NAME}}", platforms: [.macOS(.v14), .iOS(.v17), .tvOS(.v17)], products: [ - .executable(name: "App", targets: ["App"]), + .executable(name: "{{HB_EXECUTABLE_NAME}}", targets: ["{{HB_EXECUTABLE_NAME}}"]), ], dependencies: [ .package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0-beta.1"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0") ], targets: [ - .executableTarget(name: "App", + .executableTarget(name: "{{HB_EXECUTABLE_NAME}}", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), .product(name: "Hummingbird", package: "hummingbird"), ], + path: "Sources/App", swiftSettings: [ // Enable better optimizations when building in Release configuration. Despite the use of // the `.unsafeFlags` construct required by SwiftPM, this flag is recommended for Release @@ -26,11 +27,12 @@ let package = Package( .unsafeFlags(["-cross-module-optimization"], .when(configuration: .release)) ] ), - .testTarget(name: "AppTests", + .testTarget(name: "{{HB_EXECUTABLE_NAME}}Tests", dependencies: [ - .byName(name: "App"), + .byName(name: "{{HB_EXECUTABLE_NAME}}"), .product(name: "HummingbirdTesting", package: "hummingbird") - ] + ], + path: "Tests/AppTests" ) ] ) diff --git a/README.md b/README.md index 2cb29a7..4ec0dbd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ # Template Template for Hummingbird App + +Either click on `Use this template` or run the following to clone locally +```bash +curl -L https://raw.githubusercontent.com/hummingbird-project/template/configure/scripts/download.sh | bash -s +``` + +Then enter the folder created, run `./configure.sh` and follow the instructions. diff --git a/Sources/App/Application+build.swift b/Sources/App/Application+build.swift index 839c8c2..69ffe22 100644 --- a/Sources/App/Application+build.swift +++ b/Sources/App/Application+build.swift @@ -13,7 +13,7 @@ public protocol AppArguments { public func buildApplication(_ arguments: some AppArguments) -> some ApplicationProtocol { let logger = { - var logger = Logger(label: "HB") + var logger = Logger(label: "{{HB_PACKAGE_NAME}}") logger.logLevel = arguments.logLevel ?? .info return logger }() @@ -26,7 +26,7 @@ public func buildApplication(_ arguments: some AppArguments) -> some Application router: router, configuration: .init( address: .hostname(arguments.hostname, port: arguments.port), - serverName: "Hummingbird" + serverName: "{{HB_PACKAGE_NAME}}" ), logger: logger ) diff --git a/Tests/AppTests/AppTests.swift b/Tests/AppTests/AppTests.swift index cc559c2..26ea441 100644 --- a/Tests/AppTests/AppTests.swift +++ b/Tests/AppTests/AppTests.swift @@ -3,7 +3,7 @@ import HummingbirdTesting import Logging import XCTest -@testable import App +@testable import {{HB_EXECUTABLE_NAME}} final class AppTests: XCTestCase { struct TestArguments: AppArguments { diff --git a/configure.sh b/configure.sh new file mode 100755 index 0000000..e4ca130 --- /dev/null +++ b/configure.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +PWD=$(pwd) +TARGET_FOLDER=${1:-$PWD} +BASE_FOLDER=$(basename $TARGET_FOLDER) +CLEAN_BASE_FOLDER=$(echo "$BASE_FOLDER" | sed -e 's/[^a-zA-Z0-9_]/_/g') + +TEMP_FOLDER=$(mktemp -d) +MO="$TEMP_FOLDER"/mo + +cleanup() +{ + rm -rf "$TEMP_FOLDER" +} + +# Download MO bash mustache renderer +download_mo() +{ + curl -sSL https://raw.githubusercontent.com/tests-always-included/mo/master/mo -o "$MO" + chmod a+x "$MO" +} + +read_input_with_default () { + echo -n "[$1] > " + read -r READ_INPUT_RETURN + + if [ -z "$READ_INPUT_RETURN" ]; then + READ_INPUT_RETURN="$1" + fi +} + +run_mustache() +{ + FILES=$1 + for FILE in $FILES; do + $MO "$FILE" > "$TEMP_FOLDER"/tempfile + mv -f "$TEMP_FOLDER"/tempfile "$TARGET_FOLDER/$FILE" + done +} + +run_mustache-template() +{ + echo $1 + #| $MO > "$TEMP_FOLDER"/$2 + echo $2 +} + +exitWithError() +{ + echo "Error: $1" + exit 1 +} + +check_valid() { + if [[ "$HB_PACKAGE_NAME" =~ [^a-zA-Z0-9_] ]]; then + exitWithError "Invalid package name: $HB_PACKAGE_NAME" + fi +} +trap cleanup EXIT $? + +echo "Configuring your Hummingbird project" + +# Download Bash Mustache +download_mo + +if [[ "$TARGET_FOLDER" != "$PWD" ]]; then + echo "Outputting to $TARGET_FOLDER" + mkdir -p "$TARGET_FOLDER"/Sources/App + mkdir -p "$TARGET_FOLDER"/Tests/AppTests +else + echo "Outputting to current folder" +fi + + + +echo -n "Enter your package name: " +read_input_with_default "$CLEAN_BASE_FOLDER" +export HB_PACKAGE_NAME=$READ_INPUT_RETURN +if [[ "$HB_PACKAGE_NAME" =~ [^a-zA-Z0-9_-] ]]; then + exitWithError "Invalid package name: $HB_PACKAGE_NAME" +fi + +echo -n "Enter your executable name: " +read_input_with_default "App" +export HB_EXECUTABLE_NAME=$READ_INPUT_RETURN +if [[ "$HB_EXECUTABLE_NAME" =~ [^a-zA-Z0-9_] ]]; then + exitWithError "Invalid executable name: $HB_EXECUTABLE_NAME" +fi + +# Root level files +FILES=$(find . -maxdepth 1 ! -type d ! -name "*.sh") +run_mustache "$FILES" +# Files in Sources and Tests folder +FILES=$(find Sources Tests ! -type d) +run_mustache "$FILES" + +# README file +cat < $TARGET_FOLDER/README.md +# $HB_PACKAGE_NAME +My awesome project +EOF diff --git a/scripts/download.sh b/scripts/download.sh new file mode 100755 index 0000000..b5786de --- /dev/null +++ b/scripts/download.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +FOLDER=${1:-} +TEMPLATE_VERSION=2.0.0-beta.1 + +if [[ -z "$FOLDER" ]]; then + echo "Missing folder name" + echo "Usage: download.sh " + exit 1 +fi + +curl -sSL https://github.com/hummingbird-project/template/archive/refs/tags/"$TEMPLATE_VERSION".tar.gz | tar xvz -s /template-2.0.0-beta.1/"$FOLDER"/ \ No newline at end of file