diff --git a/.github/workflows/mmbm-deploy.yml b/.github/workflows/mmbm-deploy.yml new file mode 100644 index 00000000..76650d45 --- /dev/null +++ b/.github/workflows/mmbm-deploy.yml @@ -0,0 +1,16 @@ +name: mmbm-deploy +on: + pull_request: { types: [opened, reopened, synchronize, ready_for_review] } + push: { branches: [main] } + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build image + run: docker build --network=host -t app:latest -f template-dockerfile . + + # Push the image to a Docker container registry diff --git a/.github/workflows/mmbm-tests.yml b/.github/workflows/mmbm-tests.yml new file mode 100644 index 00000000..dc7c8bfc --- /dev/null +++ b/.github/workflows/mmbm-tests.yml @@ -0,0 +1,16 @@ +name: mmbm-tests +on: + pull_request: { types: [opened, reopened, synchronize, ready_for_review] } + push: { branches: [main] } + +jobs: + unit-tests: + runs-on: swift:6.0-noble + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Run unit tests + run: swift test --enable-code-coverage + + # Process the code coverage report, etc... diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f52e4a25..10bf60d8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,7 +3,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: - pull_request: { types: [opened, reopened, synchronize, ready_for_review] } + # pull_request: { types: [opened, reopened, synchronize, ready_for_review] } push: { branches: [main] } jobs: diff --git a/Dockerfile b/Dockerfile index ddced0c7..48c9be8e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # ================================ # Build image # ================================ -FROM swift:6.0-jammy as build +FROM swift:6.0-noble as build ARG SWIFT_CONFIGURATION ARG EXEC_NAME @@ -26,7 +26,7 @@ RUN rm -dr .build # ================================ # Run image # ================================ -FROM ubuntu:jammy +FROM ubuntu:noble # Make sure all system packages are up to date, and install only essential packages. RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ diff --git a/template-dockerfile b/template-dockerfile new file mode 100644 index 00000000..655d9fb1 --- /dev/null +++ b/template-dockerfile @@ -0,0 +1,89 @@ +# ================================ +# Build image +# ================================ +FROM swift:6.0-jammy AS build + +# Install OS updates +RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + && apt-get -q update \ + && apt-get -q dist-upgrade -y \ + && apt-get install -y libjemalloc-dev + +# Set up a build area +WORKDIR /build + +# First just resolve dependencies. +# This creates a cached layer that can be reused +# as long as your Package.swift/Package.resolved +# files do not change. +COPY ./Package.* ./ +RUN swift package resolve \ + $([ -f ./Package.resolved ] && echo "--force-resolved-versions" || true) + +# Copy entire repo into container +COPY . . + +# Build the application, with optimizations, with static linking, and using jemalloc +# N.B.: The static version of jemalloc is incompatible with the static Swift runtime. +RUN swift build -c release \ + --product App \ + --static-swift-stdlib \ + -Xlinker -ljemalloc + +# 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" ./ + +# Copy static swift backtracer binary to staging area +RUN cp "/usr/libexec/swift/linux/swift-backtrace-static" ./ + +# Copy resources bundled by SPM to staging area +RUN find -L "$(swift build --package-path /build -c release --show-bin-path)/" -regex '.*\.resources$' -exec cp -Ra {} ./ \; + +# Copy any resources 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. +RUN [ -d /build/Public ] && { mv /build/Public ./Public && chmod -R a-w ./Public; } || true +RUN [ -d /build/Resources ] && { mv /build/Resources ./Resources && chmod -R a-w ./Resources; } || true + +# ================================ +# Run image +# ================================ +FROM ubuntu:jammy + +# Make sure all system packages are up to date, and install only essential packages. +RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + && apt-get -q update \ + && apt-get -q dist-upgrade -y \ + && apt-get -q install -y \ + libjemalloc2 \ + ca-certificates \ + tzdata \ +# If your app or its dependencies import FoundationNetworking, also install `libcurl4`. + # libcurl4 \ +# If your app or its dependencies import FoundationXML, also install `libxml2`. + # libxml2 \ + && rm -r /var/lib/apt/lists/* + +# Create a vapor user and group with /app as its home directory +RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /app vapor + +# Switch to the new home directory +WORKDIR /app + +# Copy built executable and any staged resources from builder +COPY --from=build --chown=vapor:vapor /staging /app + +# Provide configuration needed by the built-in crash reporter and some sensible default behaviors. +ENV SWIFT_BACKTRACE=enable=yes,sanitize=yes,threads=all,images=all,interactive=no,swift-backtrace=./swift-backtrace-static + +# Ensure all further commands run as the vapor user +USER vapor:vapor + +# Let Docker bind to port 8080 +EXPOSE 8080 + +# Start the Vapor service when the image is run, default to listening on 8080 in production environment +ENTRYPOINT ["./App"] +CMD ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]