Ctrl K
ComunidadGuías…

CMakeLists.txt

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
cmake_minimum_required(VERSION 3.23)

option(BUILD_SIMPLE_ICONS "Embed simple-icons into the final binary, used for providing icons for transactions." ON)
option(BUILD_NOSIMD "Disable SIMD support at compile time." OFF)
option(BUILD_CONTAINER_TAG_LATEST "Tag containers with latest when building them." ON)

option(SIGN_RECURSIVE "Sign all referenced images recursively (covers each platform image of multi-arch builds)." OFF)
option(SIGN_TLOG_UPLOAD "Upload cosign signatures to the Sigstore Rekor transparency log." ON)
set(SIGN_CERT_IDENTITY_REGEX "^https://github.com/monetr/monetr/" CACHE STRING "OIDC certificate identity regex used to verify cosign signatures.")
set(SIGN_OIDC_ISSUER "https://token.actions.githubusercontent.com" CACHE STRING "OIDC issuer URL used to verify cosign signatures.")

option(TEST_RACE "Go tests should be run with the -race flag" ON)
option(TEST_COVERAGE "Coverage data should be collected from tests" ON)
option(TEST_USE_GOTESTSUM "Wrap test execution in gotestsum" OFF)
option(TEST_SHORT "Exclude long running tests" ON)

if (CMAKE_BUILD_TYPE STREQUAL "Release")
  message(STATUS "Mode: Release")
else()
  message(STATUS "Mode: Debug")
endif()

# This makes it possible to support some other languages.
# You'll find here we have the FindX files as well as some other ones.
# This will make it so cmake looks here for some Find files.
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
project(monetr Go)

