diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc6a0ee..7d1379b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,11 +17,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-20.04 + - os: ubuntu-24.04 make: test-debug info: g++-9 + test-debug - - os: ubuntu-20.04 + - os: ubuntu-24.04 make: test-release info: g++-9 + test-release @@ -29,12 +29,12 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - name: Reuse ccache directory - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.ccache key: '${{matrix.os}} ${{matrix.info}} ccache-dir ${{github.ref}} run-${{github.run_number}}' @@ -46,6 +46,7 @@ jobs: run: | (cd third_party && git clone -b develop --single-branch --depth 1 https://github.com/userver-framework/userver.git) sudo apt update + sudo apt purge -y libpq5 libpq-dev postgresql-* sudo apt install --allow-downgrades -y postgresql $(cat third_party/userver/scripts/docs/en/deps/${{matrix.os}}.md | tr '\n' ' ') python3 -m pip install -r requirements.txt @@ -63,6 +64,8 @@ jobs: run: | make dist-clean make install PREFIX=`pwd`/local_installation/ + sed -i "s|/var/www/upastebin|`pwd`/local_installation/var/www/upastebin|g" \ + `pwd`/local_installation/etc/upastebin/static_config.yaml - name: Test run after install if: matrix.make == 'test-release' diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 179ce27..0b4ca8a 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -14,12 +14,12 @@ jobs: tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - name: Reuse ccache directory - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: .ccache key: 'ccache-dir-${{github.ref}}_run-${{github.run_number}}' @@ -27,9 +27,6 @@ jobs: ccache-dir-${{github.ref}}_run- ccache- - - name: Setup ccache - run: docker-compose run --rm upastebin-container bash -c 'ccache -M 2.0GB && ccache -s' - - name: Cmake run: make docker-cmake-release diff --git a/CMakeLists.txt b/CMakeLists.txt index 01d9f14..4a6f120 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,6 @@ if(NOT userver_FOUND) # Fallback to subdirectory usage # Compatibility mode: some systems don't support these features set(USERVER_FEATURE_CRYPTOPP_BLAKE2 OFF CACHE BOOL "" FORCE) - set(USERVER_FEATURE_GRPC_CHANNELZ OFF CACHE BOOL "" FORCE) - set(USERVER_FEATURE_REDIS_HI_MALLOC ON CACHE BOOL "" FORCE) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/userver) message(STATUS "Using userver framework from third_party/userver") @@ -79,3 +77,4 @@ file(GLOB CONFIGS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/configs/*.yaml ${CMAKE_CURRE install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${PROJECT_NAME}) install(FILES ${CONFIGS_FILES} DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME} COMPONENT ${PROJECT_NAME}) +install(DIRECTORY www-data/ DESTINATION ${CMAKE_INSTALL_LOCALSTATEDIR}/www/${PROJECT_NAME} COMPONENT ${PROJECT_NAME}) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..7be33fe --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,46 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 20, + "patch": 0 + }, + "configurePresets": [ + { + "name": "debug", + "displayName": "Debug", + "description": "Fully featured Debug build", + "inherits": [ + "common-flags" + ], + "binaryDir": "${sourceDir}/build-debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "USERVER_SANITIZE": "addr;ub" + } + }, + { + "name": "release", + "displayName": "Release", + "description": "Fully featured Release build", + "inherits": [ + "common-flags" + ], + "binaryDir": "${sourceDir}/build-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "common-flags", + "hidden": true, + "generator": "Ninja", + "cacheVariables": { + "USERVER_FEATURE_GRPC": "ON", // grpc template current + "USERVER_FEATURE_POSTGRESQL": "ON", // postgresql template current + "USERVER_FEATURE_MONGODB": "ON", // mongo template current + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + } + ] +} diff --git a/Makefile b/Makefile index 17ee980..077aeef 100644 --- a/Makefile +++ b/Makefile @@ -1,63 +1,57 @@ -CMAKE_COMMON_FLAGS ?= -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -CMAKE_DEBUG_FLAGS ?= -DUSERVER_SANITIZE='' -CMAKE_RELEASE_FLAGS ?= +PROJECT_NAME = upastebin NPROCS ?= $(shell nproc) CLANG_FORMAT ?= clang-format -DOCKER_COMPOSE ?= docker-compose - -# NOTE: use Makefile.local to override the options defined above. --include Makefile.local - -CMAKE_DEBUG_FLAGS += -DCMAKE_BUILD_TYPE=Debug $(CMAKE_COMMON_FLAGS) -CMAKE_RELEASE_FLAGS += -DCMAKE_BUILD_TYPE=Release $(CMAKE_COMMON_FLAGS) +DOCKER_IMAGE ?= ghcr.io/userver-framework/ubuntu-24.04-userver:latest +CMAKE_OPTS ?= +# If we're under TTY, pass "-it" to "docker run" +DOCKER_ARGS = $(shell /bin/test -t 0 && /bin/echo -it || echo) +PRESETS ?= debug release debug-custom release-custom .PHONY: all all: test-debug test-release # Run cmake -.PHONY: cmake-debug -cmake-debug: - cmake -B build_debug $(CMAKE_DEBUG_FLAGS) +.PHONY: $(addprefix cmake-, $(PRESETS)) +$(addprefix cmake-, $(PRESETS)): cmake-%: + cmake --preset $* $(CMAKE_OPTS) -.PHONY: cmake-release -cmake-release: - cmake -B build_release $(CMAKE_RELEASE_FLAGS) - -build_debug/CMakeCache.txt: cmake-debug -build_release/CMakeCache.txt: cmake-release +$(addsuffix /CMakeCache.txt, $(addprefix build-, $(PRESETS))): build-%/CMakeCache.txt: + $(MAKE) cmake-$* # Build using cmake -.PHONY: build-debug build-release -build-debug build-release: build-%: build_%/CMakeCache.txt - cmake --build build_$* -j $(NPROCS) --target upastebin +.PHONY: $(addprefix build-, $(PRESETS)) +$(addprefix build-, $(PRESETS)): build-%: build-%/CMakeCache.txt + cmake --build build-$* -j $(NPROCS) --target $(PROJECT_NAME) # Test -.PHONY: test-debug test-release -test-debug test-release: test-%: build-% - cmake --build build_$* -j $(NPROCS) --target runtests-upastebin - cd build_$* && GTEST_COLOR=1 PYTEST_ADDOPTS="--color=yes" ctest -V - pycodestyle tests +.PHONY: $(addprefix test-, $(PRESETS)) +$(addprefix test-, $(PRESETS)): test-%: build-%/CMakeCache.txt + cmake --build build-$* -j $(NPROCS) + cd build-$* && ((test -t 1 && GTEST_COLOR=1 PYTEST_ADDOPTS="--color=yes" ctest -V) || ctest -V) # Start the service (via testsuite service runner) -.PHONY: service-start-debug service-start-release -service-start-debug service-start-release: service-start-%: build-% - cmake --build build_$* -v --target start-upastebin +.PHONY: $(addprefix start-, $(PRESETS)) +$(addprefix start-, $(PRESETS)): start-%: + cmake --build build-$* -v --target start-$(PROJECT_NAME) # Cleanup data -.PHONY: clean-debug clean-release -clean-debug clean-release: clean-%: - cmake --build build_$* --target clean +.PHONY: $(addprefix clean-, $(PRESETS)) +$(addprefix clean-, $(PRESETS)): clean-%: + cmake --build build-$* --target clean .PHONY: dist-clean dist-clean: - rm -rf build_* + rm -rf build* rm -rf tests/__pycache__/ rm -rf tests/.pytest_cache/ + rm -rf .ccache + rm -rf .vscode/.cache + rm -rf .vscode/compile_commands.json # Install -.PHONY: install-debug install-release -install-debug install-release: install-%: build-% - cmake --install build_$* -v --component upastebin +.PHONY: $(addprefix install-, $(PRESETS)) +$(addprefix install-, $(PRESETS)): install-%: build-% + cmake --install build-$* -v --component $(PROJECT_NAME) .PHONY: install install: install-release @@ -68,28 +62,17 @@ format: find src -name '*pp' -type f | xargs $(CLANG_FORMAT) -i find tests -name '*.py' -type f | xargs autopep8 -i -# Set environment for --in-docker-start -export DB_CONNECTION := postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@service-postgres:5432/${POSTGRES_DB} - -# Internal hidden targets that are used only in docker environment ---in-docker-start-debug --in-docker-start-release: --in-docker-start-%: install-% - psql ${DB_CONNECTION} -f ./postgresql/data/initial_data.sql - /home/user/.local/bin/upastebin \ - --config /home/user/.local/etc/upastebin/static_config.yaml \ - --config_vars /home/user/.local/etc/upastebin/config_vars.docker.yaml - -# Build and run service in docker environment -.PHONY: docker-start-service-debug docker-start-service-release -docker-start-service-debug docker-start-service-release: docker-start-service-%: - $(DOCKER_COMPOSE) run -p 8080:8080 --rm upastebin-container make -- --in-docker-start-$* - -# Start targets makefile in docker environment -.PHONY: docker-cmake-debug docker-build-debug docker-test-debug docker-clean-debug docker-install-debug docker-cmake-release docker-build-release docker-test-release docker-clean-release docker-install-release -docker-cmake-debug docker-build-debug docker-test-debug docker-clean-debug docker-install-debug docker-cmake-release docker-build-release docker-test-release docker-clean-release docker-install-release: docker-%: - $(DOCKER_COMPOSE) run --rm upastebin-container make $* - -# Stop docker container and remove PG data -.PHONY: docker-clean-data -docker-clean-data: - $(DOCKER_COMPOSE) down -v - rm -rf ./.pgdata +# Start targets makefile in docker wrapper. +# The docker mounts the whole service's source directory, +# so you can do some stuff as you wish, switch back to host (non-docker) system +# and still able to access the results. +.PHONY: $(addprefix docker-cmake-, $(PRESETS)) $(addprefix docker-build-, $(PRESETS)) $(addprefix docker-test-, $(PRESETS)) $(addprefix docker-clean-, $(PRESETS)) +$(addprefix docker-cmake-, $(PRESETS)) $(addprefix docker-build-, $(PRESETS)) $(addprefix docker-test-, $(PRESETS)) $(addprefix docker-clean-, $(PRESETS)): docker-%: + docker run $(DOCKER_ARGS) \ + --network=host \ + -v $$PWD:$$PWD \ + -w $$PWD \ + $(DOCKER_IMAGE) \ + env CCACHE_DIR=$$PWD/.ccache \ + HOME=$$HOME \ + $$PWD/run_as_user.sh $(shell /bin/id -u) $(shell /bin/id -g) make $* diff --git a/README.md b/README.md index 5d18833..46f58bc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # upastebin -Template of a C++ service that uses [userver framework](https://github.com/userver-framework/userver) with PostgreSQL. +[![upastebin CI](https://github.com/userver-framework/upastebin/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/userver-framework/upastebin/actions/workflows/ci.yml) +[![upastebin Docker](https://github.com/userver-framework/upastebin/actions/workflows/docker.yaml/badge.svg?branch=develop)](https://github.com/userver-framework/upastebin/actions/workflows/docker.ymal) + +A C++ service that uses [userver framework](https://github.com/userver-framework/userver) with PostgreSQL. See [the article (ru)](https://habr.com/ru/companies/yandex/articles/894294/) for in depth description. ## Download and Build diff --git a/configs/static_config.yaml b/configs/static_config.yaml index 74bfcf4..a325b27 100644 --- a/configs/static_config.yaml +++ b/configs/static_config.yaml @@ -34,7 +34,7 @@ components_manager: http-client: fs-task-processor: fs-task-processor resources-cache: - dir: /home/segoon/projects/upastebin/www-data + dir: /var/www/upastebin update-period: 1s fs-task-processor: fs-task-processor diff --git a/run_as_user.sh b/run_as_user.sh new file mode 100755 index 0000000..25e78b1 --- /dev/null +++ b/run_as_user.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +# Exit on any error and treat unset variables as errors +set -euo + +OLD_UID=$1 +OLD_GID=$2 +shift; shift + +groupadd --gid $OLD_GID --non-unique user +useradd --uid $OLD_UID --gid $OLD_GID --non-unique user + +sudo -E -u user "$@" diff --git a/tests/test_crud.py b/tests/test_crud.py index 44f5b27..8133c82 100644 --- a/tests/test_crud.py +++ b/tests/test_crud.py @@ -32,11 +32,12 @@ async def test_create_and_retrieve(service_client): response = await service_client.get('/api/v1/latest') assert response.status == 200 json = response.json() + assert json['items'][0]['ip'] + del json['items'][0]['ip'] assert json == { 'items': [ { 'author': 'foo', - 'ip': '::ffff:127.0.0.1', 'id': uuid, 'text': TEXT, }