Skip to content
This repository was archived by the owner on Mar 21, 2025. It is now read-only.

Commit 17f2bc7

Browse files
committed
WIP. First version with basic test
1 parent e947609 commit 17f2bc7

File tree

27 files changed

+552
-2
lines changed

27 files changed

+552
-2
lines changed

.github/workflows/main.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
strategy:
1818
fail-fast: true
1919
matrix:
20-
image: ["buildah", "finish", "go-toolset", "gradle-toolset", "helm", "sonar", "start", "pipeline-manager", "python-toolset", "node16-npm-toolset"]
20+
image: ["buildah", "finish", "go-toolset", "gradle-toolset", "helm", "sonar", "start", "pipeline-manager", "python-toolset", "node16-npm-toolset", "sbt-toolset"]
2121
steps:
2222
-
2323
name: Checkout
@@ -53,7 +53,7 @@ jobs:
5353
runs-on: ubuntu-latest
5454
needs: build-images
5555
env:
56-
IMAGES: buildah finish go-toolset gradle-toolset helm sonar start pipeline-manager python-toolset node16-npm-toolset
56+
IMAGES: buildah finish go-toolset gradle-toolset helm sonar start pipeline-manager python-toolset node16-npm-toolset sbt-toolset
5757
steps:
5858
-
5959
name: Download image artifacts
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
FROM registry.access.redhat.com/ubi8/openjdk-11:1.13
2+
3+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
4+
5+
ARG SBT_VERSION=1.7.1
6+
ARG SBT_SHA256=2ae094410b518acc46d9cdcdc4e138b4c27cd5040fc91d48d2d823fe84984294
7+
8+
ENV LANG=en_US.UTF-8 \
9+
LC_ALL=en_US.UTF-8
10+
11+
USER root
12+
13+
RUN microdnf install --nodocs openssl-${OPENSSL_VERSION}* git-${GIT_VERSION}* && microdnf clean all
14+
15+
RUN SBT_INSTALL_DIR=/tmp/sbt-install && \
16+
mkdir -p $SBT_INSTALL_DIR && \
17+
cd $SBT_INSTALL_DIR && \
18+
curl -LO https://github.com/sbt/sbt/releases/download/v${SBT_VERSION}/sbt-${SBT_VERSION}.zip && \
19+
echo $SBT_SHA256 sbt-${SBT_VERSION}.zip | sha256sum -c - && \
20+
unzip -d /opt sbt-${SBT_VERSION}.zip && \
21+
ln -s /opt/sbt/bin/sbt /usr/local/bin/sbt && \
22+
rm -rf $SBT_INSTALL_DIR
23+
24+
RUN sbt -v sbtVersion && \
25+
rm -rf project target
26+
27+
# Add scripts
28+
COPY build/package/scripts/cache-build.sh /usr/local/bin/cache-build
29+
COPY build/package/scripts/copy-build-if-cached.sh /usr/local/bin/copy-build-if-cached
30+
COPY build/package/scripts/copy-artifacts.sh /usr/local/bin/copy-artifacts
31+
COPY build/package/scripts/build-sbt.sh /usr/local/bin/build-sbt
32+
COPY build/package/scripts/supply-sonar-project-properties-default.sh /usr/local/bin/supply-sonar-project-properties-default
33+
# TODO set sbt http proxy COPY build/package/scripts/set-sbt-proxy.sh /usr/local/bin/set-sbt-proxy
34+
RUN chmod +x /usr/local/bin/build-sbt && \
35+
chmod +x /usr/local/bin/cache-build && \
36+
chmod +x /usr/local/bin/copy-build-if-cached && \
37+
chmod +x /usr/local/bin/copy-artifacts && \
38+
chmod +x /usr/local/bin/supply-sonar-project-properties-default && \
39+
chown -R 1001:0 /tmp/.sbt
40+
# TODO set sbt http proxy chmod +x /usr/local/bin/set-sbt-proxy # TODO set sbt http proxy
41+
42+
# Add sonar-project.properties
43+
COPY build/package/sonar-project.properties.d/sbt.properties /usr/local/default-sonar-project.properties
44+
45+
USER 1001