# Get the hostname for the build.
if (WIN32)
  set(HOME $ENV{USERPROFILE})
  execute_process(COMMAND hostname OUTPUT_VARIABLE HOSTNAME OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
  set(HOME $ENV{HOME})
  execute_process(COMMAND uname -n OUTPUT_VARIABLE HOSTNAME OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()

# monetr requires cgo in order to be built at this time, so if gcc is not present on the system then show a warning.
find_package(Gcc REQUIRED)
find_package(Git REQUIRED)

set(DOCKER_MIN_VERSION "26.0.0")
find_package(Docker QUIET)
find_program(COSIGN_EXECUTABLE cosign)

set(MONETR_PKG_ROOT github.com/monetr/monetr CACHE INTERNAL "Base go package for monetr.")

# The UI tasks are split out into their own file.
# Import this _after_ we have found all the packages above.
include(NodeModules)
include(GolangUtils)
add_subdirectory("${CMAKE_SOURCE_DIR}/images")
add_subdirectory("${CMAKE_SOURCE_DIR}/interface")
add_subdirectory("${CMAKE_SOURCE_DIR}/emails")

add_custom_target(
  dependencies
  DEPENDS dependencies.node_modules ${GO_MODULES}
)

if(DOCKER_EXECUTABLE)
  message(STATUS "Container engine: Docker")
  message(STATUS "  Container build targets will be enabled!")
  include("${CMAKE_SOURCE_DIR}/cmake/development.cmake")

  if(NOT BUILD_PLATFORMS)
    set(BUILD_PLATFORMS "linux/amd64,linux/arm64")
  endif()
  message(STATUS "  Container will be built for platforms: ${BUILD_PLATFORMS}")

  if(NOT "$ENV{CONTAINER_REGISTRY}" STREQUAL "")
    set(CONTAINER_REGISTRY "$ENV{CONTAINER_REGISTRY}")
  else()
    set(CONTAINER_REGISTRY "ghcr.io/monetr/monetr" "docker.io/monetr/monetr" "quay.io/monetr/monetr")
  endif()
  set(CONTAINER_TAGS "$(CONTAINER_VERSION)")
  if(BUILD_CONTAINER_TAG_LATEST)
    list(APPEND CONTAINER_TAGS "latest")
  endif()

  set(CONTAINER_ARGS)
  foreach(REGISTRY ${CONTAINER_REGISTRY})
    foreach(TAG ${CONTAINER_TAGS})
      list(APPEND CONTAINER_ARGS "-t" "${REGISTRY}:${TAG}")
    endforeach()
  endforeach()

  set(DOCKER_CONTAINER ${CMAKE_BINARY_DIR}/docker-build-manifest.json)
  add_custom_command(
    OUTPUT ${DOCKER_CONTAINER}
    BYPRODUCTS ${DOCKER_CONTAINER}
    COMMENT "Building monetr container image"
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    DEPENDS
      ${APP_GO_FILES}
      ${APP_UI_FILES}
      ${CMAKE_SOURCE_DIR}/Dockerfile
      ${CMAKE_SOURCE_DIR}/package.json
      ${CMAKE_SOURCE_DIR}/pnpm-lock.yaml
      ${PUBLIC_FILES}
      ${UI_CONFIG_FILES}
    VERBATIM
    COMMAND ${CMAKE_COMMAND} -E echo "-- Building monetr container: ${CONTAINER_REGISTRY} - ${CONTAINER_TAGS}"
    COMMAND ${DOCKER_EXECUTABLE} buildx build
        -f ${CMAKE_SOURCE_DIR}/Dockerfile
        --platform ${BUILD_PLATFORMS}
        --build-arg GOFLAGS=-tags=icons,simple_icons
        --build-arg RELEASE=$(RELEASE_VERSION)
        --build-arg REVISION=$(RELEASE_REVISION)
        --build-arg BUILD_HOST=${HOSTNAME}
        --metadata-file ${DOCKER_CONTAINER}
        --label "index:org.opencontainers.image.url=https://monetr.app"
        --label "index:org.opencontainers.image.source=https://github.com/monetr/monetr"
        --label "index:org.opencontainers.image.authors=elliot.courant@monetr.app"
        --label "index:org.opencontainers.image.vendor=monetr"
        --label "index:org.opencontainers.image.licenses=FSL-1.1-MIT"
        --label "index:org.opencontainers.image.description=monetr's budgeting application"
        --label "index:org.opencontainers.image.version=$(RELEASE_VERSION)"
        --label "index:org.opencontainers.image.revision=$(RELEASE_REVISION)"
        --annotation "index:org.opencontainers.image.url=https://monetr.app"
        --annotation "index:org.opencontainers.image.source=https://github.com/monetr/monetr"
        --annotation "index:org.opencontainers.image.authors=elliot.courant@monetr.app"
        --annotation "index:org.opencontainers.image.vendor=monetr"
        --annotation "index:org.opencontainers.image.licenses=FSL-1.1-MIT"
        --annotation "index:org.opencontainers.image.description=monetr's budgeting application"
        --annotation "index:org.opencontainers.image.version=$(RELEASE_VERSION)"
        --annotation "index:org.opencontainers.image.revision=$(RELEASE_REVISION)"
        ${CONTAINER_ARGS}
        ${CMAKE_SOURCE_DIR}
  )
  add_custom_target(
    build.container.docker
    DEPENDS ${DOCKER_CONTAINER}
  )

  set(DOCKER_CONTAINER_PUSH ${CMAKE_BINARY_DIR}/docker-container-push-manifest.json)
  add_custom_command(
    OUTPUT ${DOCKER_CONTAINER_PUSH}
    BYPRODUCTS ${DOCKER_CONTAINER_PUSH}
    COMMENT "Building monetr container image"
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    DEPENDS
      ${APP_GO_FILES}
      ${APP_UI_FILES}
      ${CMAKE_SOURCE_DIR}/Dockerfile
      ${CMAKE_SOURCE_DIR}/package.json
      ${CMAKE_SOURCE_DIR}/pnpm-lock.yaml
      ${PUBLIC_FILES}
      ${UI_CONFIG_FILES}
    VERBATIM
    COMMAND ${CMAKE_COMMAND} -E echo "-- Building monetr container: ${CONTAINER_REGISTRY} - ${CONTAINER_TAGS}"
    COMMAND ${DOCKER_EXECUTABLE} buildx build
        --push
        -f ${CMAKE_SOURCE_DIR}/Dockerfile
        --platform ${BUILD_PLATFORMS}
        --build-arg GOFLAGS=-tags=icons,simple_icons
        --build-arg RELEASE=$(RELEASE_VERSION)
        --build-arg REVISION=$(RELEASE_REVISION)
        --build-arg BUILD_HOST=${HOSTNAME}
        --metadata-file ${DOCKER_CONTAINER_PUSH}
        --label "index:org.opencontainers.image.url=https://monetr.app"
        --label "index:org.opencontainers.image.source=https://github.com/monetr/monetr"
        --label "index:org.opencontainers.image.authors=elliot.courant@monetr.app"
        --label "index:org.opencontainers.image.vendor=monetr"
        --label "index:org.opencontainers.image.licenses=FSL-1.1-MIT"
        --label "index:org.opencontainers.image.description=monetr's budgeting application"
        --label "index:org.opencontainers.image.version=$(RELEASE_VERSION)"
        --label "index:org.opencontainers.image.revision=$(RELEASE_REVISION)"
        --annotation "index:org.opencontainers.image.url=https://monetr.app"
        --annotation "index:org.opencontainers.image.source=https://github.com/monetr/monetr"
        --annotation "index:org.opencontainers.image.authors=elliot.courant@monetr.app"
        --annotation "index:org.opencontainers.image.vendor=monetr"
        --annotation "index:org.opencontainers.image.licenses=FSL-1.1-MIT"
        --annotation "index:org.opencontainers.image.description=monetr's budgeting application"
        --annotation "index:org.opencontainers.image.version=$(RELEASE_VERSION)"
        --annotation "index:org.opencontainers.image.revision=$(RELEASE_REVISION)"
        ${CONTAINER_ARGS}
        ${CMAKE_SOURCE_DIR}
  )

  add_custom_target(
    build.container.docker.push
    DEPENDS ${DOCKER_CONTAINER_PUSH}
  )

  if(COSIGN_EXECUTABLE)
    message(STATUS "  Container signing engine: cosign (${COSIGN_EXECUTABLE})")

    # CMake's add_custom_command(COMMAND ...) splits list-valued args on the
    # ; separator, which would expand a multi-registry list into separate
    # cmake -P arguments. Join into a comma-separated string so the script
    # gets a single -DREGISTRIES=... arg and re-splits on , at runtime.
    list(JOIN CONTAINER_REGISTRY "," CONTAINER_REGISTRY_CSV)

    set(DOCKER_CONTAINER_DIGEST ${CMAKE_BINARY_DIR}/docker-container-push.digest)
    set(DOCKER_CONTAINER_SIGNING_CONFIG ${CMAKE_BINARY_DIR}/cosign-signing-config-no-tlog.json)
    set(DOCKER_CONTAINER_SIGN_STAMP ${CMAKE_BINARY_DIR}/docker-container-sign.stamp)
    add_custom_command(
      OUTPUT ${DOCKER_CONTAINER_SIGN_STAMP}
      BYPRODUCTS ${DOCKER_CONTAINER_SIGN_STAMP} ${DOCKER_CONTAINER_DIGEST} ${DOCKER_CONTAINER_SIGNING_CONFIG}
      COMMENT "Signing monetr container images with cosign"
      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
      DEPENDS ${DOCKER_CONTAINER_PUSH}
      VERBATIM
      COMMAND ${CMAKE_COMMAND}
        "-DMETADATA_FILE=${DOCKER_CONTAINER_PUSH}"
        "-DREGISTRIES=${CONTAINER_REGISTRY_CSV}"
        "-DCOSIGN_EXECUTABLE=${COSIGN_EXECUTABLE}"
        "-DSIGN_RECURSIVE=${SIGN_RECURSIVE}"
        "-DSIGN_TLOG_UPLOAD=${SIGN_TLOG_UPLOAD}"
        "-DDIGEST_FILE=${DOCKER_CONTAINER_DIGEST}"
        "-DSIGNING_CONFIG_FILE=${DOCKER_CONTAINER_SIGNING_CONFIG}"
        -P ${CMAKE_SOURCE_DIR}/cmake/scripts/CosignSign.cmake
      COMMAND ${CMAKE_COMMAND} -E touch ${DOCKER_CONTAINER_SIGN_STAMP}
    )
    add_custom_target(
      build.container.docker.sign
      DEPENDS ${DOCKER_CONTAINER_SIGN_STAMP}
    )

    set(DOCKER_CONTAINER_VERIFY_STAMP ${CMAKE_BINARY_DIR}/docker-container-verify.stamp)
    add_custom_command(
      OUTPUT ${DOCKER_CONTAINER_VERIFY_STAMP}
      BYPRODUCTS ${DOCKER_CONTAINER_VERIFY_STAMP}
      COMMENT "Verifying monetr container image signatures with cosign"
      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
      DEPENDS ${DOCKER_CONTAINER_SIGN_STAMP}
      VERBATIM
      COMMAND ${CMAKE_COMMAND}
        "-DMETADATA_FILE=${DOCKER_CONTAINER_PUSH}"
        "-DREGISTRIES=${CONTAINER_REGISTRY_CSV}"
        "-DCOSIGN_EXECUTABLE=${COSIGN_EXECUTABLE}"
        "-DSIGN_TLOG_UPLOAD=${SIGN_TLOG_UPLOAD}"
        "-DSIGN_CERT_IDENTITY_REGEX=${SIGN_CERT_IDENTITY_REGEX}"
        "-DSIGN_OIDC_ISSUER=${SIGN_OIDC_ISSUER}"
        -P ${CMAKE_SOURCE_DIR}/cmake/scripts/CosignVerify.cmake
      COMMAND ${CMAKE_COMMAND} -E touch ${DOCKER_CONTAINER_VERIFY_STAMP}
    )
    add_custom_target(
      build.container.docker.verify
      DEPENDS ${DOCKER_CONTAINER_VERIFY_STAMP}
    )
  else()
    message(STATUS "  cosign not found; container signing targets will be unavailable")
  endif()
endif()

if(NOT DEFINED ENV{CI})
  add_custom_target(lint
    COMMENT "Linting monetr code base..."
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    DEPENDS tools.biome
    COMMAND ${CMAKE_Go_COMPILER} fmt ./...
    # Check all of the files that have changed since this commit, this is when the linting was introduced.
    COMMAND ${BIOME_EXECUTABLE} check --write --max-diagnostics=1000 --since=6173df2df49e0754f0a2b902a433c712e034e1e2 --changed
  )
else()
  add_custom_target(lint
    COMMENT "Linting monetr code base..."
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    DEPENDS tools.biome
    # Check all of the files that have changed since this commit, this is when the linting was introduced.
    COMMAND ${BIOME_EXECUTABLE} ci --reporter=github --max-diagnostics=1000 --since=6173df2df49e0754f0a2b902a433c712e034e1e2 --changed
  )
endif()

add_custom_target(lint-all
  COMMENT "Linting monetr code base..."
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  DEPENDS tools.biome
  COMMAND ${CMAKE_Go_COMPILER} fmt ./...
  COMMAND ${BIOME_EXECUTABLE} check --write --max-diagnostics=1000
)

add_custom_target(interface.typecheck
  COMMENT "Type checking monetr's frontend code..."
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  DEPENDS tools.tsc
  COMMAND ${TSC_EXECUTABLE} --noEmit --pretty
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/interface
)

add_custom_target(emails.typecheck
  COMMENT "Type checking monetr's email templates..."
  DEPENDS tools.tsc
  COMMAND ${TSC_EXECUTABLE} --noEmit --pretty
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/emails
)

add_custom_target(docs.typecheck
  COMMENT "Type checking monetr's documentation..."
  DEPENDS tools.tsc
  COMMAND ${TSC_EXECUTABLE} --noEmit --pretty
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
)

################################################################################
#                                     TESTING                                  #
################################################################################

enable_testing()
option(BUILD_TESTING "Build the testing tree." OFF)

include(GolangTestUtils)

if(BUILD_TESTING)
  if(CMAKE_Go_COMPILER)
    execute_process(
      COMMAND ${CMAKE_Go_COMPILER} run ${CMAKE_SOURCE_DIR}/cmake/find_tests.go ${CMAKE_SOURCE_DIR}/server
      OUTPUT_VARIABLE GOLANG_TEST_LIST
      OUTPUT_STRIP_TRAILING_WHITESPACE
      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    )
    set(GOLANG_TEST_LIST "${GOLANG_TEST_LIST}" CACHE STRING "All Golang unit tests in json format." FORCE)

    add_test(
      NAME migrate.db
      COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} -t development.migrate
      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    )
    # Migrations have to compile the server, which needs the CLDR dataset. This
    # also keeps both of these from downloading it at the same time
    set_tests_properties(migrate.db PROPERTIES FIXTURES_SETUP DB FIXTURES_REQUIRED cldr)
    set_property(
      TEST migrate.db
      PROPERTY LABELS "bootstrap"
    )

    # The currency package embeds the CLDR dataset, so basically nothing in Go
    # compiles until it's been downloaded
    add_test(
      NAME download.cldr-json
      COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} -t download.cldr-json
      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    )
    set_tests_properties(download.cldr-json PROPERTIES FIXTURES_SETUP cldr)
    set_property(
      TEST download.cldr-json
      PROPERTY LABELS "bootstrap"
    )

    # If this test fails that means you need to run `go mod tidy`.
    add_test(
      NAME go.mod.tidy
      COMMAND ${CMAKE_Go_COMPILER} mod tidy --diff
      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    )
    set_property(
      TEST go.mod.tidy
      PROPERTY LABELS "bootstrap"
    )
  else()
    message(STATUS "Go tests will not be run since Go installation could not be found.")
  endif()

  add_test(
    NAME ui.dependencies
    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} -t dependencies.node_modules
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  )
  set_tests_properties(ui.dependencies PROPERTIES FIXTURES_SETUP node_modules DEPENDS ${PNPM_EXECUTABLE})
  set_property(
    TEST ui.dependencies
    PROPERTY LABELS "bootstrap"
  )
  set(INTERFACE_TEST_DIRECTORY ${CMAKE_BINARY_DIR}/tests/interface)
  set(INTERFACE_COVERAGE_DIRECTORY ${INTERFACE_TEST_DIRECTORY}/coverage)
  file(MAKE_DIRECTORY ${INTERFACE_TEST_DIRECTORY})
  file(MAKE_DIRECTORY ${INTERFACE_COVERAGE_DIRECTORY})

  set(INTERFACE_TEST_ARGS "run" "--config=${CMAKE_SOURCE_DIR}/interface/rstest.config.ts")
  if(TEST_COVERAGE)
    list(APPEND INTERFACE_TEST_ARGS "--coverage.enabled")
  endif()

  add_test(
    NAME interface
    COMMAND ${RSTEST_EXECUTABLE} ${INTERFACE_TEST_ARGS}
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/interface
  )
  set_tests_properties(interface PROPERTIES
    FIXTURES_REQUIRED node_modules
    TIMEOUT 120
    LABELS "interface"
    PROCESSORS 4
  )
  if(TEST_COVERAGE)
    set_property(
      TEST interface
      PROPERTY ENVIRONMENT "RSTEST_COVERAGE_DIR=${INTERFACE_COVERAGE_DIRECTORY}"
    )
  endif()

  add_test(
    NAME interface.typecheck
    COMMAND ${TSC_EXECUTABLE} --noEmit --pretty
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/interface
  )
  set_tests_properties(interface.typecheck PROPERTIES
    FIXTURES_REQUIRED node_modules
    TIMEOUT 120
    LABELS "interface"
    PROCESSORS 2
  )

  add_test(
    NAME emails.typecheck
    COMMAND ${TSC_EXECUTABLE} --noEmit --pretty
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/emails
  )
  set_tests_properties(emails.typecheck PROPERTIES
    FIXTURES_REQUIRED node_modules
    TIMEOUT 120
    LABELS "emails"
    PROCESSORS 2
  )

  add_test(
    NAME docs.typecheck
    COMMAND ${TSC_EXECUTABLE} --noEmit --pretty
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
  )
  set_tests_properties(docs.typecheck PROPERTIES
    FIXTURES_REQUIRED node_modules
    TIMEOUT 120
    LABELS "docs"
    PROCESSORS 2
  )

  # add_test(
  #   NAME renovate.validate
  #   COMMAND ${RENOVATE_CONFIG_VALIDATOR_EXECUTABLE} --strict
  #   WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  # )
  # set_tests_properties(renovate.validate PROPERTIES
  #   FIXTURES_REQUIRED node_modules
  #   FIXTURES_SETUP ui.dependencies
  #   TIMEOUT 60
  # )
  # set_property(
  #   TEST renovate.validate
  #   PROPERTY LABELS "renovate"
  # )
endif()

file(GLOB_RECURSE SUB_PACKAGES RELATIVE ${CMAKE_SOURCE_DIR} "${CMAKE_SOURCE_DIR}/server/*CMakeLists.txt")
# # Loop through the files and get their directories
foreach(SUB_PACKAGE IN LISTS SUB_PACKAGES)
  get_filename_component(DIR ${SUB_PACKAGE} DIRECTORY)
  add_subdirectory(${DIR})
endforeach()


# In order for documentation tests to work this has to be after the tests are setup.
add_subdirectory("${CMAKE_SOURCE_DIR}/docs")

# Prevent caching of this value
unset(BUILD_TESTING)