diff --git a/.gitignore b/.gitignore index fc0c073a..70ed16d1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ ._* *.code-workspace vendor -dist +bin/* backend/config.json backend/internal/api/handler/assets test/node_modules diff --git a/Jenkinsfile b/Jenkinsfile index 80a39e6d..684ec0c8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -46,19 +46,11 @@ pipeline { } } } - stage('Versions') { - steps { - // Is this frontend version stuff still applicable? - sh 'cat frontend/package.json | jq --arg BUILD_VERSION "${BUILD_VERSION}" \'.version = $BUILD_VERSION\' | sponge frontend/package.json' - sh 'echo -e "\\E[1;36mFrontend Version is:\\E[1;33m $(cat frontend/package.json | jq -r .version)\\E[0m"' - sh 'sed -i -E "s/(version-)[0-9]+\\.[0-9]+\\.[0-9]+(-green)/\\1${BUILD_VERSION}\\2/" README.md' - } - } } } stage('Frontend') { steps { - sh './scripts/ci/frontend-build' + sh './scripts/ci/build-frontend' } post { always { @@ -69,18 +61,17 @@ pipeline { } stage('Backend') { steps { - withCredentials([usernamePassword(credentialsId: 'oss-index-token', passwordVariable: 'NANCY_TOKEN', usernameVariable: 'NANCY_USER')]) { - sh '''docker build --pull --no-cache --squash --compress \\ + withCredentials([string(credentialsId: 'npm-sentry-dsn', variable: 'SENTRY_DSN')]) { + withCredentials([usernamePassword(credentialsId: 'oss-index-token', passwordVariable: 'NANCY_TOKEN', usernameVariable: 'NANCY_USER')]) { + sh './scripts/ci/test-backend' + } + sh './scripts/ci/build-backend' + sh '''docker build --pull --no-cache \\ -t "${IMAGE}:${BRANCH_LOWER}-ci-${BUILD_NUMBER}" \\ -f docker/Dockerfile \\ - --build-arg BUILD_COMMIT="${BUILD_COMMIT:-dev}" \\ + --build-arg BUILD_COMMIT="${BUILD_COMMIT}" \\ --build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \\ --build-arg BUILD_VERSION="${BUILD_VERSION}" \\ - --build-arg GOPRIVATE="${GOPRIVATE:-}" \\ - --build-arg GOPROXY="${GOPROXY:-}" \\ - --build-arg NANCY_TOKEN="${NANCY_TOKEN:-}" \\ - --build-arg NANCY_USER="${NANCY_USER:-}" \\ - --build-arg SENTRY_DSN="${SENTRY_DSN:-}" \\ . ''' } diff --git a/docker/Dockerfile b/docker/Dockerfile index f1e428ca..f98a8fcc 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,13 +1,10 @@ # This is a Dockerfile intended to be built using `docker buildx` # for multi-arch support. Building with `docker build` may have unexpected results. -# This file assumes that the frontend has been built using ./scripts/frontend-build +# This file assumes that these scripts have been run first: +# - ./scripts/ci/build-frontend -#=============== -# gobuild -#=============== - -FROM jc21/nginx-full:github-acme.sh-golang AS gobuild +FROM jc21/gotools:latest AS gobuild SHELL ["/bin/bash", "-o", "pipefail", "-c"] @@ -15,10 +12,7 @@ ARG BUILD_COMMIT ARG BUILD_VERSION ARG GOPRIVATE ARG GOPROXY -ARG NANCY_TOKEN -ARG NANCY_USER ARG SENTRY_DSN -ARG SKIP_TESTS ENV BUILD_COMMIT="${BUILD_COMMIT:-dev}" \ BUILD_VERSION="${BUILD_VERSION:-0.0.0}" \ @@ -26,16 +20,16 @@ ENV BUILD_COMMIT="${BUILD_COMMIT:-dev}" \ GO111MODULE=on \ GOPRIVATE="${GOPRIVATE:-}" \ GOPROXY="${GOPROXY:-}" \ - NANCY_TOKEN="${NANCY_TOKEN:-}" \ - NANCY_USER="${NANCY_USER:-}" \ - SENTRY_DSN="${SENTRY_DSN:-}" \ - SKIP_TESTS="${SKIP_TESTS:-}" + SENTRY_DSN="${SENTRY_DSN:-}" -# Code -RUN mkdir -p /app +COPY backend /app WORKDIR /app -COPY . . -RUN ./scripts/docker-gobuild + +RUN mkdir -p /dist \ + && go build \ + -ldflags "-w -s -X main.commit=${BUILD_COMMIT:-notset} -X main.version=${BUILD_VERSION} -X main.sentryDSN=${SENTRY_DSN:-}" \ + -o "/dist/server" \ + ./cmd/server #=============== # Final image @@ -43,15 +37,15 @@ RUN ./scripts/docker-gobuild FROM jc21/nginx-full:github-acme.sh AS final -COPY --from=gobuild /app/dist /app -COPY --from=gobuild /app/backend/migrations /app/migrations +COPY --from=gobuild /dist/server /app/server +COPY backend/migrations /app/migrations ENV SUPPRESS_NO_CONFIG_WARNING=1 ENV S6_FIX_ATTRS_HIDDEN=1 RUN echo "fs.file-max = 65535" > /etc/sysctl.conf # s6 overlay -RUN curl -L -o /tmp/s6-overlay-amd64.tar.gz "https://github.com/just-containers/s6-overlay/releases/download/v1.22.1.0/s6-overlay-amd64.tar.gz" \ +RUN curl -L -o /tmp/s6-overlay-amd64.tar.gz "https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64.tar.gz" \ && tar -xzf /tmp/s6-overlay-amd64.tar.gz -C / EXPOSE 80/tcp 81/tcp 443/tcp diff --git a/scripts/ci/build-backend b/scripts/ci/build-backend new file mode 100755 index 00000000..283cf313 --- /dev/null +++ b/scripts/ci/build-backend @@ -0,0 +1,79 @@ +#!/bin/bash +set -e + +IMAGE=jc21/gotools:latest + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +. "$DIR/../.common.sh" + +BUILD_DATE=$(date '+%Y-%m-%d %T %Z') +NOW=$(date --rfc-3339=s) + +cd $DIR/../.. + +if [ "$BUILD_COMMIT" = "" ]; then + BUILD_COMMIT=$(git log -n 1 --format=%h) +fi + +if [ "$BUILD_VERSION" = "" ]; then + BUILD_VERSION=$(cat .version) +fi + +echo -e "${BLUE}❯ ${GREEN}build-backend:${RESET}" +echo " BUILD_COMMIT: ${BUILD_COMMIT:-notset}" +echo " BUILD_DATE: $BUILD_DATE" +echo " BUILD_VERSION: $BUILD_VERSION" +echo " CGO_ENABLED: ${CGO_ENABLED:-not set}" +echo " GO111MODULE: ${GO111MODULE:-}" +echo " GOPRIVATE: ${GOPRIVATE:-}" +echo " GOPROXY: ${GOPROXY:-}" +echo " NOW: $NOW" + +cleanup() { + docker run --rm -v "$(pwd):/app" "${IMAGE}" chown -R "$(id -u):$(id -g)" /app/bin +} + +build_backend() { + echo -e "${BLUE}❯ ${CYAN}Building backend for ${YELLOW}${1}-${2} ...${RESET}" + + FILENAME="nginxproxymanager-v${BUILD_VERSION}_${1}_${2}" + if [ "$1" = "windows" ]; then + FILENAME="${FILENAME}.exe" + fi + + docker run --rm \ + -e BUILD_COMMIT="${BUILD_COMMIT:-notset}" \ + -e BUILD_DATE="$BUILD_DATE" \ + -e BUILD_VERSION="$BUILD_VERSION" \ + -e GOARCH="${2}" \ + -e GOOS="${1}" \ + -e GOPRIVATE="${GOPRIVATE:-}" \ + -e GOPROXY="${GOPROXY:-}" \ + -e NOW="$NOW" \ + -e SENTRY_DSN="${SENTRY_DSN:-}" \ + -e TZ="${TZ:-Australia/Brisbane}" \ + -v "$(pwd):/app" \ + -w '/app/backend' \ + "${IMAGE}" \ + go build \ + -ldflags "-w -s -X main.commit=${BUILD_COMMIT:-notset} -X main.version=${BUILD_VERSION} -X main.sentryDSN=${SENTRY_DSN:-}" \ + -o "/app/bin/$FILENAME" \ + ./cmd/server +} + +docker pull "${IMAGE}" + +build_backend "darwin" "amd64" +build_backend "darwin" "arm64" +build_backend "linux" "amd64" +build_backend "linux" "arm64" +build_backend "linux" "arm" +build_backend "openbsd" "amd64" +build_backend "windows" "amd64" + +cleanup + +echo -e "${BLUE}❯ ${GREEN}build-backend completed${RESET}" +exit 0 + +trap cleanup EXIT diff --git a/scripts/ci/frontend-build b/scripts/ci/build-frontend similarity index 100% rename from scripts/ci/frontend-build rename to scripts/ci/build-frontend diff --git a/scripts/ci/test-backend b/scripts/ci/test-backend new file mode 100755 index 00000000..eb5ed41a --- /dev/null +++ b/scripts/ci/test-backend @@ -0,0 +1,70 @@ +#!/bin/bash +set -e + +IMAGE=jc21/gotools:latest + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +. "$DIR/../.common.sh" + +BUILD_DATE=$(date '+%Y-%m-%d %T %Z') +NOW=$(date --rfc-3339=s) +cd $DIR/../.. + +if [ "$BUILD_COMMIT" = "" ]; then + BUILD_COMMIT=$(git log -n 1 --format=%h) +fi + +if [ "$BUILD_VERSION" = "" ]; then + BUILD_VERSION=$(cat .version) +fi + +echo -e "${BLUE}❯ ${GREEN}test-backend: ${YELLOW}${1:-}${RESET}" +echo " BUILD_COMMIT: ${BUILD_COMMIT:-notset}" +echo " BUILD_DATE: $BUILD_DATE" +echo " BUILD_VERSION: $BUILD_VERSION" +echo " CGO_ENABLED: ${CGO_ENABLED:-not set}" +echo " GO111MODULE: ${GO111MODULE:-}" +echo " GOPRIVATE: ${GOPRIVATE:-}" +echo " GOPROXY: ${GOPROXY:-}" +echo " NOW: $NOW" + +if [ "${1:-}" = "--inside-docker" ]; then + mkdir -p /workspace + echo -e "${BLUE}❯ ${CYAN}Nancy setup${RESET}" + cd /workspace + # go get github.com/sonatype-nexus-community/nancy + cp /app/backend/go.mod /app/backend/go.sum /app/backend/.nancy-ignore . + go mod download + + echo -e "${BLUE}❯ ${CYAN}Nancy testing${RESET}" + go list -json -m all | nancy sleuth --quiet --username "${NANCY_USER}" --token "${NANCY_TOKEN:-}" + rm -rf /workspace + + echo -e "${BLUE}❯ ${CYAN}Testing backend code${RESET}" + cd /app/backend + [ -z "$(go tool fix -diff ./internal)" ] + richgo test -cover -v ./internal/... + richgo test -bench=. ./internal/... + golangci-lint -v run ./... +else + # run this script from within docker + docker pull "${IMAGE}" + docker run --rm \ + -e BUILD_COMMIT="${BUILD_COMMIT:-notset}" \ + -e BUILD_DATE="$BUILD_DATE" \ + -e BUILD_VERSION="$BUILD_VERSION" \ + -e GOARCH="${2}" \ + -e GOOS="${1}" \ + -e GOPRIVATE="${GOPRIVATE:-}" \ + -e GOPROXY="${GOPROXY:-}" \ + -e NOW="$NOW" \ + -e SENTRY_DSN="${SENTRY_DSN:-}" \ + -e TZ="${TZ:-Australia/Brisbane}" \ + -v "$(pwd):/app" \ + -w '/app/backend' \ + "${IMAGE}" \ + /app/scripts/ci/test-backend --inside-docker +fi + +echo -e "${BLUE}❯ ${GREEN}test-backend ${YELLOW}${1:-} ${GREEN}completed${RESET}" +exit 0 diff --git a/scripts/docker-gobuild b/scripts/docker-gobuild deleted file mode 100755 index a34a58cf..00000000 --- a/scripts/docker-gobuild +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -e - -# This script is run as part of the Dockerfile -# It will conduct golang testing and vuln lookups -# unless SKIP_TESTS=1 is defined - -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -. "$DIR/.common.sh" - -echo -e "${BLUE}❯ ${CYAN}docker-gobuild${RESET}" -echo -e " ${YELLOW}BUILD_COMMIT: ${BUILD_COMMIT:-not set}${RESET}" -echo -e " ${YELLOW}BUILD_VERSION: ${BUILD_VERSION:-not set}${RESET}" -echo -e " ${YELLOW}CGO_ENABLED: ${CGO_ENABLED:-not set}${RESET}" -echo -e " ${YELLOW}GOPROXY: ${GOPROXY:-not set}${RESET}" -echo -e " ${YELLOW}GOPRIVATE: ${GOPRIVATE:-not set}${RESET}" -echo -e " ${YELLOW}GO111MODULE: ${GO111MODULE:-not set}${RESET}" -echo -e " ${YELLOW}SKIP_TESTS: ${SKIP_TESTS:-not set}${RESET}" - -echo -e "${BLUE}❯ ${CYAN}Downloading backend go modules${RESET}" -cd /app/backend -go mod download - -# Testing and vulnerability lookup -if ! [ "${SKIP_TESTS:-}" = "1" ]; then - mkdir -p /workspace - echo -e "${BLUE}❯ ${CYAN}Nancy setup${RESET}" - cd /workspace - go get github.com/sonatype-nexus-community/nancy - cp /app/backend/go.mod /app/backend/go.sum /app/backend/.nancy-ignore . - go mod download - - echo -e "${BLUE}❯ ${CYAN}Nancy testing${RESET}" - go list -json -m all | nancy sleuth --quiet --username "${NANCY_USER}" --token "${NANCY_TOKEN:-}" - rm -rf /workspace - - echo -e "${BLUE}❯ ${CYAN}Testing backend code${RESET}" - cd /app/backend - [ -z "$(go tool fix -diff ./internal)" ] - richgo test -cover -v ./internal/... - richgo test -bench=. ./internal/... - golangci-lint -v run ./... -fi - -echo -e "${BLUE}❯ ${CYAN}Building backend binary${RESET}" -go build \ - -ldflags "-w -s -X main.commit=${BUILD_COMMIT} -X main.version=${BUILD_VERSION} -X main.sentryDSN=${SENTRY_DSN:-}" \ - -o ../dist/bin/server \ - -v ./cmd/server - -echo -e "${BLUE}❯ ${CYAN}docker-gobuild ${GREEN}completed${RESET}"