build/package/scripts/build-sbt.sh

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/bin/bash
2+
set -eu
3+
4+
OUTPUT_DIR="docker"
5+
WORKING_DIR="."
6+
ROOT_DIR=$(pwd)
7+
export ARTIFACTS_DIR=$ROOT_DIR/.ods/artifacts
8+
9+
# might be needed for several task executions that would publish to the same artefact path...
10+
ARTIFACT_PREFIX=
11+
DEBUG="${DEBUG:-false}"
12+
13+
while [[ "$#" -gt 0 ]]; do
14+
case $1 in
15+
16+
--working-dir) WORKING_DIR="$2"; shift;;
17+
--working-dir=*) WORKING_DIR="${1#*=}";;
18+
19+
--output-dir) OUTPUT_DIR="$2"; shift;;
20+
--output-dir=*) OUTPUT_DIR="${1#*=}";;
21+
22+
*) echo "Unknown parameter passed: $1"; exit 1;;
23+
esac; shift; done
24+
25+
if [ "${WORKING_DIR}" != "." ]; then
26+
WORKING_DIR="${ROOT_DIR}"
27+
ARTIFACT_PREFIX="${WORKING_DIR/\//-}-"
28+
fi
29+
30+
if [ "${DEBUG}" == "true" ]; then
31+
set -x
32+
fi
33+
34+
echo "Using NEXUS_URL=$NEXUS_URL"
35+
echo "Using ARTIFACTS_DIR=$ARTIFACTS_DIR"
36+
37+
echo
38+
cd "${WORKING_DIR}"
39+
echo "Working on SBT project in '${WORKING_DIR}'..."
40+
echo
41+
export ODS_OUTPUT_DIR=${OUTPUT_DIR}
42+
echo "Exported env var 'ODS_OUTPUT_DIR' with value '${OUTPUT_DIR}'"
43+
echo
44+
echo "Building (Compile and Test) ..."
45+
# shellcheck disable=SC2086
46+
# old command: "sbt clean scalafmtSbtCheck scalafmtCheckAll coverage test coverageReport copyDockerFiles"
47+
# plugins needed by the build: scalafmt scoverage native-packager
48+
# TODO: with scoverage the build needs to run two times, one time with coverage and one time without, otherwise the production code
49+
# will end up instrumented in production... This is due to the fact that scoverage has no way for on-the-fly instrumentation which only happens in memory
50+
51+
# check format of sbt and source files, activate coverage and test with coverage report
52+
sbt -no-colors -v clean scalafmtSbtCheck scalafmtCheckAll coverage test coverageReport
53+
54+
# copy reports
55+
echo "Verifying unit test report was generated ..."
56+
BUILD_DIR="target"
57+
UNIT_TEST_RESULT_DIR="${BUILD_DIR}/test-reports"
58+
if [ -d "${UNIT_TEST_RESULT_DIR}" ]; then
59+
UNIT_TEST_ARTIFACTS_DIR="${ARTIFACTS_DIR}/xunit-reports"
60+
mkdir -p "${UNIT_TEST_ARTIFACTS_DIR}"
61+
cp "${UNIT_TEST_RESULT_DIR}/"*.xml "${UNIT_TEST_ARTIFACTS_DIR}/${ARTIFACT_PREFIX}"
62+
else
63+
echo "Build failed: no unit test results found in ${UNIT_TEST_RESULT_DIR}"
64+
exit 1
65+
fi
66+
67+
echo "Verifying unit test coverage report was generated ..."
68+
COVERAGE_RESULT_DIR="${BUILD_DIR}/scala-2.13"
69+
if [ -d "${COVERAGE_RESULT_DIR}" ]; then
70+
CODE_COVERAGE_ARTIFACTS_DIR="${ARTIFACTS_DIR}/code-coverage"
71+
mkdir -p "${CODE_COVERAGE_ARTIFACTS_DIR}"
72+
cp "${COVERAGE_RESULT_DIR}/scoverage-report/scoverage.xml" "${CODE_COVERAGE_ARTIFACTS_DIR}/${ARTIFACT_PREFIX}scoverage.xml"
73+
else
74+
echo "Build failed: no unit test coverage report was found in ${COVERAGE_RESULT_DIR}"
75+
exit 1
76+
fi
77+
78+
# create a clean binary as the previous compiled sources where instrumented for the coverage report
79+
sbt -no-colors -v clean stage
80+
81+
STAGING_DIR="${BUILD_DIR}/universal/stage"
82+
echo "Copying contents of ${STAGING_DIR} to ${OUTPUT_DIR}/dist ..."
83+
cp -r "${STAGING_DIR}/." "${OUTPUT_DIR}/dist"
84+
85+
# TODO oder alles in einem command:
86+
# sbt clean coverage test coverageReport coverageOff clean compile / publishMyReports / copy stuff to docker...
87+
# dann muss man nur dafür sorgen, dass die reports vor dem 2. clean gesaved werden...
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# this is just a fallback sonar properties. A matching one should be provided by each project
2+
sonar.sources=app
3+
sonar.sourceEncoding=UTF-8
4+
sonar.scala.version=2.13
5+
sonar.scala.scapegoat.disable=true
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{{if or .Values.global.enabledTasks.buildSbt .Values.sbtToolset}}
2+
kind: BuildConfig
3+
apiVersion: build.openshift.io/v1
4+
metadata:
5+
name: ods-sbt-toolset
6+
labels:
7+
{{- include "chart.labels" . | nindent 4}}
8+
spec:
9+
nodeSelector: null
10+
output:
11+
to:
12+
kind: ImageStreamTag
13+
name: 'ods-sbt-toolset:{{.Values.global.imageTag | default .Chart.AppVersion}}'
14+
resources: {}
15+
successfulBuildsHistoryLimit: 5
16+
failedBuildsHistoryLimit: 5
17+
postCommit: {}
18+
strategy:
19+
type: Docker
20+
dockerStrategy:
21+
buildArgs:
22+
- name: imageTag
23+
value: '{{.Values.global.imageTag | default .Chart.AppVersion}}'
24+
- name: privateCertServer
25+
value: '{{.Values.privateCertServer}}'
26+
source:
27+
dockerfile: |-
28+
{{- .Files.Get "docker/Dockerfile.sbt-toolset" | nindent 6}}
29+
runPolicy: Serial
30+
{{end}}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{{if or .Values.global.enabledTasks.buildSbt .Values.sbtToolset}}
2+
apiVersion: image.openshift.io/v1
3+
kind: ImageStream
4+
metadata:
5+
name: ods-sbt-toolset
6+
labels:
7+
{{- include "chart.labels" . | nindent 4}}
8+
annotations:
9+
"helm.sh/resource-policy": keep
10+
{{end}}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{{if .Values.global.enabledTasks.buildSbt }}
2+
apiVersion: tekton.dev/v1beta1
3+
kind: '{{default "Task" .Values.global.taskKind}}'
4+
metadata:
5+
name: '{{default "ods" .Values.taskPrefix}}-build-sbt{{- include "taskSuffix" .}}'
6+
annotations:
7+
"helm.sh/resource-policy": keep
8+
spec:
9+
description: |
10+
sbt build - TBD
11+
params:
12+
- name: working-dir
13+
description: |
14+
Working directory. The path must be relative to the root of the repository,
15+
without leading `./` and trailing `/`.
16+
type: string
17+
default: "."
18+
- name: output-dir
19+
description: >-
20+
Path to the directory into which the resulting build artifact should be copied, relative to `working-dir`.
21+
This directory may then later be used as Docker context for example.
22+
type: string
23+
default: docker
24+
- name: cache-build
25+
description: >-
26+
If enabled tasks uses or populates cache with the output dir contents (and artifacts) so that
27+
a build can be skipped if the `working-dir` contents did not change.
28+
For single build repos enabling build caching has limited benefits. For multi build repos enabling this is recommended unless the build is dependant on files outside of the working directory. See ADR caching-build-tasks for more details and workarounds.
29+
type: string
30+
default: "false"
31+
- name: build-script
32+
description: >-
33+
Build script to execute. The
34+
link:https://github.com/opendevstack/ods-pipeline/blob/master/build/package/scripts/build-sbt.sh[default script]
35+
is located in the container image. If you specify a relative path
36+
instead, it will be resolved from the workspace. See the task definition
37+
for details how the build script is invoked.
38+
type: string
39+
default: "/usr/local/bin/build-sbt"
40+
- name: sonar-quality-gate
41+
description: Whether the SonarQube quality gate needs to pass for the task to succeed.
42+
type: string
43+
default: "false"
44+
- name: sonar-skip
45+
description: Whether to skip SonarQube analysis or not.
46+
type: string
47+
default: "false"
48+
results:
49+
- description: The cache location that the build task used. If caching is not enabled this will be an empty string.
50+
name: build-reused-from-location
51+
{{- with ((.Values.sbt).sidecars) }}
52+
sidecars:
53+
{{- toYaml . | nindent 4 }}
54+
{{- end }}
55+
steps:
56+
- name: build-sbt-binary
57+
# Image is built from build/package/Dockerfile.sbt-toolset.
58+
image: '{{.Values.registry}}/{{default .Release.Namespace .Values.namespace}}/ods-sbt-toolset:{{.Values.global.imageTag | default .Chart.AppVersion}}'
59+
env:
60+
- name: DEBUG
61+
valueFrom:
62+
configMapKeyRef:
63+
key: debug
64+
name: ods-pipeline
65+
- name: HOME
66+
value: '/tekton/home'
67+
- name: CI
68+
value: "true"
69+
- name: NEXUS_URL
70+
valueFrom:
71+
configMapKeyRef:
72+
key: url
73+
name: ods-nexus
74+
- name: NEXUS_USERNAME
75+
valueFrom:
76+
secretKeyRef:
77+
key: username
78+
name: ods-nexus-auth
79+
- name: NEXUS_PASSWORD
80+
valueFrom:
81+
secretKeyRef:
82+
key: password
83+
name: ods-nexus-auth
84+
resources:
85+
{{- (.Values.sbt).resources | default dict | toYaml | nindent 8 }}
86+
script: |
87+
supply-sonar-project-properties-default
88+
echo -n "" > $(results.build-reused-from-location.path)
89+
cache_build_key=sbt
90+
if copy-build-if-cached \
91+
--cache-build=$(params.cache-build) \
92+
--cache-build-key="$cache_build_key" \
93+
--cache-location-used-path=$(results.build-reused-from-location.path) \
94+
--working-dir=$(params.working-dir) \
95+
--output-dir=$(params.output-dir) \
96+
--debug=${DEBUG} ; then
97+
exit 0
98+
fi
99+
# Default build script is build/package/scripts/build-sbt.sh.
100+
set +e
101+
$(params.build-script) \
102+
--working-dir=$(params.working-dir) \
103+
--output-dir=$(params.output-dir)
104+
build_exit=$?
105+
set -e
106+
copy-artifacts --debug=${DEBUG}
107+
if [ $build_exit -ne 0 ]; then
108+
exit $build_exit
109+
fi
110+
if [ "$(params.cache-build)" == "true" ]; then
111+
cache-build \
112+
--cache-build-key="$cache_build_key" \
113+
--cache-location-used-path=$(results.build-reused-from-location.path) \
114+
--working-dir=$(params.working-dir) \
115+
--output-dir=$(params.output-dir) \
116+
--debug=${DEBUG}
117+
fi
118+
workingDir: $(workspaces.source.path)
119+
{{- include "sonar-step" . | indent 4}}
120+
workspaces:
121+
- name: source
122+
{{end}}

