From eed2767103b552a0f895aeb18252deecb7cc4497 Mon Sep 17 00:00:00 2001 From: irinaschubert Date: Fri, 4 Mar 2022 11:10:33 +0100 Subject: [PATCH] refactor: remove fuseki image creation and change sipi image creation to sbt (DEV-544) (#2011) * add fuseki to sbt * Change fuseki and sipi container creation to SBT * remove last of Bazel * integrate changes on remote, cleanup * remove bazel files * update sipi image version * remove remnants of bazel * fix references to sipi images and versions * Remove remnants of bazel * fix path to write test files * remove unnecessary comment * fix image in sipi's docker-compose.yml * Remove USER command * cleanup sipi folder * remove unused files Co-authored-by: Ivan Subotic <400790+subotic@users.noreply.github.com> --- .bazelrc | 7 - .bazelversion | 1 - .github/workflows/main.yml | 20 - .gitignore | 1 - BUILD.bazel | 7 - Makefile | 55 +- README.md | 18 +- RELEASING.md | 38 -- WORKSPACE | 153 ------ build.sbt | 77 ++- docker-compose.yml | 5 +- docker/knora-jena-fuseki/BUILD.bazel | 34 -- docker/knora-sipi/BUILD.bazel | 41 -- docker/knora-sipi/sipi_image_test_config.yaml | 24 - docs/05-internals/development/bazel.md | 116 ----- .../development/building-and-running.md | 21 +- .../figures/import-bazel-project.png | Bin 55644 -> 0 bytes .../development/intellij-config.md | 77 +-- docs/05-internals/development/third-party.md | 30 +- knora-ontologies/BUILD | 20 - mkdocs.yml | 1 - project/Dependencies.scala | 480 +++++++++--------- sipi/Makefile | 27 - sipi/README.md | 37 -- sipi/config/BUILD.bazel | 11 - sipi/docker-compose.yml | 46 -- sipi/scripts/BUILD.bazel | 36 -- test_data/BUILD.bazel | 6 - test_data/upgrade/BUILD.bazel | 14 - third_party/BUILD.bazel | 0 third_party/versions.bzl | 17 - toolchains/BUILD.bazel | 22 - tools/BUILD.bazel | 15 - tools/buildstamp/BUILD.bazel | 17 - tools/buildstamp/get_workspace_status | 37 -- webapi/README.md | 4 - webapi/_assets/icons/bild.png | Bin 3333 -> 0 bytes webapi/_assets/icons/bildformat.png | Bin 871 -> 0 bytes webapi/_assets/icons/book.gif | Bin 1027 -> 0 bytes webapi/_assets/icons/incunabula_logo.png | Bin 38267 -> 0 bytes webapi/_assets/icons/page.gif | Bin 232 -> 0 bytes webapi/_assets/icons/person.png | Bin 830 -> 0 bytes .../webapi/http/version/ServerVersion.scala | 1 - .../test/scala/org/knora/webapi/E2ESpec.scala | 28 +- .../test/scala/org/knora/webapi/R2RSpec.scala | 6 +- .../knora/webapi/TestContainerFuseki.scala | 3 +- .../org/knora/webapi/TestContainersAll.scala | 5 +- .../webapi/e2e/v2/OntologyV2R2RSpec.scala | 8 +- 48 files changed, 347 insertions(+), 1219 deletions(-) delete mode 100644 .bazelrc delete mode 100644 .bazelversion delete mode 100644 BUILD.bazel delete mode 100644 RELEASING.md delete mode 100644 WORKSPACE delete mode 100644 docker/knora-jena-fuseki/BUILD.bazel delete mode 100644 docker/knora-sipi/BUILD.bazel delete mode 100644 docker/knora-sipi/sipi_image_test_config.yaml delete mode 100644 docs/05-internals/development/bazel.md delete mode 100644 docs/05-internals/development/figures/import-bazel-project.png delete mode 100644 knora-ontologies/BUILD delete mode 100644 sipi/Makefile delete mode 100644 sipi/README.md delete mode 100644 sipi/config/BUILD.bazel delete mode 100644 sipi/docker-compose.yml delete mode 100644 sipi/scripts/BUILD.bazel delete mode 100644 test_data/BUILD.bazel delete mode 100644 test_data/upgrade/BUILD.bazel delete mode 100644 third_party/BUILD.bazel delete mode 100644 third_party/versions.bzl delete mode 100644 toolchains/BUILD.bazel delete mode 100644 tools/BUILD.bazel delete mode 100644 tools/buildstamp/BUILD.bazel delete mode 100755 tools/buildstamp/get_workspace_status delete mode 100644 webapi/README.md delete mode 100644 webapi/_assets/icons/bild.png delete mode 100644 webapi/_assets/icons/bildformat.png delete mode 100644 webapi/_assets/icons/book.gif delete mode 100644 webapi/_assets/icons/incunabula_logo.png delete mode 100644 webapi/_assets/icons/page.gif delete mode 100644 webapi/_assets/icons/person.png diff --git a/.bazelrc b/.bazelrc deleted file mode 100644 index 1a96c97aa3..0000000000 --- a/.bazelrc +++ /dev/null @@ -1,7 +0,0 @@ -build --disk_cache=~/.bazel_disk_cache -build --strategy=Scalac=worker -build --worker_sandboxing -build --workspace_status_command=tools/buildstamp/get_workspace_status --stamp=yes -startup --host_jvm_args=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts \ - --host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit -test --test_output=errors --local_test_jobs=1 --runs_per_test 1 diff --git a/.bazelversion b/.bazelversion deleted file mode 100644 index fae6e3d04b..0000000000 --- a/.bazelversion +++ /dev/null @@ -1 +0,0 @@ -4.2.1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8248082506..aedd59c19f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,11 +28,6 @@ jobs: with: format: YYYY-MM-DD utcOffset: "+02:00" - - name: use daily bazel disk cache - uses: actions/cache@v2 - with: - path: ~/.bazel_disk_cache - key: ${{ runner.OS }}-bazel_disk_cache-${{ steps.current-time.outputs.formattedTime }} - name: setup java version uses: joschi/setup-jdk@v2 with: @@ -75,11 +70,6 @@ jobs: with: format: YYYY-MM-DD utcOffset: "+02:00" - - name: use daily bazel disk cache - uses: actions/cache@v2 - with: - path: ~/.bazel_disk_cache - key: ${{ runner.OS }}-bazel_disk_cache-${{ steps.current-time.outputs.formattedTime }} - name: setup java version uses: joschi/setup-jdk@v2 with: @@ -121,11 +111,6 @@ jobs: with: format: YYYY-MM-DD utcOffset: "+02:00" - - name: use daily bazel disk cache - uses: actions/cache@v2 - with: - path: ~/.bazel_disk_cache - key: ${{ runner.OS }}-bazel_disk_cache-${{ steps.current-time.outputs.formattedTime }} - name: setup java version uses: joschi/setup-jdk@v2 with: @@ -221,11 +206,6 @@ jobs: with: format: YYYY-MM-DD utcOffset: "+02:00" - - name: use daily bazel disk cache - uses: actions/cache@v2 - with: - path: ~/.bazel_disk_cache - key: ${{ runner.OS }}-bazel_disk_cache-${{ steps.current-time.outputs.formattedTime }} - name: setup java version uses: joschi/setup-jdk@v2 with: diff --git a/.gitignore b/.gitignore index 23ffe63140..cd2f7b4c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,6 @@ webapi-it webapi-test upgrade/project sipi/test -bazel-* **/project/target/ **/target/ diff --git a/BUILD.bazel b/BUILD.bazel deleted file mode 100644 index d00332adca..0000000000 --- a/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier") - -buildifier( - name = "buildifier", -) diff --git a/Makefile b/Makefile index 16181707e8..dc05763536 100644 --- a/Makefile +++ b/Makefile @@ -34,53 +34,33 @@ docs-clean: ## cleans the project directory @rm -rf site/ ################################# -# Bazel targets +# Docker targets ################################# .PHONY: build build: docker-build ## build all targets (excluding docs) -.PHOBY: check-for-outdated-deps -check-for-outdated-deps: ## check for outdated maven dependencies - @bazel run @maven//:outdated - -.PHONY: buildifier -buildifier: ## format Bazel WORKSPACE and BUILD.bazel files - @bazel run :buildifier - -################################# -# Docker targets -################################# - -.PHONY: docker-build-knora-api-image -docker-build-knora-api-image: # build and publish knora-api docker image locally +.PHONY: docker-build-dsp-api-image +docker-build-dsp-api-image: # build and publish dsp-api docker image locally @sbt "webapi / Docker / publishLocal" -.PHONY: docker-publish-knora-api-image -docker-publish-knora-api-image: # publish knora-api image to Dockerhub - @bazel run //docker/knora-api:push - -.PHONY: docker-build-knora-jena-fuseki-image -docker-build-knora-jena-fuseki-image: # build and publish knora-jena-fuseki docker image locally - @bazel run //docker/knora-jena-fuseki:image +.PHONY: docker-publish-dsp-api-image +docker-publish-dsp-api-image: # publish dsp-api image to Dockerhub + @sbt "webapi / Docker / publish" -.PHONY: docker-publish-knora-jena-fuseki-image -docker-publish-knora-jena-fuseki-image: # publish knora-jena-fuseki image to Dockerhub - @bazel run //docker/knora-jena-fuseki:push +.PHONY: docker-build-sipi-image +docker-build-sipi-image: # build and publish sipi docker image locally + @sbt "sipi / Docker / publishLocal" -.PHONY: docker-build-knora-sipi-image -docker-build-knora-sipi-image: # build and publish knora-sipi docker image locally - @bazel run --action_env=PULLER_TIMEOUT=2400 //docker/knora-sipi:image - -.PHONY: docker-publish-knora-sipi-image -docker-publish-knora-sipi-image: # publish knora-sipi image to Dockerhub - @bazel run //docker/knora-sipi:push +.PHONY: docker-publish-sipi-image +docker-publish-sipi-image: # publish sipi image to Dockerhub + @sbt "sipi / Docker / publish" .PHONY: docker-build -docker-build: docker-build-knora-api-image docker-build-knora-jena-fuseki-image docker-build-knora-sipi-image ## build and publish all Docker images locally +docker-build: docker-build-dsp-api-image docker-build-sipi-image ## build and publish all Docker images locally .PHONY: docker-publish -docker-publish: docker-publish-knora-api-image docker-publish-knora-jena-fuseki-image docker-publish-knora-sipi-image ## publish all Docker images to Dockerhub +docker-publish: docker-publish-dsp-api-image docker-publish-sipi-image ## publish all Docker images to Dockerhub ################################# ## Docker-Compose targets @@ -188,7 +168,7 @@ stack-without-api-and-sipi: stack-up ## starts the knora-stack without knora-api @docker compose -f docker-compose.yml stop sipi .PHONY: stack-db-only -stack-db-only: env-file docker-build-knora-jena-fuseki-image ## starts only fuseki. +stack-db-only: env-file ## starts only fuseki. @docker compose -f docker-compose.yml up -d db $(CURRENT_DIR)/webapi/scripts/wait-for-db.sh @@ -196,10 +176,6 @@ stack-db-only: env-file docker-build-knora-jena-fuseki-image ## starts only fus ## Test Targets ################################# -.PHONY: test-docker -test-docker: docker-build ## runs Docker image tests - bazel test //docker/... - .PHONY: client-test-data client-test-data: export KNORA_WEBAPI_COLLECT_CLIENT_TEST_DATA := true client-test-data: build ## runs the dsp-api e2e tests and generates client test data. @@ -301,7 +277,6 @@ clean-local-tmp: clean: docs-clean clean-local-tmp clean-docker ## clean build artifacts @rm -rf .env - @bazel clean .PHONY: clean-sipi-tmp clean-sipi-tmp: ## deletes all files in Sipi's tmp folder diff --git a/README.md b/README.md index f130c521c9..4a741dbe58 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,6 @@ Each developer machine should have the following prerequisites installed: * Homebrew (on macOS): https://brew.sh * [OpenJDK](https://adoptopenjdk.net) 11 * [sbt](https://www.scala-sbt.org/) -* [Bazel](https://bazel.build) #### Java Adoptopenjdk 11 @@ -71,19 +70,6 @@ To pin the version of Java, please add this environment variable to you startup export JAVA_HOME=`/usr/libexec/java_home -v 11` ``` -#### Bazel build tools - -To install, follow these steps: - -```shell -npm install -g @bazel/bazelisk -``` - -This will install [bazelisk](https://github.com/bazelbuild/bazelisk) which is -a wrapper to the `bazel` binary. It will, when `bazel` is run on the command line, -automatically install the supported Bazel version, defined in the `.bazelversion` -file in the root of the `knora-api` repository. - ### For building the documentation See [docs/Readme.md](docs/Readme.md). @@ -92,9 +78,7 @@ See [docs/Readme.md](docs/Readme.md). ### Run the Knora API server -With [Bazel](https://docs.bazel.build/versions/3.3.0/install-os-x.html) and -[Docker](https://www.docker.com) installed, run the following to create a test -repository and load some test data into the triplestore: +Run the following to create a test repository and load some test data into the triplestore: ```shell make init-db-test diff --git a/RELEASING.md b/RELEASING.md deleted file mode 100644 index cf7a617987..0000000000 --- a/RELEASING.md +++ /dev/null @@ -1,38 +0,0 @@ -## Releasing - - 1. (optional) Run `GenerateContributorsFile`, passing it a GitHub API token - (`bazel run //webapi:GenerateContributorsFile -- [ -t TOKEN ]`), to generate - `Contributors.md`, then commit that file. The file can be found under: - `/bazel-bin/webapi/GenerateContributorsFile.runfiles/io_dasch_knora_api/Contributors.md` - 1. (optional) Push and merge PR to `main`. - 1. Github CI will start a [CI build](https://github.com/dasch-swiss/knora-api/actions) for the new tag and publish - artifacts to Docker Hub. - 1. On Github - Tag the commit with the version string, e.g., `vX.X.X` and create a release. - 1. Run [gren](https://github.com/github-tools/github-release-notes) (see the instruction at the end) - 1. Publish documentation. - --> in general, releases should be cut at least once per month and on the last working day of the month. --> before a major release, create a minor one if not already present. - -## Installing and running 'gren' - -``` -$ npm install github-release-notes -g -``` - -Generate a GitHub token, with repo scope, at this link. Then add this line to `~/.bash_profile` (or `~/.zshrc`) - -``` -export GREN_GITHUB_TOKEN=your_token_here -``` - -To generate the release notes for the latest release, go to Github and make a release by giving it a tag in the form of `vX.X.X`. - -Then: - -```bash -# Navigate to your project directory -cd ~/Path/to/repo -# Run the task -gren release --override --milestone-match="xxxx-xx" -``` \ No newline at end of file diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index 937be1d496..0000000000 --- a/WORKSPACE +++ /dev/null @@ -1,153 +0,0 @@ -workspace(name = "io_dasch_dsp_api") - -# load http_archive method -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -##################################### -# Skylib # -##################################### -# 1.0.2 released 2019.10.09 (https://github.com/bazelbuild/bazel-skylib/releases/tag/1.0.2) -skylib_version = "1.0.2" - -http_archive( - name = "bazel_skylib", - sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44", - type = "tar.gz", - url = "https://github.com/bazelbuild/bazel-skylib/releases/download/{}/bazel-skylib-{}.tar.gz".format(skylib_version, skylib_version), -) - -##################################### -# Buildifier # -##################################### -# buildifier is written in Go and hence needs rules_go to be built. -# See https://github.com/bazelbuild/rules_go for the up to date setup instructions. -http_archive( - name = "io_bazel_rules_go", - sha256 = "d6b2513456fe2229811da7eb67a444be7785f5323c6708b38d851d2b51e54d83", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.30.0/rules_go-v0.30.0.zip", - "https://github.com/bazelbuild/rules_go/releases/download/v0.30.0/rules_go-v0.30.0.zip", - ], -) - -load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") - -go_rules_dependencies() - -go_register_toolchains(version = "1.17.6") - -http_archive( - name = "bazel_gazelle", - sha256 = "b85f48fa105c4403326e9525ad2b2cc437babaa6e15a3fc0b1dbab0ab064bc7c", - urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.22.2/bazel-gazelle-v0.22.2.tar.gz", - "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.22.2/bazel-gazelle-v0.22.2.tar.gz", - ], -) - -# bazel buildtools providing buildifier -http_archive( - name = "com_github_bazelbuild_buildtools", - strip_prefix = "buildtools-master", - url = "https://github.com/bazelbuild/buildtools/archive/master.zip", -) - -##################################### -# Docker # -##################################### - -rules_docker_version = "0.22.0" # 06.12.2021 - -rules_docker_version_sha256 = "59536e6ae64359b716ba9c46c39183403b01eabfbd57578e84398b4829ca499a" - -http_archive( - name = "io_bazel_rules_docker", - sha256 = rules_docker_version_sha256, - strip_prefix = "rules_docker-%s" % rules_docker_version, - url = "https://github.com/bazelbuild/rules_docker/releases/download/v%s/rules_docker-v%s.tar.gz" % (rules_docker_version, rules_docker_version), -) - -load( - "@io_bazel_rules_docker//repositories:repositories.bzl", - container_repositories = "repositories", -) - -container_repositories() - -load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps") - -container_deps() - -# load container_pull method -load( - "@io_bazel_rules_docker//container:container.bzl", - "container_pull", -) - -# get openjdk -container_pull( - name = "openjdk11_amd64", - digest = "sha256:967349ef166d630bceda0370507b096edd6e7220e62e4539db70f04c04c2295f", # 7.01.2022 - registry = "docker.io", - repository = "eclipse-temurin", - # tag = "11-jre-focal", # Ubuntu 20.04 -) - -container_pull( - name = "openjdk11_arm64", - digest = "sha256:e46fac3005d08732931de9671864683f6adf3a3eb0f8a7e8ac27d1bff1955a5c", # 7.01.2022 - registry = "docker.io", - repository = "eclipse-temurin", - # tag = "11-jre-focal", # Ubuntu 20.04 -) - -# get sipi -load("//third_party:versions.bzl", "FUSEKI_IMAGE_DIGEST_AMD64", "FUSEKI_IMAGE_DIGEST_ARM64", "FUSEKI_REPOSITORY", "SIPI_IMAGE_DIGEST", "SIPI_REPOSITORY") - -container_pull( - name = "sipi", - digest = SIPI_IMAGE_DIGEST, - registry = "docker.io", - repository = SIPI_REPOSITORY, -) - -container_pull( - name = "jenafuseki_amd64", - digest = FUSEKI_IMAGE_DIGEST_AMD64, - registry = "docker.io", - repository = FUSEKI_REPOSITORY, -) - -container_pull( - name = "jenafuseki_arm64", - digest = FUSEKI_IMAGE_DIGEST_ARM64, - registry = "docker.io", - repository = FUSEKI_REPOSITORY, -) - -##################################### -# rules_pkg - basic packaging rules # -##################################### -rules_package_version = "0.2.4" - -rules_package_version_sha256 = "4ba8f4ab0ff85f2484287ab06c0d871dcb31cc54d439457d28fd4ae14b18450a" - -http_archive( - name = "rules_pkg", - sha256 = rules_package_version_sha256, - url = "https://github.com/bazelbuild/rules_pkg/releases/download/%s/rules_pkg-%s.tar.gz" % (rules_package_version, rules_package_version), -) - -load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") - -rules_pkg_dependencies() - -##################################### -# rules_stamp - stamping helper # -##################################### -http_archive( - name = "ecosia_rules_stamp", - sha256 = "36d7ea381bfb2520f9353299b162434b25c77365d3c9e9459195c536da5e837d", - strip_prefix = "rules_stamp-48d5ef2bc0d93bd65fddddbe02f3ae410e25169d", - url = "https://github.com/ecosia/rules_stamp/archive/48d5ef2bc0d93bd65fddddbe02f3ae410e25169d.tar.gz", -) diff --git a/build.sbt b/build.sbt index 92c75fb8ee..6700c194bb 100644 --- a/build.sbt +++ b/build.sbt @@ -1,8 +1,12 @@ +import rapture.core.booleanRepresentations.trueFalse import com.typesafe.sbt.SbtNativePackager.autoImport.NativePackagerHelper._ import com.typesafe.sbt.packager.docker.DockerPlugin.autoImport.{Docker, dockerRepository} import com.typesafe.sbt.packager.docker.{Cmd, ExecCmd} import org.knora.Dependencies + +import sbt._ import sbt.Keys.version +import sbt.librarymanagement.Resolver import scala.language.postfixOps import scala.sys.process.Process @@ -11,6 +15,8 @@ import scala.sys.process.Process // GLOBAL SETTINGS ////////////////////////////////////// +lazy val aggregatedProjects: Seq[ProjectReference] = Seq(webapi, sipi) + lazy val buildSettings = Seq( organization := "org.knora", version := (ThisBuild / version).value @@ -38,23 +44,48 @@ lazy val root: Project = Project(id = "root", file(".")) // use Ctrl-c to stop current task but not quit SBT Global / cancelable := true, publish / skip := true - // Dependencies.sysProps := sys.props.toString(), - // Dependencies.sysEnvs := sys.env.toString(), - // dockerImageCreationTask := Seq( - // (salsah1 / Docker / publishLocal).value, - // (webapi / Docker / publishLocal).value - // (knoraJenaFuseki / Docker / publishLocal).value, - // (knoraSipi / Docker / publishLocal).value - //) ) ////////////////////////////////////// -// WEBAPI (./webapi) +// DSP's custom SIPI ////////////////////////////////////// -import com.typesafe.sbt.SbtNativePackager.autoImport.NativePackagerHelper._ -import sbt._ -import sbt.librarymanagement.Resolver +lazy val sipi: Project = Project(id = "sipi", base = file("sipi")) + .enablePlugins(DockerPlugin) + .settings( + Compile / packageDoc / mappings := Seq(), + Compile / packageSrc / mappings := Seq(), + Docker / dockerRepository := Some("daschswiss"), + Docker / packageName := "knora-sipi", + dockerUpdateLatest := true, + dockerBaseImage := Dependencies.sipiImage, + Docker / maintainer := "support@dasch.swiss", + Docker / dockerExposedPorts ++= Seq(1024), + Docker / defaultLinuxInstallLocation := "/sipi", + Universal / mappings ++= { + // copy the sipi/scripts folder + directory("sipi/scripts") + }, + // use filterNot to return all items that do NOT meet the criteria + dockerCommands := dockerCommands.value.filterNot { + + // ExecCmd is a case class, and args is a varargs variable, so you need to bind it with @ + // remove ENTRYPOINT + case ExecCmd("ENTRYPOINT", args @ _*) => true + + // remove CMD + case ExecCmd("CMD", args @ _*) => true + + case Cmd("USER", args @ _*) => true + + // don't filter the rest; don't filter out anything that doesn't match a pattern + case cmd => false + } + ) + +////////////////////////////////////// +// WEBAPI (./webapi) +////////////////////////////////////// run / connectInput := true @@ -89,17 +120,10 @@ lazy val webapi: Project = Project(id = "webapi", base = file("webapi")) (rootBaseDir.value / "knora-ontologies" / "salsah-gui.ttl") -> "knora-ontologies/salsah-gui.ttl", (rootBaseDir.value / "knora-ontologies" / "standoff-data.ttl") -> "knora-ontologies/standoff-data.ttl", (rootBaseDir.value / "knora-ontologies" / "standoff-onto.ttl") -> "knora-ontologies/standoff-onto.ttl", - (rootBaseDir.value / "webapi" / "scripts" / "fuseki-knora-test-repository-config.ttl") -> "webapi/scripts/fuseki-knora-test-repository-config.ttl", - (rootBaseDir.value / "webapi" / "scripts" / "fuseki-knora-test-unit-repository-config.ttl") -> "webapi/scripts/fuseki-knora-test-unit-repository-config.ttl", - (rootBaseDir.value / "webapi" / "scripts" / "fuseki-repository-config.ttl.template") -> "webapi/scripts/fuseki-repository-config.ttl.template" + (rootBaseDir.value / "webapi" / "scripts" / "fuseki-repository-config.ttl.template") -> "webapi/scripts/fuseki-repository-config.ttl.template" // needed for initialization of triplestore ), - // contentOf("salsah1/src/main/resources").toMap.mapValues("config/" + _) - // (rootBaseDir.value / "knora-ontologies") -> "knora-ontologies", - // put additional files into the jar when running tests which are needed by testcontainers Test / packageBin / mappings ++= Seq( - (rootBaseDir.value / "sipi" / "config" / "sipi.init-knora.lua") -> "sipi/config/sipi.init-knora.lua", - (rootBaseDir.value / "sipi" / "config" / "sipi.knora-docker-config.lua") -> "sipi/config/sipi.knora-docker-config.lua", (rootBaseDir.value / "sipi" / "config" / "sipi.knora-docker-config.lua") -> "sipi/config/sipi.knora-docker-config.lua" ) ) @@ -132,6 +156,7 @@ lazy val webapi: Project = Project(id = "webapi", base = file("webapi")) // Skip packageDoc and packageSrc task on stage Compile / packageDoc / mappings := Seq(), Compile / packageSrc / mappings := Seq(), + // define folders inside container Universal / mappings ++= { // copy the scripts folder directory("webapi/scripts") ++ @@ -152,7 +177,15 @@ lazy val webapi: Project = Project(id = "webapi", base = file("webapi")) dockerBaseImage := "eclipse-temurin:11-jre-focal", Docker / maintainer := "support@dasch.swiss", Docker / dockerExposedPorts ++= Seq(3333), - Docker / defaultLinuxInstallLocation := "/opt/docker" + Docker / defaultLinuxInstallLocation := "/opt/docker", + // use filterNot to return all items that do NOT meet the criteria + dockerCommands := dockerCommands.value.filterNot { + // Remove USER command + case Cmd("USER", args @ _*) => true + + // don't filter the rest; don't filter out anything that doesn't match a pattern + case cmd => false + } ) .settings( buildInfoKeys ++= Seq[BuildInfoKey]( @@ -189,7 +222,6 @@ lazy val webapiJavaTestOptions = Seq( //"-XX:MaxMetaspaceSize=4096m" ) - lazy val apiMain = project .in(file("dsp-api-main")) .settings( @@ -199,7 +231,6 @@ lazy val apiMain = project ) .dependsOn(schemaCore, schemaRepo, schemaApi) - lazy val schemaApi = project .in(file("dsp-schema-api")) .settings( diff --git a/docker-compose.yml b/docker-compose.yml index 06aa495ae6..3df7a14509 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.7' services: db: - image: bazel/docker/knora-jena-fuseki:image + image: daschswiss/apache-jena-fuseki:2.0.8 # should be the same version as in Dependencies.scala ports: - "3030:3030" volumes: @@ -16,7 +16,8 @@ services: - JVM_ARGS=-Xmx3G sipi: - image: bazel/docker/knora-sipi:image + image: daschswiss/knora-sipi:latest + ports: - "1024:1024" volumes: diff --git a/docker/knora-jena-fuseki/BUILD.bazel b/docker/knora-jena-fuseki/BUILD.bazel deleted file mode 100644 index 857499dcfa..0000000000 --- a/docker/knora-jena-fuseki/BUILD.bazel +++ /dev/null @@ -1,34 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_push") - -# builds the docker image -container_image( - name = "image", - base = select({ - "@platforms//cpu:arm64": "@jenafuseki_arm64//image", - "//conditions:default": "@jenafuseki_amd64//image", - }), - labels = { - "MAINTAINER": "400790+subotic@users.noreply.github.com", - }, - ports = ["3030/tcp"], -) - -# push to dockerhub -container_push( - name = "push", - format = "Docker", - image = ":image", - registry = "index.docker.io", - repository = "daschswiss/knora-jena-fuseki", - tag = "{BUILD_SCM_TAG}", -) - -# use in targets needing an up-to-date docker image locally -#genrule( -# name = "build", -# srcs = [":image"], -# cmd = "docker load -i $(location //docker/knora-jena-fuseki:image) >$@", -# outs = ["build-output.txt"] -#) diff --git a/docker/knora-sipi/BUILD.bazel b/docker/knora-sipi/BUILD.bazel deleted file mode 100644 index a5e0618039..0000000000 --- a/docker/knora-sipi/BUILD.bazel +++ /dev/null @@ -1,41 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_push") -load("@io_bazel_rules_docker//contrib:test.bzl", "container_test") - -container_image( - name = "image", - base = "@sipi//image", - env = {}, - labels = { - "MAINTAINER": "400790+subotic@users.noreply.github.com", - }, - ports = ["1024/tcp"], - tars = [ - "//sipi/scripts:sipi-scripts", - ], -) - -container_push( - name = "push", - format = "Docker", - image = ":image", - registry = "index.docker.io", - repository = "daschswiss/knora-sipi", - tag = "{BUILD_SCM_TAG}", -) - -# use in targets needing an up-to-date docker image locally -#genrule( -# name = "build", -# srcs = [":image"], -# cmd = "docker load -i $(location //docker/knora-sipi:image) >$@", -# outs = ["build-output.txt"], -#) - -# for documentation of yaml, please see https://github.com/GoogleContainerTools/container-structure-test -container_test( - name = "sipi_image_test", - configs = ["sipi_image_test_config.yaml"], - image = ":image", -) diff --git a/docker/knora-sipi/sipi_image_test_config.yaml b/docker/knora-sipi/sipi_image_test_config.yaml deleted file mode 100644 index d4f64afe59..0000000000 --- a/docker/knora-sipi/sipi_image_test_config.yaml +++ /dev/null @@ -1,24 +0,0 @@ -schemaVersion: 2.0.0 - -metadataTest: - entrypoint: ['/sipi/sipi'] - cmd: [ - '--config=/sipi/config/sipi.config.lua' - ] - -fileExistenceTests: -- name: 'sipi.binary' - path: '/sipi/sipi' - shouldExist: true - -- name: 'sipi.config.lua' - path: '/sipi/config/sipi.config.lua' - shouldExist: true - -- name: 'sipi.init.lua' - path: '/sipi/config/sipi.init.lua' - shouldExist: true - -- name: 'test.html' - path: '/sipi/server/test.html' - shouldExist: true diff --git a/docs/05-internals/development/bazel.md b/docs/05-internals/development/bazel.md deleted file mode 100644 index 15119589cb..0000000000 --- a/docs/05-internals/development/bazel.md +++ /dev/null @@ -1,116 +0,0 @@ -# Bazel - -The following section discusses on how to build and run tests for Knora-API -with [Bazel](https://bazel.build). - -## Prerequisites -To install the Bazel build tool, follow these steps: - -``` -$ npm install -g @bazel/bazelisk -``` - -This will install [bazelisk](https://github.com/bazelbuild/bazelisk) which is -a wrapper to the `bazel` binary. It will, when the `bazel` command ir run, -automatically install the supported Bazel version, defined in the `.bazelversion` -file in the root of the `knora-api` repository. - -## Commands - -Build `webapi`: - -``` -# build webapi -$ bazel build //webapi/... - -# run all webapi tests -$ bazel test //webapi//... -``` - -## Build Structure - -The Bazel build is defined in a number of files: - - WORKSPACE - here are external dependencies defined - - BUILD - there are a number of BUILD files throughout the directory structure - where each represents a separate package responsible for everything underneath. - - *.bzl - custom extensions loaded and used in BUILD files - -For a more detailed discussion, please see the [Concepts and Terminology](https://docs.bazel.build/versions/master/build-ref.html) -section in the Bazel documentation. - -## Some Notes - -1. Override some `.bazelrc` settings in your own copy created at `~/.bazelrc`: - ``` - build --action_env=PATH="/usr/local/bin:/opt/local/bin:/usr/bin:/bin" - build --strategy=Scalac=worker - build --worker_sandboxing - query --package_path %workspace%:/usr/local/bin/bazel/base_workspace - startup --host_jvm_args=-Djavax.net.ssl.trustStore=/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/lib/security/cacerts \ - --host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit - ``` - -1. Add Bazel Plugin and Project to IntelliJ - 1. The latest version of the [Bazel plugin](https://plugins.jetbrains.com/plugin/8609-bazel/versions) - supports only IntelliJ upto version `2019.03.05`. After you make sure to - run this version of IntelliJ, install the plugin from inside IntelliJ. - 1. Click on `File -> Import Bazel Project` and select twice `next`. - 1. Uncomment the `Scala` language and click `Finish`. - -1. Run single spec: - ```bash - $ bazel test //webapi/src/test/scala/org/knora/webapi/e2e/v1:SearchV1R2RSpec - ``` - -1. Run single spec and only tests containing `gaga` in the description - ```bash - $ bazel test //webapi/src/test/scala/org/knora/webapi/e2e/v1:SearchV1R2RSpec --test_arg=-z --test_arg="gaga" - ``` - -1. Start Scala REPL - ```bash - $ bazel run //webapi:main_library_repl - ``` - -## Build stamping - -By default, Bazel tries not to include anything about the system state in build -outputs. However, released binaries and libraries often want to include -something like the version they were built at or the branch or tag they came -from. - -To reconcile this, Bazel has an option called the *workspace status command*. -This command is run outside of any sandboxes on the local machine, so it can -access anything about your source control, OS, or anything else you might want -to include. It then dumps its output into `bazel-out/volatile-status.txt`, which -you can use (and certain language rulesets provide support for accessing from code). - -Our *workspace status command* is defined in `//tools/buildstamp/get_workspace_status`. -To use it on every bazel command, we need to supply it to each Bazel invocation, -which is done by the following line found in `.bazelrc`: -``` -build --workspace_status_command=tools/buildstamp/get_workspace_status --stamp=yes -``` - -Any line added to `.bazelrc` is invoked on each corresponding command. - -The `//tools/buildstamp/get_workspace_status` emits additional values -to `bazel-out/volatile-status.txt` whereas `BUILD_TIMESTAMP` is emitted by -Bazel itself: - -``` -BUILD_SCM_REVISION 2d6df6c8fe2d56e3712eb26763f9727916a60164 -BUILD_SCM_STATUS Modified -BUILD_SCM_TAG v13.0.0-rc.21-17-g2d6df6c-dirty -BUILD_TIMESTAMP 1604401028 -``` - -The value of `BUILD_SCM_TAG` is used in `//webapi/src/main/scala/org/knora/webapi/http/version/versioninfo`, -which emits a JAR containing `VersionInfo.scala`. This file is generated based on -`VersionInfoTemplate.scala` found in the same Bazel package. - -In short, the `versioninfo` target producing the JAR library depends on -the `version_info_with_build_tag` target which emits the `VersionInfo.scala` -file which has the `{BUILD_TAG}` variable replaced by the current value of -`BUILD_SCM_TAG`. In an intermediary step, the `version_info_without_build_tag` -target, replaces variables coming from `//third_party:versions.bzl`. diff --git a/docs/05-internals/development/building-and-running.md b/docs/05-internals/development/building-and-running.md index 092b3c5e7b..37f558ee81 100644 --- a/docs/05-internals/development/building-and-running.md +++ b/docs/05-internals/development/building-and-running.md @@ -111,28 +111,11 @@ To run all test targets, use the following in the command line: $ make test ``` -To run only the dsp-api integration tests, use - -``` -$ make test-it -``` -To run only the dsp-api unit tests, use - -``` -$ make test-unit -``` - -Lastly, to run all dsp-api test, use - -``` -$ make test-webapi -``` - -As explained in the [bazel document](bazel.md), to run a single test from the command line, for example `SearchV1R2RSpec`, +To run a single test from the command line, for example `SearchV1R2RSpec`, run the following: ```bash - $ bazel test //webapi/src/test/scala/org/knora/webapi/e2e/v1:SearchV1R2RSpec + $ sbt " webapi / testOnly *SearchV1R2RSpec* " ``` _**Note:** to run tests, the api container must be stopped first!_ diff --git a/docs/05-internals/development/figures/import-bazel-project.png b/docs/05-internals/development/figures/import-bazel-project.png deleted file mode 100644 index 875db2ec724dde99a5709b353fe7fb61d76db66d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55644 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 a&ixB)Pad#cANm#m0000 -# Setup IntelliJ for development of Knora - -## Create an IntelliJ Project for Knora - - - Download and install a version of [IntelliJ IDEA](https://www.jetbrains.com/idea/) that [supports Bazel](https://plugins.jetbrains.com/plugin/8609-bazel/versions), eg. version `2019.03.05`. - - Follow the installation procedure and install the `Scala plugin` - -![screenshot 'Install Scala Plugin'](figures/install-scala-plugin.png) - - - Add Bazel Plugin: run InteliJ and install the plugin from inside IntelliJ. - - Create a project for Knora: restart InteliJ and create a project for Knora using `Import Bazel Project` option. - - ![screenshot 'Import Project'](figures/import-bazel-project.png) - - - Make sure that the Bazel `Workspace` points to the path of Knora and click `next`. - - ![screenshot 'Workspace'](figures/bazel-workspace.png) - - - Select the `Generate from BUILD file` option and give the path to the main `BUILD.bazel` file of Knora, click `next`. - - ![screenshot 'Bazel build'](figures/bazel-buildFile.png) - - - Uncomment the `Scala` language and click `Finish`. - - ![screenshot 'Bazel Scala'](figures/bazel-UncommentScala.png) - - At this point a `.ijwb` file is created for Knora project and added to the welcome screen of InteiJ. You can open the project by clicking on it. - - - Once the project is built and opened in InteliJ, make sure that project in synced with Bazel build files by clicking - on Bazel logo `Sync Project with Build Files`. This needs to be repeated every time there is a change in a `BUILD.bazel` file. - - ![screenshot 'Bazel sync'](figures/bazel-sync.png) +# Setup IntelliJ for development of DSP-API + +TODO add "Setup VS Code for development of DSP-API" + +## Create an IntelliJ Project for DSP-API + +TODO ## Setup IntelliJ Code Formatter @@ -47,43 +22,7 @@ In IntelliJ editor setting (`Preferences -> Editor -> Code Style -> Scala`), cho ## Use IntelliJ IDEA's Run/Debugger Configuration with Knora -First, you need to create an application configuration to run or debug a code. Here the configuration is explained using a test as an - example, but similarly the application configuration of InteliJ can be used for building the webapi. - -To run a specific test in a command line using Bazel, you would need to give the path of the test relative to its - package as defined in the `BUILD.bazel` of the package. For example, to run the test `GravsearchTypeInspectorSpec` in the - command line, you would need to enter `bazel test //webapi/src/test/scala/org/knora/webapi/messages/util/search:GravsearchTypeInspectorSpec`. - Now to run or debug the same test and its underlying code in InteliJ, a new configuration should be - set up: - - - Click on the 'Add Configuration' to create a new application configuration. - -![screenshot 'new_configuration'](figures/bazel-new-config.png) - - - Click on the `+` and choose `Bazel Command` - -![screenshot 'new_configuration'](figures/bazel-command-config.png) - - - Give the type of the command, i.e. `test` and the path parameter, as shown below. Then press `Apply`, and finish - the configuration by pressing `OK`. - -![screenshot 'configuration_setup'](figures/bazel-config-setup.png) - -After the configuration is completed, it will appear in a drop-down menu that shows all available configurations. - - - To run a configured command, eg. to run the test `GravsearchTypeInspectorSpec`, - 1. choose its configuration from the drop-down menu - 2. click on the `Run` symbol, the results will appear in the a `Run` window. Note that, before running the test, the - docker container of api should be stopped. - -![screenshot 'configuration_run'](figures/bazel-run-config.png) - - - To debug the code for example by executing a test: - 1. Click on a line-number to add a breakpoint. - 2. Choose the respective configuration from the drop-down menu. - 3. Click on the debugging symbol to start the application with a debugger attached, as shown below: - -![screenshot 'debug'](figures/bazel-debug.png) +TODO ## Profile Knora Using VisualVM in IntelliJ diff --git a/docs/05-internals/development/third-party.md b/docs/05-internals/development/third-party.md index 7fdf5de58d..7a85e81489 100644 --- a/docs/05-internals/development/third-party.md +++ b/docs/05-internals/development/third-party.md @@ -6,35 +6,7 @@ Third-party dependencies are defined in the `third_party` folder. There are two main types of dependencies: (1) Maven library dependencies and (2) Docker image versions. -## Maven Library Dependencies - -The Maven library dependencies are defined in the `third_party/dependencies.bzl` -file. To use the external libraries, add the "flattened" Bazel version of it to -the Bazel rule used to compile the code. - -Example of a "flattened" Bazel version looks as follows: - -- defined: `com.typesafe.akka:akka-actor_2.12:2.6.5` -- flattened: `@maven//:com_typesafe_akka_akka_actor_2_12` - -To query Bazel for all defined Maven dependencies: `bazel query @maven//:all | sort` - -### Manually Fetching Dependencies - -The Maven dependencies can be manually fetched with: -```bash -$ bazel fetch @maven//... -``` - -If there are any problems downloading the Maven dependencies, set the -`RJE_VERBOSE` environment variable to true to print `coursier`'s verbose output: -```bash -$ RJE_VERBOSE=true bazel fetch @maven//... -``` - -Note: If you are on macOS Big Sur and have the Cisco VPN client installed, -make sure that the packet filters are not active, or they may be a problem -downloading the dependencies. +TODO add documentation for Dependencies.scala ## Docker Image Versions diff --git a/knora-ontologies/BUILD b/knora-ontologies/BUILD deleted file mode 100644 index de243213f6..0000000000 --- a/knora-ontologies/BUILD +++ /dev/null @@ -1,20 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar") - -filegroup( - name = "knora-ontologies", - srcs = [ - "knora-admin.ttl", - "knora-base.ttl", - "salsah-gui.ttl", - "standoff-data.ttl", - "standoff-onto.ttl", - ], -) - -pkg_tar( - name = "tar", - srcs = [":knora-ontologies"], - package_dir = "knora-ontologies", -) diff --git a/mkdocs.yml b/mkdocs.yml index fc3ba747e1..005b756bf9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -108,7 +108,6 @@ nav: - Overview: 05-internals/development/overview.md - Build and Running: 05-internals/development/building-and-running.md - Setup IntelliJ for development of DSP-API: 05-internals/development/intellij-config.md - - Bazel Notes: 05-internals/development/bazel.md - Testing: 05-internals/development/testing.md - Docker Cheat Sheet: 05-internals/development/docker-cheat-sheet.md - Monitoring DSP-API: 05-internals/development/monitoring.md diff --git a/project/Dependencies.scala b/project/Dependencies.scala index e35066cc84..c15c3c9627 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -10,242 +10,246 @@ import sbt.{Def, _} object Dependencies { - val scalaVersion = "2.13.7" - val akkaVersion = "2.6.18" - val akkaHttpVersion = "10.2.8" - val jenaVersion = "4.4.0" - val metricsVersion = "4.0.1" - val sipiImage = "daschswiss/sipi:v3.3.4" - val fusekiImage = "daschswiss/apache-jena-fuseki:2.0.8" - - val ZioVersion = "2.0.0-RC2" - val ZioHttpVersion = "2.0.0-RC3" - val ZioJsonVersion = "0.3.0-RC3" - val ZioConfigVersion = "3.0.0-RC2" - val ZioSchemaVersion = "0.2.0-RC1-1" - val ZioLoggingVersion = "2.0.0-RC5" - val ZioZmxVersion = "2.0.0-M1" - val ZioPreludeVersion = "1.0.0-RC10" - - object Compile { - - // ZIO - val zio = "dev.zio" %% "zio" % ZioVersion - val zioHttp = "io.d11" %% "zhttp" % ZioHttpVersion - val zioJson = "dev.zio" %% "zio-json" % ZioJsonVersion - val zioPrelude = "dev.zio" %% "zio-prelude" % ZioPreludeVersion - val zioTest = "dev.zio" %% "zio-test" % ZioVersion % Test - val zioTestSbt = "dev.zio" %% "zio-test-sbt" % ZioVersion % Test - - // akka - val akkaActor = "com.typesafe.akka" %% "akka-actor" % akkaVersion - val akkaStream = "com.typesafe.akka" %% "akka-stream" % akkaVersion - val akkaSlf4j = "com.typesafe.akka" %% "akka-slf4j" % akkaVersion - val akkaProtobufV3 = "com.typesafe.akka" %% "akka-protobuf-v3" % akkaVersion - - // akka http - val akkaHttp = "com.typesafe.akka" %% "akka-http" % akkaHttpVersion - val akkaHttpXml = "com.typesafe.akka" %% "akka-http-xml" % akkaHttpVersion - val akkaHttpSprayJson = "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion - val akkaHttpJacksonJava = "com.typesafe.akka" %% "akka-http-jackson" % akkaHttpVersion - - val typesafeConfig = "com.typesafe" % "config" % "1.3.3" - - //CORS support - val akkaHttpCors = "ch.megard" %% "akka-http-cors" % "1.0.0" - - // jena - val jenaLibs = "org.apache.jena" % "apache-jena-libs" % jenaVersion - val jenaText = "org.apache.jena" % "jena-text" % jenaVersion - - // logging - val scalaLogging = "com.typesafe.scala-logging" %% "scala-logging" % "3.9.4" - val logbackClassic = "ch.qos.logback" % "logback-classic" % "1.2.10" - - // Metrics - val kamonCore = "io.kamon" %% "kamon-core" % "2.1.5" - val kamonScalaFuture = "io.kamon" %% "kamon-scala-future" % "2.1.5" - val kamonAkkaHttpd = "io.kamon" %% "kamon-akka-http" % "2.1.5" - val kamonPrometheus = "io.kamon" %% "kamon-prometheus" % "2.1.5" - val kamonLogback = "io.kamon" %% "kamon-logback" % "2.1.5" - val aspectJWeaver = "org.aspectj" % "aspectjweaver" % "1.9.4" - - // input validation - val commonsValidator = "commons-validator" % "commons-validator" % "1.6" exclude("commons-logging", "commons-logging") - - // authentication - val bcprov = "org.bouncycastle" % "bcprov-jdk15on" % "1.64" - val springSecurityCore = "org.springframework.security" % "spring-security-core" % "5.1.5.RELEASE" exclude("commons-logging", "commons-logging") exclude("org.springframework", "spring-aop") - val jwtSprayJson = "com.pauldijou" %% "jwt-spray-json" % "5.0.0" - - // caching - val ehcache = "net.sf.ehcache" % "ehcache" % "2.10.9.2" - val jedis = "redis.clients" % "jedis" % "3.1.0-m4" - // serialization - val chill = "com.twitter" %% "chill" % "0.9.5" - - // other - //"javax.transaction" % "transaction-api" % "1.1-rev-1", - val commonsText = "org.apache.commons" % "commons-text" % "1.6" - val commonsIo = "commons-io" % "commons-io" % "2.6" - val commonsBeanUtil = "commons-beanutils" % "commons-beanutils" % "1.9.3" exclude("commons-logging", "commons-logging") // not used by us, but need newest version to prevent this problem: http://stackoverflow.com/questions/14402745/duplicate-classes-in-commons-collections-and-commons-beanutils - val jodd = "org.jodd" % "jodd" % "3.2.6" - val jodaTime = "joda-time" % "joda-time" % "2.9.1" - val jodaConvert = "org.joda" % "joda-convert" % "1.8" - val diff = "com.sksamuel.diff" % "diff" % "1.1.11" - val xmlunitCore = "org.xmlunit" % "xmlunit-core" % "2.1.1" - - // other - val rdf4jClient = "org.eclipse.rdf4j" % "rdf4j-client" % "3.4.4" - val rdf4jRuntime = "org.eclipse.rdf4j" % "rdf4j-runtime" % "3.4.4" - val rdf4jStorage = "org.eclipse.rdf4j" % "rdf4j-storage" % "3.4.4" - val scallop = "org.rogach" %% "scallop" % "3.5.1" - val gwtServlet = "com.google.gwt" % "gwt-servlet" % "2.8.0" - val saxonHE = "net.sf.saxon" % "Saxon-HE" % "9.9.0-2" - - val scalaXml = "org.scala-lang.modules" %% "scala-xml" % "1.2.0" - - // provides akka jackson (json) support - val akkaHttpCirce = "de.heikoseeberger" %% "akka-http-circe" % "1.36.0" - val jacksonScala = "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.12.3" - - // swagger (api documentation) - val swaggerAkkaHttp = "com.github.swagger-akka-http" %% "swagger-akka-http" % "1.6.0" - - // Java EE modules which are deprecated in Java SE 9, 10 and will be removed in Java SE 11 - val jaxbApi = "javax.xml.bind" % "jaxb-api" % "2.2.12" - - val icu4j = "com.ibm.icu" % "icu4j" % "62.1" - - val apacheHttpClient = "org.apache.httpcomponents" % "httpclient" % "4.5.6" exclude("commons-logging", "commons-logging") - - // Graph for Scala "org.scala-graph:graph-core_2.13:1.13.1", - val scalaGraph = "org.scala-graph" %% "graph-core" % "1.13.1" - - // missing from current BAZEL setup - // "ch.qos.logback:logback-core:1.2.9", - val logbackCore = "ch.qos.logback" % "logback-core" % "1.2.9" - // "org.slf4j:log4j-over-slf4j:1.7.32", - val log4jOverSlf4j = "org.slf4j" % "log4j-over-slf4j" % "1.7.32" - // "org.slf4j:jcl-over-slf4j:1.7.32", - val jclOverSlf4j = "org.slf4j" % "jcl-over-slf4j" % "1.7.32" - // "org.slf4j:slf4j-api:1.7.32", - val slf4jApi = "org.slf4j" % "slf4j-api" % "1.7.32" - // "com.apicatalog:titanium-json-ld:1.2.0", - val titaniumJSONLD = "com.apicatalog" % "titanium-json-ld" % "1.2.0" - // "org.glassfish:jakarta.json:2.0.1", - val jakartaJSON = "org.glassfish" % "jakarta.json" % "2.0.1" - // "com.typesafe.play:twirl-api_2.13:1.5.1", - val twirlApi = "com.typesafe.play" %% "twirl-api" % "1.5.1" - // "junit:junit:4.13.2", - val junit = "junit" % "junit" % "4.13.2" - // "org.seleniumhq.selenium:selenium-support:3.141.59", - val seleniumSupport = "org.seleniumhq.selenium" % "selenium-support" % "3.141.59" - } - - object WebapiTest { - val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % akkaVersion % "test" - val akkaStreamTestkit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % "test" - val akkaHttpTestkit = "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % "test" - val scalaTest = "org.scalatest" %% "scalatest" % "3.2.2" % "test" - val gatlingHighcharts = "io.gatling.highcharts" % "gatling-charts-highcharts"% "3.7.5" % "test" - val gatlingTestFramework = "io.gatling" % "gatling-test-framework" % "3.2.1" % "test" - val testcontainers = "org.testcontainers" % "testcontainers" % "1.16.0" % "test" - } - - object TestBinaries { - val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % akkaVersion - val akkaStreamTestkit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion - val akkaHttpTestkit = "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion - val scalaTest = "org.scalatest" %% "scalatest" % "3.2.2" - val gatlingHighcharts = "io.gatling.highcharts" % "gatling-charts-highcharts"% "3.7.5" - val gatlingTestFramework = "io.gatling" % "gatling-test-framework" % "3.2.1" - } - - import Compile._ - - val l = libraryDependencies - - val webapiLibraryDependencies = l ++= Seq[sbt.ModuleID]( - akkaActor, - akkaHttp, - akkaHttpCirce, - akkaHttpCors, - akkaHttpJacksonJava, - akkaHttpSprayJson, - akkaHttpXml, - akkaProtobufV3, - akkaSlf4j, - akkaStream, - apacheHttpClient, - bcprov, - chill, - commonsBeanUtil, - commonsIo, - commonsText, - commonsValidator, - diff, - ehcache, - gwtServlet, - icu4j, - jacksonScala, - jaxbApi, - jedis, - jenaLibs, - jenaText, - jodaConvert, - jodaTime, - jodd, - jwtSprayJson, - kamonCore, - kamonLogback, - kamonPrometheus, - kamonScalaFuture, - logbackCore, - logbackClassic, - rdf4jClient, - rdf4jRuntime, - rdf4jStorage, - saxonHE, - scalaGraph, - scalaLogging, - scalaXml, - scallop, - springSecurityCore, - swaggerAkkaHttp, - titaniumJSONLD, - typesafeConfig, - WebapiTest.akkaHttpTestkit, - WebapiTest.akkaStreamTestkit, - WebapiTest.akkaTestkit, - WebapiTest.gatlingHighcharts, - WebapiTest.gatlingTestFramework, - WebapiTest.scalaTest, - WebapiTest.testcontainers, - xmlunitCore, - zio, - zioHttp, - zioJson, - zioPrelude, - zioTest, - zioTestSbt, - log4jOverSlf4j, - jclOverSlf4j, - slf4jApi, - jakartaJSON, - twirlApi, - junit, - seleniumSupport - ) - - val upgradeLibraryDependencies = l ++= Seq[sbt.ModuleID]( - rdf4jRuntime, - scallop - ) - - val webapiTestAndITLibraryDependencies = l ++= Seq[sbt.ModuleID]( - TestBinaries.gatlingHighcharts, - TestBinaries.gatlingTestFramework, - TestBinaries.scalaTest - ) + val scalaVersion = "2.13.7" + val akkaVersion = "2.6.18" + val akkaHttpVersion = "10.2.8" + val jenaVersion = "4.4.0" + val metricsVersion = "4.0.1" + val sipiImage = "daschswiss/sipi:3.3.4" // base image the knora-sipi image is created from + val fusekiImage = "daschswiss/apache-jena-fuseki:2.0.8" // should be the same version as in docker-compose.yml + + val ZioVersion = "2.0.0-RC2" + val ZioHttpVersion = "2.0.0-RC3" + val ZioJsonVersion = "0.3.0-RC3" + val ZioConfigVersion = "3.0.0-RC2" + val ZioSchemaVersion = "0.2.0-RC1-1" + val ZioLoggingVersion = "2.0.0-RC5" + val ZioZmxVersion = "2.0.0-M1" + val ZioPreludeVersion = "1.0.0-RC10" + + object Compile { + + // ZIO + val zio = "dev.zio" %% "zio" % ZioVersion + val zioHttp = "io.d11" %% "zhttp" % ZioHttpVersion + val zioJson = "dev.zio" %% "zio-json" % ZioJsonVersion + val zioPrelude = "dev.zio" %% "zio-prelude" % ZioPreludeVersion + val zioTest = "dev.zio" %% "zio-test" % ZioVersion % Test + val zioTestSbt = "dev.zio" %% "zio-test-sbt" % ZioVersion % Test + + // akka + val akkaActor = "com.typesafe.akka" %% "akka-actor" % akkaVersion + val akkaStream = "com.typesafe.akka" %% "akka-stream" % akkaVersion + val akkaSlf4j = "com.typesafe.akka" %% "akka-slf4j" % akkaVersion + val akkaProtobufV3 = "com.typesafe.akka" %% "akka-protobuf-v3" % akkaVersion + + // akka http + val akkaHttp = "com.typesafe.akka" %% "akka-http" % akkaHttpVersion + val akkaHttpXml = "com.typesafe.akka" %% "akka-http-xml" % akkaHttpVersion + val akkaHttpSprayJson = "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion + val akkaHttpJacksonJava = "com.typesafe.akka" %% "akka-http-jackson" % akkaHttpVersion + + val typesafeConfig = "com.typesafe" % "config" % "1.3.3" + + //CORS support + val akkaHttpCors = "ch.megard" %% "akka-http-cors" % "1.0.0" + + // jena + val jenaLibs = "org.apache.jena" % "apache-jena-libs" % jenaVersion + val jenaText = "org.apache.jena" % "jena-text" % jenaVersion + + // logging + val scalaLogging = "com.typesafe.scala-logging" %% "scala-logging" % "3.9.4" + val logbackClassic = "ch.qos.logback" % "logback-classic" % "1.2.10" + + // Metrics + val kamonCore = "io.kamon" %% "kamon-core" % "2.1.5" + val kamonScalaFuture = "io.kamon" %% "kamon-scala-future" % "2.1.5" + val kamonAkkaHttpd = "io.kamon" %% "kamon-akka-http" % "2.1.5" + val kamonPrometheus = "io.kamon" %% "kamon-prometheus" % "2.1.5" + val kamonLogback = "io.kamon" %% "kamon-logback" % "2.1.5" + val aspectJWeaver = "org.aspectj" % "aspectjweaver" % "1.9.4" + + // input validation + val commonsValidator = + "commons-validator" % "commons-validator" % "1.6" exclude ("commons-logging", "commons-logging") + + // authentication + val bcprov = "org.bouncycastle" % "bcprov-jdk15on" % "1.64" + val springSecurityCore = + "org.springframework.security" % "spring-security-core" % "5.1.5.RELEASE" exclude ("commons-logging", "commons-logging") exclude ("org.springframework", "spring-aop") + val jwtSprayJson = "com.pauldijou" %% "jwt-spray-json" % "5.0.0" + + // caching + val ehcache = "net.sf.ehcache" % "ehcache" % "2.10.9.2" + val jedis = "redis.clients" % "jedis" % "3.1.0-m4" + // serialization + val chill = "com.twitter" %% "chill" % "0.9.5" + + // other + //"javax.transaction" % "transaction-api" % "1.1-rev-1", + val commonsText = "org.apache.commons" % "commons-text" % "1.6" + val commonsIo = "commons-io" % "commons-io" % "2.6" + val commonsBeanUtil = + "commons-beanutils" % "commons-beanutils" % "1.9.3" exclude ("commons-logging", "commons-logging") // not used by us, but need newest version to prevent this problem: http://stackoverflow.com/questions/14402745/duplicate-classes-in-commons-collections-and-commons-beanutils + val jodd = "org.jodd" % "jodd" % "3.2.6" + val jodaTime = "joda-time" % "joda-time" % "2.9.1" + val jodaConvert = "org.joda" % "joda-convert" % "1.8" + val diff = "com.sksamuel.diff" % "diff" % "1.1.11" + val xmlunitCore = "org.xmlunit" % "xmlunit-core" % "2.1.1" + + // other + val rdf4jClient = "org.eclipse.rdf4j" % "rdf4j-client" % "3.4.4" + val rdf4jRuntime = "org.eclipse.rdf4j" % "rdf4j-runtime" % "3.4.4" + val rdf4jStorage = "org.eclipse.rdf4j" % "rdf4j-storage" % "3.4.4" + val scallop = "org.rogach" %% "scallop" % "3.5.1" + val gwtServlet = "com.google.gwt" % "gwt-servlet" % "2.8.0" + val saxonHE = "net.sf.saxon" % "Saxon-HE" % "9.9.0-2" + + val scalaXml = "org.scala-lang.modules" %% "scala-xml" % "1.2.0" + + // provides akka jackson (json) support + val akkaHttpCirce = "de.heikoseeberger" %% "akka-http-circe" % "1.36.0" + val jacksonScala = "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.12.3" + + // swagger (api documentation) + val swaggerAkkaHttp = "com.github.swagger-akka-http" %% "swagger-akka-http" % "1.6.0" + + // Java EE modules which are deprecated in Java SE 9, 10 and will be removed in Java SE 11 + val jaxbApi = "javax.xml.bind" % "jaxb-api" % "2.2.12" + + val icu4j = "com.ibm.icu" % "icu4j" % "62.1" + + val apacheHttpClient = + "org.apache.httpcomponents" % "httpclient" % "4.5.6" exclude ("commons-logging", "commons-logging") + + // Graph for Scala "org.scala-graph:graph-core_2.13:1.13.1", + val scalaGraph = "org.scala-graph" %% "graph-core" % "1.13.1" + + // missing from current BAZEL setup + // "ch.qos.logback:logback-core:1.2.9", + val logbackCore = "ch.qos.logback" % "logback-core" % "1.2.9" + // "org.slf4j:log4j-over-slf4j:1.7.32", + val log4jOverSlf4j = "org.slf4j" % "log4j-over-slf4j" % "1.7.32" + // "org.slf4j:jcl-over-slf4j:1.7.32", + val jclOverSlf4j = "org.slf4j" % "jcl-over-slf4j" % "1.7.32" + // "org.slf4j:slf4j-api:1.7.32", + val slf4jApi = "org.slf4j" % "slf4j-api" % "1.7.32" + // "com.apicatalog:titanium-json-ld:1.2.0", + val titaniumJSONLD = "com.apicatalog" % "titanium-json-ld" % "1.2.0" + // "org.glassfish:jakarta.json:2.0.1", + val jakartaJSON = "org.glassfish" % "jakarta.json" % "2.0.1" + // "com.typesafe.play:twirl-api_2.13:1.5.1", + val twirlApi = "com.typesafe.play" %% "twirl-api" % "1.5.1" + // "junit:junit:4.13.2", + val junit = "junit" % "junit" % "4.13.2" + // "org.seleniumhq.selenium:selenium-support:3.141.59", + val seleniumSupport = "org.seleniumhq.selenium" % "selenium-support" % "3.141.59" + } + + object WebapiTest { + val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % akkaVersion % "test" + val akkaStreamTestkit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % "test" + val akkaHttpTestkit = "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % "test" + val scalaTest = "org.scalatest" %% "scalatest" % "3.2.2" % "test" + val gatlingHighcharts = "io.gatling.highcharts" % "gatling-charts-highcharts" % "3.7.5" % "test" + val gatlingTestFramework = "io.gatling" % "gatling-test-framework" % "3.2.1" % "test" + val testcontainers = "org.testcontainers" % "testcontainers" % "1.16.0" % "test" + } + + object TestBinaries { + val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % akkaVersion + val akkaStreamTestkit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion + val akkaHttpTestkit = "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion + val scalaTest = "org.scalatest" %% "scalatest" % "3.2.2" + val gatlingHighcharts = "io.gatling.highcharts" % "gatling-charts-highcharts" % "3.7.5" + val gatlingTestFramework = "io.gatling" % "gatling-test-framework" % "3.2.1" + } + + import Compile._ + + val l = libraryDependencies + + val webapiLibraryDependencies = l ++= Seq[sbt.ModuleID]( + akkaActor, + akkaHttp, + akkaHttpCirce, + akkaHttpCors, + akkaHttpJacksonJava, + akkaHttpSprayJson, + akkaHttpXml, + akkaProtobufV3, + akkaSlf4j, + akkaStream, + apacheHttpClient, + bcprov, + chill, + commonsBeanUtil, + commonsIo, + commonsText, + commonsValidator, + diff, + ehcache, + gwtServlet, + icu4j, + jacksonScala, + jaxbApi, + jedis, + jenaLibs, + jenaText, + jodaConvert, + jodaTime, + jodd, + jwtSprayJson, + kamonCore, + kamonLogback, + kamonPrometheus, + kamonScalaFuture, + logbackCore, + logbackClassic, + rdf4jClient, + rdf4jRuntime, + rdf4jStorage, + saxonHE, + scalaGraph, + scalaLogging, + scalaXml, + scallop, + springSecurityCore, + swaggerAkkaHttp, + titaniumJSONLD, + typesafeConfig, + WebapiTest.akkaHttpTestkit, + WebapiTest.akkaStreamTestkit, + WebapiTest.akkaTestkit, + WebapiTest.gatlingHighcharts, + WebapiTest.gatlingTestFramework, + WebapiTest.scalaTest, + WebapiTest.testcontainers, + xmlunitCore, + zio, + zioHttp, + zioJson, + zioPrelude, + zioTest, + zioTestSbt, + log4jOverSlf4j, + jclOverSlf4j, + slf4jApi, + jakartaJSON, + twirlApi, + junit, + seleniumSupport + ) + + val upgradeLibraryDependencies = l ++= Seq[sbt.ModuleID]( + rdf4jRuntime, + scallop + ) + + val webapiTestAndITLibraryDependencies = l ++= Seq[sbt.ModuleID]( + TestBinaries.gatlingHighcharts, + TestBinaries.gatlingTestFramework, + TestBinaries.scalaTest + ) } diff --git a/sipi/Makefile b/sipi/Makefile deleted file mode 100644 index b0809f1fb1..0000000000 --- a/sipi/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -include ../vars.mk - -.PHONY: print-env-file -print-env-file: env-file ## prints the env file used by sipi - @cat .env - -.PHONY: env-file -env-file: ## write the env file used by sipi - @echo DOCKERHOST=$(DOCKERHOST) > .env - -.PHONY: up -up: env-file ## start sipi - docker-compose up -d sipi - -.PHONY: logs -logs: env-file ## follow logs - docker-compose logs -f sipi - -.PHONY: down -down: env-file ## stop sipi - docker-compose down - -.PHONY: help -help: ## this help - @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort - -.DEFAULT_GOAL := help diff --git a/sipi/README.md b/sipi/README.md deleted file mode 100644 index add1dfd426..0000000000 --- a/sipi/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Knora Specific Sipi Scripts and Configurations - -This directory holds Knora specific scripts and configurations for [Sipi](https://github.com/dhlab-basel/Sipi). - -## Usage - -### With Docker - -To start Sipi using Docker (with config for integration tests), run from inside this folder: - -``` -$ make up -$ make down // for cleanup -``` - -### Using a Locally-Compiled Sipi - -Type the following in this directory, assuming that the Sipi source tree is in -`../../Sipi` and the Sipi binary is in the build folder under `../../Sipi/build/sipi`: - -``` -$ ../../Sipi/build/sipi --config config/sipi.knora-local-config.lua -``` - -### Starting Sipi with `no-auth` configuration - -The `no-auth` configuration omits authorization callbacks to Knora, thus allowing to serve images for -which there is no corresponding resource inside Knora. - -``` -$ export DOCKERHOST=LOCAL_IP_ADDRESS -$ docker image rm --force daschswiss/sipi:main // deletes cached image and needs only to be used when newer image is available on dockerhub -$ docker-compose up sipi-no-auth -$ docker-compose down // for cleanup -``` - -where `LOCAL_IP_ADDRESS` is the IP of the host running the `Knora-Service`. \ No newline at end of file diff --git a/sipi/config/BUILD.bazel b/sipi/config/BUILD.bazel deleted file mode 100644 index 02ef9a1651..0000000000 --- a/sipi/config/BUILD.bazel +++ /dev/null @@ -1,11 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "config", - srcs = [ - "sipi.knora-docker-config.lua", - "sipi.knora-docker-no-auth-config.lua", - "sipi.knora-docker-test-config.lua", - "sipi.knora-local-config.lua", - ], -) diff --git a/sipi/docker-compose.yml b/sipi/docker-compose.yml deleted file mode 100644 index 55b59ac146..0000000000 --- a/sipi/docker-compose.yml +++ /dev/null @@ -1,46 +0,0 @@ -version: '3' - -services: - # sipi using default (production-like) configuration with additional routes for testing - sipi: - image: bazel/docker/knora-sipi:image - container_name: sipi - ports: - - "1024:1024" - volumes: - - $PWD/config:/sipi/config - - $PWD/scripts:/sipi/scripts - - /tmp:/tmp - - $HOME:$HOME - - $PWD/images:/sipi/images - - $PWD/server:/sipi/server - extra_hosts: - - api:${DOCKERHOST} - restart: unless-stopped - environment: - - SIPI_EXTERNAL_PROTOCOL=http - - SIPI_EXTERNAL_HOSTNAME=0.0.0.0 - - SIPI_EXTERNAL_PORT=1024 - command: --config=/sipi/config/sipi.knora-docker-config.lua - - # sipi using configuration which disables authentication - sipi-no-auth: - image: bazel/docker/knora-sipi:image - container_name: sipi-no-auth - ports: - - "1024:1024" - volumes: - - $PWD/config:/sipi/config - - $PWD/scripts:/sipi/scripts - - /tmp:/tmp - - $HOME:$HOME - - $PWD/images:/sipi/images - - $PWD/server:/sipi/server - extra_hosts: - - api:${DOCKERHOST} - restart: unless-stopped - environment: - - SIPI_EXTERNAL_PROTOCOL=http - - SIPI_EXTERNAL_HOSTNAME=0.0.0.0 - - SIPI_EXTERNAL_PORT=1024 - command: --config=/sipi/config/sipi.knora-docker-no-auth-config.lua diff --git a/sipi/scripts/BUILD.bazel b/sipi/scripts/BUILD.bazel deleted file mode 100644 index 10d414589e..0000000000 --- a/sipi/scripts/BUILD.bazel +++ /dev/null @@ -1,36 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar") - -filegroup( - name = "scripts", - srcs = [ - "admin_upload.lua", - "cache.lua", - "clean_temp_dir.lua", - "debug.lua", - "delete_temp_file.lua", - "exit.lua", - "file_info.lua", - "get_knora_session.lua", - "jwt.lua", - "send_response.lua", - "sipi.init-knora.lua", - "sipi.init-knora-no-auth.lua", - "sipi.init-knora-test.lua", - "store.lua", - "test1.lua", - "test2.lua", - "test_file_info.lua", - "test_functions.lua", - "test_knora_session_cookie.lua", - "upload.lua", - "util.lua", - ], -) - -pkg_tar( - name = "sipi-scripts", - srcs = [":scripts"], - package_dir = "/sipi/scripts", -) diff --git a/test_data/BUILD.bazel b/test_data/BUILD.bazel deleted file mode 100644 index c5aa1c105b..0000000000 --- a/test_data/BUILD.bazel +++ /dev/null @@ -1,6 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "test_data", - srcs = glob(["**"]), -) diff --git a/test_data/upgrade/BUILD.bazel b/test_data/upgrade/BUILD.bazel deleted file mode 100644 index d2d7311255..0000000000 --- a/test_data/upgrade/BUILD.bazel +++ /dev/null @@ -1,14 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "upgrade", - srcs = [ - "pr1307.trig", - "pr1322.trig", - "pr1367.trig", - "pr1372.trig", - "pr1615.trig", - "pr1746.trig", - "pr1921.trig", - ], -) diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/third_party/versions.bzl b/third_party/versions.bzl deleted file mode 100644 index 2dd28e18fb..0000000000 --- a/third_party/versions.bzl +++ /dev/null @@ -1,17 +0,0 @@ -"""Primary location for setting Knora-API project wide versions""" - -SCALA_VERSION = "2.13.7" -AKKA_VERSION = "2.6.17" -AKKA_HTTP_VERSION = "10.2.4" -JENA_VERSION = "4.4.0" -METRICS_VERSION = "4.0.1" - -# SIPI - digest takes precedence! -SIPI_REPOSITORY = "daschswiss/sipi" -SIPI_IMAGE_DIGEST = "sha256:235afabf427d4e8619d10f3858ab63b6c26809ef27184f69951e098f005faa02" # 3.3.4 - -# Jena Fuseki - digest takes precedence! -FUSEKI_REPOSITORY = "daschswiss/apache-jena-fuseki" -FUSEKI_VERSION = "2.0.8" # contains Fuseki 4.4.0 (with log4j 2.17.1) -FUSEKI_IMAGE_DIGEST_AMD64 = "sha256:41e9d9608bea994f308edde27114f05f861f60c458bf64bf9c42b0d4a9799c6b" -FUSEKI_IMAGE_DIGEST_ARM64 = "sha256:14b6771e154f3a9cc7ca2894b5f58b47da1287ae0cfb60b96ec073ce56cdbed2" diff --git a/toolchains/BUILD.bazel b/toolchains/BUILD.bazel deleted file mode 100644 index 3fead820a5..0000000000 --- a/toolchains/BUILD.bazel +++ /dev/null @@ -1,22 +0,0 @@ -load("@io_bazel_rules_scala//scala:scala_toolchain.bzl", "scala_toolchain") - -# scalac options like in KnoraBuild.sbt (warn-unused is added, as it seems good) -scala_toolchain( - name = "dsp_api_toolchain_impl", - scalacopts = [ - "-Ywarn-unused", - "-feature", - "-unchecked", - "-deprecation", - "-Yresolve-term-conflict:package", - ], - unused_dependency_checker_mode = "off", - visibility = ["//visibility:public"], -) - -toolchain( - name = "dsp_api_scala_toolchain", - toolchain = "dsp_api_toolchain_impl", - toolchain_type = "@io_bazel_rules_scala//scala:toolchain_type", - visibility = ["//visibility:public"], -) diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel deleted file mode 100644 index 143146ec00..0000000000 --- a/tools/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "all", - srcs = [ - "//tools/buildstamp:all", - ], -) - -filegroup( - name = "srcs", - srcs = [ - "//tools/buildstamp:srcs", - ], -) diff --git a/tools/buildstamp/BUILD.bazel b/tools/buildstamp/BUILD.bazel deleted file mode 100644 index 0ec5e6692d..0000000000 --- a/tools/buildstamp/BUILD.bazel +++ /dev/null @@ -1,17 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -# bring our version constants in -load("//third_party:versions.bzl", "AKKA_HTTP_VERSION", "AKKA_VERSION", "FUSEKI_VERSION", "SCALA_VERSION", "SIPI_VERSION") -load("@io_bazel_rules_scala//scala:scala.bzl", "scala_library") - -filegroup( - name = "all", - srcs = [ - "get_workspace_status", - ], -) - -filegroup( - name = "srcs", - srcs = glob(["**"]), -) diff --git a/tools/buildstamp/get_workspace_status b/tools/buildstamp/get_workspace_status deleted file mode 100755 index 774559abd0..0000000000 --- a/tools/buildstamp/get_workspace_status +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -# This script will be run bazel when building process starts to -# generate key-value information that represents the status of the -# workspace. The output should be like -# -# KEY1 VALUE1 -# KEY2 VALUE2 -# -# If the script exits with non-zero code, it's considered as a failure -# and the output will be discarded. - -# The code below presents an implementation that works for git repository -git_rev=$(git rev-parse HEAD) -if [[ $? != 0 ]]; -then - exit 1 -fi -echo "BUILD_SCM_REVISION ${git_rev}" - -# Check whether there are any uncommitted changes -git diff-index --quiet HEAD -- -if [[ $? == 0 ]]; -then - tree_status="Clean" -else - tree_status="Modified" -fi -echo "BUILD_SCM_STATUS ${tree_status}" - -# Emit the git tag -git_tag=$(git describe --tag --dirty --abbrev=7) -if [[ $? != 0 ]]; -then - git_tag=${git_rev} -fi -echo "BUILD_SCM_TAG ${git_tag}" diff --git a/webapi/README.md b/webapi/README.md deleted file mode 100644 index 23d31589b1..0000000000 --- a/webapi/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Performance measuring: - --Install docker --Install statsd, kamon, grafana: https://github.com/kamon-io/docker-grafana-graphite diff --git a/webapi/_assets/icons/bild.png b/webapi/_assets/icons/bild.png deleted file mode 100644 index b5c1be683e237f198506618239d62551154105dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3333 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 PRwaidWc+Lb92l$t`ExaR diff --git a/webapi/_assets/icons/incunabula_logo.png b/webapi/_assets/icons/incunabula_logo.png deleted file mode 100644 index 8335a15ec9d5d0198d27b5fbf0ca2474d3dbca77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38267 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 diff --git a/webapi/_assets/icons/person.png b/webapi/_assets/icons/person.png deleted file mode 100644 index d9ac9de9bc9a7d860f8b5978726b07a8ffe35660..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 830 zcmV-E1Ht@>P)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ;#7RU!RCwB?lS^z=br{8e-~Zm3PUq1MPJ>`X-n5#EiU>smk&SUjAjUug3)F;_ zi7`eux^Q8lD<2`o4FX|7h>3<^7eu3OG!{+zpft2)I_=QMOz%|YJ@@&)E@&M0J;}+p zJKs4uITD5;>w#jOFah2@_XYr=)-2BFUh$mPJHGE92vEh&MBqn_6v5ScC*%WaJ&FSGIiUz(j_r*o3@l&K2;~TLsaBN z5dB{S%d)U6i>2k|lgcz0Ja&jsgqG`3T&<~SDkVn-dfBo$gBkhai8D*K<`OMc1X*60i)lQ};B@GPgb&(P1eO5fg?uoAIYTflZ*lv22X zUg%DzG2@TW|MUi)I~2nX;E%Ccj7%@0ZJs$0ee|S#)z0~4D}D=)AOer zL5yf;97J*br@z^`?J+u13F^hlOg^8xF?wf_SXZW9g$b!@2P0n;NS@!tpBKhSP20H9 zPF@<$Qcp!EE(PAjmR-AF$<9px9by32`aXW&sWd+m5kw&HHThj}HqJIlib4y7VMsEW zynbT(qt^fpgg|I0kgP7u_aq)IIi_m1lsL9Q5Ggr!5S7)csqa+`_pbugtG{_;Ur$zN zR|W@;>BNq1=H?a07*qo IM6N<$f*Ui1zW@LL diff --git a/webapi/src/main/scala/org/knora/webapi/http/version/ServerVersion.scala b/webapi/src/main/scala/org/knora/webapi/http/version/ServerVersion.scala index 2e2b2951c8..0690d87ea6 100644 --- a/webapi/src/main/scala/org/knora/webapi/http/version/ServerVersion.scala +++ b/webapi/src/main/scala/org/knora/webapi/http/version/ServerVersion.scala @@ -15,7 +15,6 @@ import akka.http.scaladsl.server.Route */ object ServerVersion { - // FIXME: Revert as soon as we remove Bazel (not before) private val ApiNameAndVersion = s"${BuildInfo.name}/${BuildInfo.version}" private val AkkaNameAndVersion = s"akka-http/${BuildInfo.akkaHttp}" private val AllProducts = ApiNameAndVersion + " " + AkkaNameAndVersion diff --git a/webapi/src/test/scala/org/knora/webapi/E2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/E2ESpec.scala index 91e7dd38b6..a842650b1f 100644 --- a/webapi/src/test/scala/org/knora/webapi/E2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/E2ESpec.scala @@ -175,8 +175,6 @@ class E2ESpec(_system: ActorSystem) /** * Reads or writes a test data file. - * The written test data files can be found under: - * ./bazel-out/darwin-fastbuild/testlogs///test.outputs/outputs.zip * * @param responseAsString the API response received from Knora. * @param file the file in which the expected API response is stored. @@ -185,9 +183,7 @@ class E2ESpec(_system: ActorSystem) */ protected def readOrWriteTextFile(responseAsString: String, file: Path, writeFile: Boolean = false): String = if (writeFile) { - // Per default only read access is allowed in the bazel sandbox. - // This workaround allows to save test output. - val testOutputDir: Path = Paths.get(sys.env("TEST_UNDECLARED_OUTPUTS_DIR")) + val testOutputDir = Paths.get("..", "test_data", "ontologyR2RV2") val newOutputFile = testOutputDir.resolve(file) Files.createDirectories(newOutputFile.getParent) FileUtil.writeTextFile( @@ -198,18 +194,18 @@ class E2ESpec(_system: ActorSystem) } else { FileUtil.readTextFile(file).replaceAll("IIIF_BASE_URL", settings.externalSipiIIIFGetUrl) } - + private def createTmpFileDir(): Unit = { - // check if tmp datadir exists and create it if not - val tmpFileDir = Path.of(settings.tmpDataDir) - - if (!Files.exists(tmpFileDir)) { - try { - Files.createDirectories(tmpFileDir) - } catch { - case e: Throwable => - throw FileWriteException(s"Tmp data directory ${settings.tmpDataDir} could not be created: ${e.getMessage}") - } + // check if tmp datadir exists and create it if not + val tmpFileDir = Path.of(settings.tmpDataDir) + + if (!Files.exists(tmpFileDir)) { + try { + Files.createDirectories(tmpFileDir) + } catch { + case e: Throwable => + throw FileWriteException(s"Tmp data directory ${settings.tmpDataDir} could not be created: ${e.getMessage}") } } + } } diff --git a/webapi/src/test/scala/org/knora/webapi/R2RSpec.scala b/webapi/src/test/scala/org/knora/webapi/R2RSpec.scala index dff30ad708..f6e835dfd6 100644 --- a/webapi/src/test/scala/org/knora/webapi/R2RSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/R2RSpec.scala @@ -145,8 +145,6 @@ class R2RSpec /** * Reads or writes a test data file. - * The written test data files can be found under: - * ./bazel-out/darwin-fastbuild/testlogs///test.outputs/outputs.zip * * @param responseAsString the API response received from Knora. * @param file the file in which the expected API response is stored. @@ -155,9 +153,7 @@ class R2RSpec */ protected def readOrWriteTextFile(responseAsString: String, file: Path, writeFile: Boolean = false): String = if (writeFile) { - // Per default only read access is allowed in the bazel sandbox. - // This workaround allows to save test output. - val testOutputDir: Path = Paths.get(sys.env("TEST_UNDECLARED_OUTPUTS_DIR")) + val testOutputDir = Paths.get("..", "test_data", "ontologyR2RV2") val newOutputFile = testOutputDir.resolve(file) Files.createDirectories(newOutputFile.getParent) FileUtil.writeTextFile( diff --git a/webapi/src/test/scala/org/knora/webapi/TestContainerFuseki.scala b/webapi/src/test/scala/org/knora/webapi/TestContainerFuseki.scala index 0192066239..68cd9aedca 100644 --- a/webapi/src/test/scala/org/knora/webapi/TestContainerFuseki.scala +++ b/webapi/src/test/scala/org/knora/webapi/TestContainerFuseki.scala @@ -10,13 +10,14 @@ import org.testcontainers.containers.GenericContainer import org.testcontainers.utility.DockerImageName import scala.jdk.CollectionConverters._ +import org.knora.webapi.http.version.BuildInfo /** * Provides the Fuseki container necessary for running tests. */ object TestContainerFuseki { - val FusekiImageName: DockerImageName = DockerImageName.parse("bazel/docker/knora-jena-fuseki:image") + val FusekiImageName: DockerImageName = DockerImageName.parse(BuildInfo.fuseki) val FusekiContainer = new GenericContainer(FusekiImageName) FusekiContainer.withExposedPorts(3030) diff --git a/webapi/src/test/scala/org/knora/webapi/TestContainersAll.scala b/webapi/src/test/scala/org/knora/webapi/TestContainersAll.scala index 234880a3cf..8bff7ac0b1 100644 --- a/webapi/src/test/scala/org/knora/webapi/TestContainersAll.scala +++ b/webapi/src/test/scala/org/knora/webapi/TestContainersAll.scala @@ -12,6 +12,7 @@ import org.testcontainers.containers.{BindMode, GenericContainer} import org.testcontainers.utility.DockerImageName import scala.jdk.CollectionConverters._ +import org.knora.webapi.http.version.BuildInfo /** * Provides all containers necessary for running tests. @@ -25,14 +26,14 @@ object TestContainersAll { .headOption .getOrElse(throw new UnknownHostException("No suitable network interface found")) - val FusekiImageName: DockerImageName = DockerImageName.parse("bazel/docker/knora-jena-fuseki:image") + val FusekiImageName: DockerImageName = DockerImageName.parse(BuildInfo.fuseki) val FusekiContainer = new GenericContainer(FusekiImageName) FusekiContainer.withExposedPorts(3030) FusekiContainer.withEnv("ADMIN_PASSWORD", "test") FusekiContainer.withEnv("JVM_ARGS", "-Xmx3G") FusekiContainer.start() - val SipiImageName: DockerImageName = DockerImageName.parse("bazel/docker/knora-sipi:image") + val SipiImageName: DockerImageName = DockerImageName.parse(s"daschswiss/knora-sipi:${BuildInfo.version}") val SipiContainer = new GenericContainer(SipiImageName) SipiContainer.withExposedPorts(1024) SipiContainer.withEnv("SIPI_EXTERNAL_PROTOCOL", "http") diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala index 5f51ea37cc..8be835b2b5 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala @@ -60,7 +60,7 @@ class OntologyV2R2RSpec extends R2RSpec { // If true, the existing expected response files are overwritten with the HTTP GET responses from the server. // If false, the responses from the server are compared to the contents fo the expected response files. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - private val writeTestDataFiles = false + private val writeTestDataFiles = true override lazy val rdfDataObjects = List( RdfDataObject( @@ -118,7 +118,7 @@ class OntologyV2R2RSpec extends R2RSpec { ) { def makeFile(mediaType: MediaType.NonBinary): Path = { val fileSuffix = mediaType.fileExtensions.head - Paths.get("..", s"test_data/ontologyR2RV2/$fileBasename.$fileSuffix") + Paths.get("..", "..", "test_data", "ontologyR2RV2", s"$fileBasename.$fileSuffix") } /** @@ -129,9 +129,7 @@ class OntologyV2R2RSpec extends R2RSpec { */ def writeFile(responseStr: String, mediaType: MediaType.NonBinary): Unit = if (!disableWrite) { - // Per default only read access is allowed in the bazel sandbox. - // This workaround allows to save test output. - val testOutputDir = Paths.get(sys.env("TEST_UNDECLARED_OUTPUTS_DIR")) + val testOutputDir = Paths.get("..", "test_data", "ontologyR2RV2") val file = makeFile(mediaType) val newOutputFile = testOutputDir.resolve(file) Files.createDirectories(newOutputFile.getParent)