deploy/ods-pipeline/charts/tasks/values.docs.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ global:
77
buildGradle: true
88
buildPython: true
99
buildNPM: true
10+
buildSbt: true
1011
packageImage: true
1112
deployHelm: true
1213

deploy/ods-pipeline/values.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ global:
1616
buildGradle: true
1717
buildPython: true
1818
buildNPM: true
19+
buildSbt: true
1920
packageImage: true
2021
deployHelm: true
2122

test/tasks/ods-build-sbt_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package tasks
2+
3+
import (
4+
"path/filepath"
5+
"testing"
6+
"time"
7+
8+
"github.com/opendevstack/pipeline/pkg/pipelinectxt"
9+
10+
"github.com/opendevstack/pipeline/pkg/tasktesting"
11+
)
12+
13+
func TestTaskODSBuildSbt(t *testing.T) {
14+
runTaskTestCases(t,
15+
"ods-build-sbt",
16+
[]tasktesting.Service{
17+
tasktesting.Nexus,
18+
tasktesting.SonarQube,
19+
},
20+
map[string]tasktesting.TestCase{
21+
"task should build sbt sample app": {
22+
Timeout: 10 * time.Minute,
23+
WorkspaceDirMapping: map[string]string{"source": "sbt-sample-app"},
24+
PreRunFunc: func(t *testing.T, ctxt *tasktesting.TaskRunContext) {
25+
wsDir := ctxt.Workspaces["source"]
26+
ctxt.ODS = tasktesting.SetupGitRepo(t, ctxt.Namespace, wsDir)
27+
ctxt.Params = map[string]string{
28+
"sonar-quality-gate": "true",
29+
}
30+
},
31+
WantRunSuccess: true,
32+
PostRunFunc: func(t *testing.T, ctxt *tasktesting.TaskRunContext) {
33+
wsDir := ctxt.Workspaces["source"]
34+
35+
checkFilesExist(t, wsDir,
36+
"docker/Dockerfile",
37+
"docker/dist",
38+
filepath.Join(pipelinectxt.XUnitReportsPath, "TEST-controllers.HomeControllerSpec.xml"),
39+
filepath.Join(pipelinectxt.CodeCoveragesPath, "scoverage.xml"),
40+
filepath.Join(pipelinectxt.SonarAnalysisPath, "analysis-report.md"),
41+
filepath.Join(pipelinectxt.SonarAnalysisPath, "issues-report.csv"),
42+
)
43+
},
44+
},
45+
})
46+
}

0 commit comments

Comments
 (0)