diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000..5db72dd6 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} diff --git a/.github/trusted-contribution.yml b/.github/trusted-contribution.yml new file mode 100644 index 00000000..31a45ab2 --- /dev/null +++ b/.github/trusted-contribution.yml @@ -0,0 +1,3 @@ +annotations: + - type: comment + text: "/gcbrun" diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index df09849e..07b514d5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,7 +6,7 @@ on: pull_request: env: - vcpkg_SHA: "dfcd4e4b30799c4ce02fe3939b62576fec444224" + vcpkg_SHA: "2024.09.30" jobs: build-ubuntu-focal: @@ -15,7 +15,7 @@ jobs: steps: - name: install ninja run: sudo apt install ninja-build - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: clone-vcpkg working-directory: "${{runner.temp}}" run: > @@ -24,7 +24,7 @@ jobs: tar -C vcpkg --strip-components=1 -zxf - - name: cache-vcpkg id: cache-vcpkg - uses: actions/cache@v2 + uses: actions/cache@v4 with: # Preserve the vcpkg binary *and* the vcpkg binary cache in the build cache path: | @@ -42,7 +42,7 @@ jobs: cmake -S . -B "${{runner.temp}}/build" -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_TOOLCHAIN_FILE="${{runner.temp}}/vcpkg/scripts/buildsystems/vcpkg.cmake" - - uses: actions/cache/save@v3 + - uses: actions/cache/save@v4 if: always() with: path: | @@ -53,7 +53,7 @@ jobs: run: cmake --build "${{runner.temp}}/build" - name: test working-directory: "${{runner.temp}}/build" - run: ctest --output-on-failure --timeout=60s + run: ctest --output-on-failure --timeout 60 # Verify the howto guides compile correctly, they need a special setup to use the # current version of `functions-framework-cpp` through vcpkg. @@ -63,10 +63,10 @@ jobs: steps: - name: install ninja run: sudo apt install ninja-build - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: cache-vcpkg id: cache-vcpkg - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: | ~/.cache/vcpkg @@ -89,7 +89,7 @@ jobs: run: > cmake -S examples/site/howto_local_development -B "${{runner.temp}}/howto_local_development/build" -GNinja -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake - - uses: actions/cache/save@v3 + - uses: actions/cache/save@v4 if: always() with: path: | @@ -104,7 +104,7 @@ jobs: build-msvc-2019: if: ${{ false }} # TODO(#366) - disable for now name: msvc-2019 - runs-on: windows-2019 + runs-on: windows-2022 steps: - name: install-ninja run: choco install -y --no-progress ninja @@ -122,7 +122,7 @@ jobs: - name: cache-vcpkg id: cache-vcpkg - uses: actions/cache@v2 + uses: actions/cache@v4 with: # Preserve the vcpkg binary cache path: | @@ -132,7 +132,7 @@ jobs: restore-keys: | vcpkg-${{ env.vcpkg_SHA }}-build-msvc-2019-2- - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: ilammy/msvc-dev-cmd@v1 - name: configure run: | @@ -140,7 +140,7 @@ jobs: '-DBUILD_TESTING=ON' ` '-DFUNCTIONS_FRAMEWORK_CPP_TEST_EXAMPLES=OFF' ` '-DCMAKE_TOOLCHAIN_FILE=${{runner.temp}}/vcpkg/scripts/buildsystems/vcpkg.cmake' - - uses: actions/cache/save@v3 + - uses: actions/cache/save@v4 if: always() with: path: | @@ -150,7 +150,7 @@ jobs: run: cmake --build "${{runner.temp}}/build" - name: test working-directory: "${{runner.temp}}/build" - run: ctest --output-on-failure --timeout=60s + run: ctest --output-on-failure --timeout 60 build-macos: if: ${{ false }} # TODO(#367) - disable for now @@ -159,7 +159,7 @@ jobs: steps: - name: install ninja run: brew install ninja - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: clone-vcpkg working-directory: "${{runner.temp}}" run: > @@ -168,7 +168,7 @@ jobs: tar -C vcpkg --strip-components=1 -zxf - - name: cache-vcpkg id: cache-vcpkg - uses: actions/cache@v2 + uses: actions/cache@v4 with: # Preserve the vcpkg binary *and* the vcpkg binary cache in the build cache path: | @@ -186,7 +186,7 @@ jobs: cmake -S . -B "${{runner.temp}}/build" -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_TOOLCHAIN_FILE="${{runner.temp}}/vcpkg/scripts/buildsystems/vcpkg.cmake" - - uses: actions/cache/save@v3 + - uses: actions/cache/save@v4 if: always() with: path: | @@ -197,4 +197,4 @@ jobs: run: cmake --build "${{runner.temp}}/build" - name: test working-directory: "${{runner.temp}}/build" - run: ctest --output-on-failure --timeout=60s + run: ctest --output-on-failure --timeout 60 diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index a22257f2..bd5cab46 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -6,7 +6,7 @@ on: pull_request: env: - vcpkg_SHA: "dfcd4e4b30799c4ce02fe3939b62576fec444224" + vcpkg_SHA: "2024.09.30" jobs: coverage: @@ -15,7 +15,7 @@ jobs: steps: - name: install tools run: sudo apt install ninja-build lcov - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: clone-vcpkg working-directory: "${{runner.temp}}" run: > @@ -24,7 +24,7 @@ jobs: tar -C vcpkg --strip-components=1 -zxf - - name: cache-vcpkg id: cache-vcpkg - uses: actions/cache@v2 + uses: actions/cache@v4 with: # Preserve the vcpkg binary *and* the vcpkg binary cache in the build cache path: | @@ -43,7 +43,7 @@ jobs: -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=--coverage -DCMAKE_TOOLCHAIN_FILE="${{runner.temp}}/vcpkg/scripts/buildsystems/vcpkg.cmake" - - uses: actions/cache/save@v3 + - uses: actions/cache/save@v4 if: always() with: path: | @@ -54,15 +54,15 @@ jobs: run: cmake --build ${{runner.workspace}}/build - name: test working-directory: ${{runner.workspace}}/build - run: ctest --output-on-failure --timeout=60s + run: ctest --output-on-failure --timeout 60 - name: Setup Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: go-version: '^1.16' - name: Run Cloud Event conformance tests - uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.8.3 + uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.8.6 with: functionType: 'cloudevent' useBuildpacks: false @@ -70,7 +70,7 @@ jobs: cmd: '${{runner.workspace}}/build/google/cloud/functions/integration_tests/cloud_event_conformance' - name: Run HTTP conformance tests - uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.8.3 + uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.8.6 with: functionType: 'http' useBuildpacks: false @@ -78,6 +78,7 @@ jobs: cmd: '${{runner.workspace}}/build/google/cloud/functions/integration_tests/http_conformance' - name: coverage-upload - working-directory: ${{runner.workspace}} - run: > - /bin/bash <(curl -s https://codecov.io/bash) -X coveragepy -x /usr/bin/gcov + uses: codecov/codecov-action@v4 + with: + directory: ${{ runner.workspace }} + token: ${{ vars.CODECOV_TOKEN }} diff --git a/.github/workflows/install.yaml b/.github/workflows/install.yaml index ad195add..604b6fc3 100644 --- a/.github/workflows/install.yaml +++ b/.github/workflows/install.yaml @@ -12,7 +12,7 @@ jobs: steps: - name: install-dependencies run: sudo apt install ninja-build libboost-dev libboost-program-options-dev nlohmann-json3-dev libabsl-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: configure run: > cmake -S . -B ${{runner.temp}}/build -GNinja -DBUILD_TESTING=OFF @@ -37,7 +37,7 @@ jobs: - name: install-dependencies run: > sudo apt install ninja-build libboost-dev libboost-program-options-dev nlohmann-json3-dev libabsl-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: configure run: > cmake -S . -B ${{runner.temp}}/build -GNinja diff --git a/.github/workflows/sanitize.yaml b/.github/workflows/sanitize.yaml deleted file mode 100644 index bed854c7..00000000 --- a/.github/workflows/sanitize.yaml +++ /dev/null @@ -1,72 +0,0 @@ -name: sanitize - -on: - push: - branches: [ main ] - pull_request: - -env: - vcpkg_SHA: "dfcd4e4b30799c4ce02fe3939b62576fec444224" - -jobs: - sanitized-build: - # Using a blank name produces better output on - # the web UI (e.g. "sanitize / (address)") than - # any other alternative we tried. - name: " " - runs-on: ubuntu-22.04 - strategy: - matrix: - sanitizer: ["address", "undefined", "thread"] - steps: - - name: install ninja - run: sudo apt install ninja-build - - uses: actions/checkout@v2 - - name: clone-vcpkg - working-directory: "${{runner.temp}}" - run: > - mkdir -p vcpkg && - curl -sSL "https://github.com/microsoft/vcpkg/archive/${{env.vcpkg_SHA}}.tar.gz" | - tar -C vcpkg --strip-components=1 -zxf - - - name: cache-vcpkg - id: cache-vcpkg - uses: actions/cache@v2 - with: - # Preserve the vcpkg binary *and* the vcpkg binary cache in the build cache - path: | - ~/.cache/vcpkg - ~/.cache/bin - key: | - vcpkg-${{ env.vcpkg_SHA }}-sanitize-${{ matrix.sanitizer }}-${{ hashFiles('vcpkg.json') }} - restore-keys: | - vcpkg-${{ env.vcpkg_SHA }}-sanitize-${{ matrix.sanitizer }}- - - name: boostrap-vcpkg - run: ci/restore-vcpkg-from-cache.sh "${{runner.temp}}/vcpkg" - - name: -fsanitize=${{matrix.sanitizer}} / configure - # See https://github.com/grpc/grpc/pull/22325 for an explanation around the - # -DGRPC_* flags. - run: > - cmake -S . -B "${{runner.temp}}/build" -GNinja - -DCMAKE_CXX_COMPILER=clang++-14 - -DCMAKE_C_COMPILER=clang-14 - -DCMAKE_BUILD_TYPE=Debug - -DCMAKE_CXX_FLAGS="-fsanitize=${{matrix.sanitizer}} -DGRPC_TSAN_SUPPRESSED -DGRPC_ASAN_SUPPRESSED" - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - -DCMAKE_TOOLCHAIN_FILE="${{runner.temp}}/vcpkg/scripts/buildsystems/vcpkg.cmake" - - uses: actions/cache/save@v3 - if: always() - with: - path: | - ~/.cache/vcpkg - ~/.cache/bin - key: vcpkg-${{ env.vcpkg_SHA }}-sanitize-${{ matrix.sanitizer }}-${{ hashFiles('vcpkg.json') }} - - name: -fsanitize=${{matrix.sanitizer}} / build - run: cmake --build "${{runner.temp}}/build" - - name: -fsanitize=${{matrix.sanitizer}} / test - working-directory: "${{runner.temp}}/build" - env: - ASAN_OPTIONS: detect_leaks=1:color=always - LSAN_OPTIONS: report_objects=1 - TSAN_OPTIONS: halt_on_error=1:second_deadlock_stack=1 - UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1 - run: ctest --output-on-failure --timeout=60s diff --git a/.github/workflows/style.yaml b/.github/workflows/style.yaml index 8cbc9438..dc2ab80e 100644 --- a/.github/workflows/style.yaml +++ b/.github/workflows/style.yaml @@ -6,115 +6,14 @@ on: pull_request: env: - vcpkg_SHA: "dfcd4e4b30799c4ce02fe3939b62576fec444224" + vcpkg_SHA: "2024.09.30" jobs: - clang-tidy: - name: clang-tidy - runs-on: ubuntu-22.04 - steps: - - name: install ninja - run: sudo apt install ninja-build clang-tidy-14 - - uses: actions/checkout@v2 - - name: clone-vcpkg - working-directory: "${{runner.temp}}" - run: > - mkdir -p vcpkg && - curl -sSL "https://github.com/microsoft/vcpkg/archive/${{env.vcpkg_SHA}}.tar.gz" | - tar -C vcpkg --strip-components=1 -zxf - - - name: cache-vcpkg - id: cache-vcpkg - uses: actions/cache@v2 - with: - # Preserve the vcpkg binary *and* the vcpkg binary cache in the build cache - path: | - ~/.cache/vcpkg - ~/.cache/bin - key: | - vcpkg-${{ env.vcpkg_SHA }}-style-clang-tidy-${{ hashFiles('vcpkg.json') }} - restore-keys: | - vcpkg-${{ env.vcpkg_SHA }}-style-clang-tidy- - - name: boostrap-vcpkg - run: ci/restore-vcpkg-from-cache.sh "${{runner.temp}}/vcpkg" - - name: configure - run: > - cmake -S . -B "${{runner.temp}}/build" - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - -DCMAKE_TOOLCHAIN_FILE="${{runner.temp}}/vcpkg/scripts/buildsystems/vcpkg.cmake" - - uses: actions/cache/save@v3 - if: always() - with: - path: | - ~/.cache/vcpkg - ~/.cache/bin - key: vcpkg-${{ env.vcpkg_SHA }}-style-clang-tidy-${{ hashFiles('vcpkg.json') }} - - name: tidy - run: > - git ls-files -z -- '*.cc' | - xargs --verbose -P 2 -n 1 -0 clang-tidy-14 -p="${{runner.temp}}/build" - - werror-build: - # Using a blank name produces better output on - # the web UI than any other alternative we tried. - name: " " - runs-on: ubuntu-22.04 - strategy: - matrix: - compiler: [ - {"cxx": "clang++-14", "cc": "clang-14"}, - {"cxx": "g++-11", "cc": "gcc-11" }, - ] - steps: - - name: install ninja - run: sudo apt install ninja-build - - uses: actions/checkout@v2 - - name: clone-vcpkg - working-directory: "${{runner.temp}}" - run: > - mkdir -p vcpkg && - curl -sSL "https://github.com/microsoft/vcpkg/archive/${{env.vcpkg_SHA}}.tar.gz" | - tar -C vcpkg --strip-components=1 -zxf - - - name: cache-vcpkg - id: cache-vcpkg - uses: actions/cache@v2 - with: - # Preserve the vcpkg binary *and* the vcpkg binary cache in the build cache - path: | - ~/.cache/vcpkg - ~/.cache/bin - key: | - vcpkg-${{ env.vcpkg_SHA }}-werror-${{ matrix.compiler.cxx }}-${{ hashFiles('vcpkg.json') }} - restore-keys: | - vcpkg-${{ env.vcpkg_SHA }}-werror-${{ matrix.compiler.cxx }}- - - name: boostrap-vcpkg - run: ci/restore-vcpkg-from-cache.sh "${{runner.temp}}/vcpkg" - - name: compiler=${{matrix.sanitizer}} / configure - run: > - cmake -S . -B "${{runner.temp}}/build" -GNinja - -DFUNCTIONS_FRAMEWORK_CPP_ENABLE_WERROR=ON - -DCMAKE_CXX_COMPILER=${{matrix.compiler.cxx}} - -DCMAKE_C_COMPILER=${{matrix.compiler.cc}} - -DCMAKE_BUILD_TYPE=Debug - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - -DCMAKE_TOOLCHAIN_FILE="${{runner.temp}}/vcpkg/scripts/buildsystems/vcpkg.cmake" - - uses: actions/cache/save@v3 - if: always() - with: - path: | - ~/.cache/vcpkg - ~/.cache/bin - key: vcpkg-${{ env.vcpkg_SHA }}-werror-${{ matrix.compiler.cxx }}-${{ hashFiles('vcpkg.json') }} - - name: compiler=${{matrix.compiler.cxx}} / build - run: cmake --build "${{runner.temp}}/build" - - name: compiler=${{matrix.compiler.cxx}} / test - working-directory: "${{runner.temp}}/build" - run: ctest --output-on-failure --timeout=60s - clang-format: name: clang-format runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: clang-format run: > git ls-files -z -- '*.h' '*.cc' | @@ -126,7 +25,7 @@ jobs: name: cmake-format runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: install cmake-format run: pip install cmakelang==0.6.13 - name: cmake-format @@ -140,7 +39,7 @@ jobs: name: generated-files runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: install ninja run: sudo apt install moreutils - name: regenerate-build-examples diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a200de7..a4f458ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +## v1.3.0 - TBD + ## v1.2.0 - 2023-07 * docs: use working buildpacks (#381) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c442d1a..75d33464 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,11 +14,7 @@ # limitations under the License. # ~~~ -cmake_minimum_required(VERSION 3.10) - -if (NOT (CMAKE_VERSION VERSION_LESS "3.14")) - cmake_policy(SET CMP0091 NEW) -endif () +cmake_minimum_required(VERSION 3.10...3.26) option(BUILD_TESTING "Enable tests" ON) if (BUILD_TESTING) @@ -34,7 +30,7 @@ set(PACKAGE_BUGREPORT "http://github.com/GoogleCloudPlatform/functions-framework-cpp") project( functions-framework-cpp - VERSION 1.2.0 + VERSION 1.3.0 DESCRIPTION "Functions Framework for C++" LANGUAGES CXX) diff --git a/build_scripts/Dockerfile b/build_scripts/Dockerfile index e0d34072..58ab228c 100644 --- a/build_scripts/Dockerfile +++ b/build_scripts/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM gcr.io/gcp-runtimes/ubuntu_18_0_4 AS parent +FROM gcr.io/gcp-runtimes/ubuntu_20_0_4 AS parent ARG cnb_uid=1000 ARG cnb_gid=1000 @@ -21,18 +21,18 @@ ARG stack_id="google" # Required by python/runtime. RUN apt-get update && apt-get install -y --no-install-recommends \ libexpat1 \ - libffi6 \ + libffi7 \ libmpdec2 \ && apt-get clean && rm -rf /var/lib/apt/lists/* # Required by dotnet/runtime. RUN apt-get update && apt-get install -y --no-install-recommends \ - libicu60 \ + libicu66 \ && apt-get clean && rm -rf /var/lib/apt/lists/* # Required by cpp/runtime. RUN apt-get update \ - && apt-get install -y libc++1-9 \ + && apt-get install -y libc++1-10 libc++abi1-10 \ && apt-get clean && rm -rf /var/lib/apt/lists/* LABEL io.buildpacks.stack.id=${stack_id} @@ -53,10 +53,8 @@ USER cnb FROM parent AS gcf-cpp-incremental-0 RUN apt-get update \ && apt install -y --no-install-recommends \ - build-essential g++-8 gcc-8 git libstdc++-8-dev pkg-config tar unzip zip \ + build-essential git pkg-config python3 tar unzip zip \ && apt-get clean && rm -rf /var/lib/apt/lists/* -RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100 \ - && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 100 # Install cmake, ninja and vcpkg. The first two are build systems for C++, the # latter is the package manager we use. In an open source builder these would @@ -65,7 +63,10 @@ RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100 \ FROM gcf-cpp-incremental-0 AS gcf-cpp-incremental-1 WORKDIR /usr/local -RUN curl -sSL https://github.com/Kitware/CMake/releases/download/v3.19.4/cmake-3.19.4-Linux-x86_64.tar.gz | \ +# Depending on the version of vcpkg, vcpkg may or may not prefer newer versions +# of cmake and will try to download it for every build_example. Instead, make +# sure we have already installed a suitable version of cmake. +RUN curl -sSL https://github.com/Kitware/CMake/releases/download/v3.29.8/cmake-3.29.8-Linux-x86_64.tar.gz | \ tar -xzf - --strip-components=1 RUN curl -sSL https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-linux.zip | \ @@ -73,7 +74,9 @@ RUN curl -sSL https://github.com/ninja-build/ninja/releases/download/v1.10.2/nin chmod 755 /usr/local/bin/ninja WORKDIR /usr/local/vcpkg -RUN curl -sSL https://github.com/Microsoft/vcpkg/archive/dfcd4e4b30799c4ce02fe3939b62576fec444224.tar.gz | \ +# This version of vcpkg should match the version in ci/pack/buildpack/bin/build +# otherwise the contents of the vcpkg cache may not be used. +RUN curl -sSL https://github.com/Microsoft/vcpkg/archive/2024.09.30.tar.gz | \ tar -xzf - --strip-components=1 && \ ./bootstrap-vcpkg.sh -disableMetrics -useSystemBinaries && \ rm -fr toolsrc/build.rel downloads/* @@ -96,29 +99,29 @@ FROM gcf-cpp-incremental-1 AS gcf-cpp-incremental-2 # These are needed by the Functions Framework, do them one at a time, easier to # rebuild the Docker image if one of them fails to download or something. -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug abseil -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug boost-core -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug openssl -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug boost-program-options -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug boost-asio -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug boost-beast -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug boost-serialization -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug nlohmann-json +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug abseil +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug boost-core +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug openssl +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug boost-program-options +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug boost-asio +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug boost-beast +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug boost-serialization +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug nlohmann-json # The following are not needed by the Functions Framework, but are used often # enough that it is a good idea to make them part of the base development # environment. Note that this automatically pulls abseil, grpc, protobuf, curl, # and a few other libraries. -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug curl -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug protobuf -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug grpc -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug google-cloud-cpp +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug curl +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug protobuf +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug grpc +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug google-cloud-cpp # Warmup the vcpkg cache for `functions-framework-cpp` using the release version # of the framework, this is the recommended path for users of the framework. FROM gcf-cpp-incremental-2 AS gcf-cpp-incremental-3 -RUN /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug functions-framework-cpp +RUN /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug functions-framework-cpp # This is the development image we recommend users create in their workstation. # It includes all the development tools, including cmake, ninja and vcpkg, as @@ -141,8 +144,11 @@ FROM gcf-cpp-incremental-2 AS gcf-cpp-ci-0 COPY . /usr/local/share/gcf RUN find /usr/local/share/gcf -type f | xargs chmod 644 RUN find /usr/local/share/gcf -type d | xargs chmod 755 +# More recent versions of cmake error when attempting to run `configure_file` on +# files owned by root. Changing the owner to user cnb fixes this. +RUN chown -R cnb:cnb /usr/local/share/gcf RUN VCPKG_OVERLAY_PORTS=/usr/local/share/gcf/build_scripts/vcpkg-overlays \ - /usr/local/vcpkg/vcpkg install --triplet x64-linux-nodebug functions-framework-cpp + /usr/local/vcpkg/vcpkg install --feature-flags=-manifests --triplet x64-linux-nodebug functions-framework-cpp # This is the image used for the CI builds, includes a binary cache of the # *current* version of `functions-framework-cpp`, as well as binary caches of diff --git a/build_scripts/vcpkg-overlays/portfile.cmake b/build_scripts/vcpkg-overlays/portfile.cmake index a9d34c23..1da9e3fa 100644 --- a/build_scripts/vcpkg-overlays/portfile.cmake +++ b/build_scripts/vcpkg-overlays/portfile.cmake @@ -1,10 +1,12 @@ set(SOURCE_PATH "/usr/local/share/gcf") -vcpkg_configure_cmake(SOURCE_PATH ${SOURCE_PATH} PREFER_NINJA - DISABLE_PARALLEL_CONFIGURE OPTIONS -DBUILD_TESTING=OFF) - -vcpkg_install_cmake(ADD_BIN_TO_PATH) +vcpkg_cmake_configure(SOURCE_PATH ${SOURCE_PATH} DISABLE_PARALLEL_CONFIGURE + OPTIONS -DBUILD_TESTING=OFF) +vcpkg_cmake_install(ADD_BIN_TO_PATH) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) +# vcpkg_fixup_cmake_targets is marked as deprecated and vcpkg_cmake_config_fixup +# is listed as its replacement. However, for our purposes, it is not a drop in +# replacement and additional work needs to be done if we are to switch. vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake TARGET_PATH share) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share) diff --git a/build_scripts/vcpkg-overlays/vcpkg.json b/build_scripts/vcpkg-overlays/vcpkg.json index e78ae9ba..1b35e8b2 100644 --- a/build_scripts/vcpkg-overlays/vcpkg.json +++ b/build_scripts/vcpkg-overlays/vcpkg.json @@ -1,6 +1,6 @@ { "name": "functions-framework-cpp", - "version-string": "0.6.0", + "version-string": "1.2.0", "homepage": "https://github.com/GoogleCloudPlatform/functions-framework-cpp/", "description": "Functions Framework for C++.", "dependencies": [ @@ -8,6 +8,14 @@ "boost-beast", "boost-program-options", "boost-serialization", - "nlohmann-json" + "nlohmann-json", + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } ] } diff --git a/ci/README.md b/ci/README.md index a91e3b7a..301a4c57 100644 --- a/ci/README.md +++ b/ci/README.md @@ -27,8 +27,14 @@ the name of the project you want to use. ## Enable the Services +Set the active project: + +```sh +gcloud config set project ${GOOGLE_CLOUD_PROJECT} +``` + ```sh -gcloud services enable --project="${GOOGLE_CLOUD_PROJECT}" \ +gcloud services enable \ bigtable.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ @@ -44,10 +50,8 @@ gcloud services enable --project="${GOOGLE_CLOUD_PROJECT}" \ ## Create Pub/Sub Topics ```sh -gcloud pubsub topics create testing \ - --project="${GOOGLE_CLOUD_PROJECT}" -gcloud pubsub topics create gcs-changes \ - --project="${GOOGLE_CLOUD_PROJECT}" +gcloud pubsub topics create testing +gcloud pubsub topics create gcs-changes ``` ## Create a Bucket @@ -77,7 +81,6 @@ Add this service account to the topic:Grant the ```shell gcloud pubsub topics add-iam-policy-binding \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --role="roles/pubsub.publisher" \ --member="serviceAccount:${GCS_SA}" \ gcs-changes @@ -98,7 +101,6 @@ readonly SA_ID="eventarc-trigger-sa" readonly SA_NAME="${SA_ID}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" gcloud iam service-accounts create "${SA_ID}" \ - "--project=${GOOGLE_CLOUD_PROJECT}" \ --description="Event Arg Triggers" ``` @@ -158,7 +160,6 @@ Create a Cloud Run deployment running the hello world example: ```sh gcloud run deploy gcf-hello-world-http \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-http:latest" \ --region="us-central1" \ --platform="managed" \ @@ -169,7 +170,6 @@ Test it by sending a request with `curl(1)`: ```sh HTTP_SERVICE_URL=$(gcloud run services describe \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --platform="managed" \ --region="us-central1" \ --format="value(status.url)" \ @@ -185,7 +185,6 @@ triggers: ```sh gcloud run deploy gcf-hello-world-pubsub \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-pubsub:latest" \ --region="us-central1" \ --platform="managed" \ @@ -199,7 +198,6 @@ PROJECT_NUMBER="$(gcloud projects list \ --filter="PROJECT_ID=${GOOGLE_CLOUD_PROJECT}" \ --format="value(project_number)")" gcloud beta eventarc triggers create gcf-hello-world-pubsub-trigger \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --location="us-central1" \ --destination-run-service="gcf-hello-world-pubsub" \ --destination-run-region="us-central1" \ @@ -210,7 +208,6 @@ Test by sending a message to the right topic: ```sh TOPIC=$(gcloud beta eventarc triggers describe gcf-hello-world-pubsub-trigger \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --location="us-central1" \ --format="value(transport.pubsub.topic)") NONCE=$(date +%s)-${RANDOM} @@ -221,7 +218,6 @@ And then verify this message shows up in the log: ```sh gcloud logging read \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --format="value(textPayload)" \ "resource.type=cloud_run_revision AND resource.labels.service_name=gcf-hello-world-pubsub AND logName:stdout" ``` @@ -233,7 +229,6 @@ triggers: ```sh gcloud run deploy gcf-hello-world-storage \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-storage:latest" \ --region="us-central1" \ --platform="managed" \ @@ -244,7 +239,6 @@ Create a trigger for Cloud Storage events: ```sh gcloud beta eventarc triggers create gcf-hello-world-storage-trigger \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --location="us-central1" \ --destination-run-service="gcf-hello-world-storage" \ --destination-run-region="us-central1" \ @@ -257,7 +251,6 @@ And then verify this message shows up in the log: ```sh gcloud logging read \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --format="value(textPayload)" \ "resource.type=cloud_run_revision AND resource.labels.service_name=gcf-hello-world-storage AND logName:stdout" ``` @@ -268,7 +261,6 @@ Finally verify this works by running the Cloud Build: ```sh gcloud builds submit \ - "--project=${GOOGLE_CLOUD_PROJECT}" \ "--substitutions=SHORT_SHA=$(git rev-parse --short HEAD)" \ "--config=ci/build-examples.yaml" ``` @@ -314,13 +306,11 @@ pack build -v \ "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-bigtable" docker push "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-bigtable" gcloud run deploy gcf-tutorial-cloud-bigtable \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-bigtable:latest" \ --region="us-central1" \ --platform="managed" \ --allow-unauthenticated BIGTABLE_SERVICE_URL=$(gcloud run services describe \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --platform="managed" \ --region="us-central1" \ --format="value(status.url)" \ @@ -333,7 +323,7 @@ curl -H "projectID: ${GOOGLE_CLOUD_PROJECT}" -H "instanceID: test-instance-0" -H Create the instance: ```shell -gcloud --project="${GOOGLE_CLOUD_PROJECT}" spanner instances create test-instance-0 \ +gcloud spanner instances create test-instance-0 \ --config="regional-us-central1" \ --description="Test instance for CI builds" \ --nodes=1 @@ -358,14 +348,12 @@ pack build -v \ "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-spanner" docker push "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-spanner" gcloud run deploy gcf-tutorial-cloud-spanner \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-tutorial-cloud-spanner:latest" \ --region="us-central1" \ --platform="managed" \ --set-env-vars=GOOGLE_CLOUD_PROJECT="${GOOGLE_CLOUD_PROJECT}",SPANNER_INSTANCE=test-instance-0,SPANNER_DATABASE=test-db \ --allow-unauthenticated SPANNER_SERVICE_URL=$(gcloud run services describe \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --platform="managed" \ --region="us-central1" \ --format="value(status.url)" \ diff --git a/ci/abi-dumps/functions_framework_cpp.expected.abi.dump.gz b/ci/abi-dumps/functions_framework_cpp.expected.abi.dump.gz index e66b40e3..14cba806 100644 Binary files a/ci/abi-dumps/functions_framework_cpp.expected.abi.dump.gz and b/ci/abi-dumps/functions_framework_cpp.expected.abi.dump.gz differ diff --git a/ci/build-examples.yaml b/ci/build-examples.yaml index 02782f5d..fdd24a50 100644 --- a/ci/build-examples.yaml +++ b/ci/build-examples.yaml @@ -1,6 +1,6 @@ # WARNING: DO NOT EDIT THIS FILE # This file is automatically generated by ci/generate-build-examples.sh -timeout: 3600s +timeout: 7200s options: machineType: 'N1_HIGHCPU_32' diskSizeGb: '512' @@ -15,6 +15,7 @@ steps: # Create the docker images for the buildpacks builder. - name: 'gcr.io/kaniko-project/executor:v1.12.0' + id: 'create run-image' args: [ "--context=dir:///workspace/", "--dockerfile=build_scripts/Dockerfile", @@ -26,9 +27,11 @@ steps: waitFor: ['-'] timeout: 1800s - name: 'gcr.io/cloud-builders/docker' + id: 'pull run-image' args: ['pull', 'gcr.io/${PROJECT_ID}/ci/run-image:${BUILD_ID}'] - name: 'gcr.io/kaniko-project/executor:v1.12.0' + id: 'create build-image' args: [ "--context=dir:///workspace/", "--dockerfile=build_scripts/Dockerfile", @@ -38,20 +41,25 @@ steps: "--destination=gcr.io/${PROJECT_ID}/ci/build-image:${BUILD_ID}", ] waitFor: ['-'] - timeout: 1800s + timeout: 3600s - name: 'gcr.io/cloud-builders/docker' + id: 'pull build-image' args: ['pull', 'gcr.io/${PROJECT_ID}/ci/build-image:${BUILD_ID}'] # Setup local names for the builder images. - name: 'gcr.io/cloud-builders/docker' + id: 'tag build-image' args: ['tag', 'gcr.io/${PROJECT_ID}/ci/build-image:${BUILD_ID}', 'ci-build-image:latest'] - name: 'gcr.io/cloud-builders/docker' + id: 'tag run-image' args: ['tag', 'gcr.io/${PROJECT_ID}/ci/run-image:${BUILD_ID}', 'ci-run-image:latest'] # Create the buildpacks builder, and make it the default. - name: 'pack' + id: 'create builder' args: ['builder', 'create', 'gcf-cpp-builder:bionic', '--config', 'ci/pack/builder.toml', ] - name: 'pack' + id: 'set builder as trusted' args: ['config', 'trusted-builders', 'add', 'gcf-cpp-builder:bionic', ] - name: 'pack' args: ['config', 'default-builder', 'gcf-cpp-builder:bionic', ] @@ -417,6 +425,7 @@ steps: # Remove the images created by this build. - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' allowFailure: true + id: 'delete images from this build' entrypoint: 'bash' args: - '-c' @@ -432,6 +441,7 @@ steps: # build does. - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' allowFailure: true + id: 'garbage collect old images' waitFor: ['-'] entrypoint: 'bash' args: diff --git a/ci/cloudbuild/builds/check-api.sh b/ci/cloudbuild/builds/check-api.sh index ac0a0dde..8f1e6cb9 100755 --- a/ci/cloudbuild/builds/check-api.sh +++ b/ci/cloudbuild/builds/check-api.sh @@ -21,26 +21,25 @@ export CXX=g++ source "$(dirname "$0")/../../lib/init.sh" source module ci/lib/io.sh +source module ci/cloudbuild/builds/lib/cmake.sh source module ci/cloudbuild/builds/lib/vcpkg.sh INSTALL_PREFIX=/var/tmp/functions-framework-cpp -vcpkg_root="$(vcpkg::root_dir)" # abi-dumper wants us to use -Og, but that causes bogus warnings about # uninitialized values with GCC, so we disable that warning with # -Wno-maybe-uninitialized. See also: # https://github.com/googleapis/google-cloud-cpp/issues/6313 io::log_h2 "Configuring, building, and installing the C++ Functions Framework" -cmake -GNinja \ +mapfile -t cmake_args < <(cmake::common_args) +mapfile -t vcpkg_args < <(vcpkg::cmake_args) +io::run cmake "${cmake_args[@]}" "${vcpkg_args[@]}" \ -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \ -DCMAKE_INSTALL_MESSAGE=NEVER \ -DBUILD_SHARED_LIBS=ON \ -DCMAKE_BUILD_TYPE=Debug \ - -DCMAKE_CXX_FLAGS="-Og -Wno-maybe-uninitialized" \ - -DCMAKE_TOOLCHAIN_FILE="${vcpkg_root}/scripts/buildsystems/vcpkg.cmake" \ - -DVCPKG_FEATURE_FLAGS="versions,manifest" \ - -S . -B cmake-out -cmake --build cmake-out -cmake --install cmake-out + -DCMAKE_CXX_FLAGS="-Og -Wno-maybe-uninitialized" +io::run cmake --build cmake-out +io::run cmake --install cmake-out # Uses `abi-dumper` to dump the ABI for the given library, which should be # installed at the given prefix. This function will be called from a subshell, diff --git a/ci/cloudbuild/builds/clang-16.0.sh b/ci/cloudbuild/builds/clang-16.0.sh new file mode 100755 index 00000000..98ae5c60 --- /dev/null +++ b/ci/cloudbuild/builds/clang-16.0.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +source "$(dirname "$0")/../../lib/init.sh" +source module ci/lib/io.sh +source module ci/cloudbuild/builds/lib/vcpkg.sh +source module ci/cloudbuild/builds/lib/cmake.sh + +io::log_h2 "Building with clang-tidy" +mapfile -t cmake_args < <(cmake::common_args) +mapfile -t vcpkg_args < <(vcpkg::cmake_args) +io::run cmake "${cmake_args[@]}" "${vcpkg_args[@]}" \ + -DFUNCTIONS_FRAMEWORK_CPP_ENABLE_WERROR=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_COMPILER=clang++ +io::run cmake --build cmake-out + +mapfile -t ctest_args < <(ctest::common_args) +io::run ctest "${ctest_args[@]}" diff --git a/ci/cloudbuild/builds/clang-tidy.sh b/ci/cloudbuild/builds/clang-tidy.sh new file mode 100755 index 00000000..9f961218 --- /dev/null +++ b/ci/cloudbuild/builds/clang-tidy.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +source "$(dirname "$0")/../../lib/init.sh" +source module ci/lib/io.sh +source module ci/cloudbuild/builds/lib/vcpkg.sh +source module ci/cloudbuild/builds/lib/cmake.sh + +io::log_h2 "Building with clang-tidy" +mapfile -t cmake_args < <(cmake::common_args) +mapfile -t vcpkg_args < <(vcpkg::cmake_args) +io::run cmake "${cmake_args[@]}" "${vcpkg_args[@]}" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_CLANG_TIDY=clang-tidy \ + -DCMAKE_CXX_COMPILER=clang++ +io::run cmake --build cmake-out diff --git a/ci/cloudbuild/builds/gcc-13.1.sh b/ci/cloudbuild/builds/gcc-13.1.sh new file mode 100755 index 00000000..8ede57bf --- /dev/null +++ b/ci/cloudbuild/builds/gcc-13.1.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +source "$(dirname "$0")/../../lib/init.sh" +source module ci/lib/io.sh +source module ci/cloudbuild/builds/lib/vcpkg.sh +source module ci/cloudbuild/builds/lib/cmake.sh + +io::log_h2 "Building with clang-tidy" +mapfile -t cmake_args < <(cmake::common_args) +mapfile -t vcpkg_args < <(vcpkg::cmake_args) +io::run cmake "${cmake_args[@]}" "${vcpkg_args[@]}" \ + -DFUNCTIONS_FRAMEWORK_CPP_ENABLE_WERROR=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_COMPILER=g++ +io::run cmake --build cmake-out + +mapfile -t ctest_args < <(ctest::common_args) +io::run ctest "${ctest_args[@]}" diff --git a/ci/cloudbuild/builds/lib/cmake.sh b/ci/cloudbuild/builds/lib/cmake.sh new file mode 100755 index 00000000..e7a5f8cb --- /dev/null +++ b/ci/cloudbuild/builds/lib/cmake.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Make our include guard clean against set -o nounset. +test -n "${CI_CLOUDBUILD_BUILDS_LIB_CMAKE_SH__:-}" || declare -i CI_CLOUDBUILD_BUILDS_LIB_CMAKE_SH__=0 +if ((CI_CLOUDBUILD_BUILDS_LIB_CMAKE_SH__++ != 0)); then + return 0 +fi # include guard + +function cmake::common_args() { + local binary="cmake-out" + if [[ $# -ge 1 ]]; then + binary="$1" + fi + local args + args=( + -G Ninja + -S . + -B "${binary}" + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + ) + printf "%s\n" "${args[@]}" +} + +function ctest::common_args() { + local binary="cmake-out" + if [[ $# -ge 1 ]]; then + binary="$1" + fi + local args + args=( + --test-dir "${binary}" + --output-on-failure + --timeout 60s + ) + printf "%s\n" "${args[@]}" +} diff --git a/ci/cloudbuild/builds/lib/vcpkg.sh b/ci/cloudbuild/builds/lib/vcpkg.sh index 0fa8d8a3..3b64041e 100644 --- a/ci/cloudbuild/builds/lib/vcpkg.sh +++ b/ci/cloudbuild/builds/lib/vcpkg.sh @@ -35,11 +35,25 @@ time { git -C "${VCPKG_ROOT_DIR}" checkout "${VCPKG_RELEASE_VERSION}" pwd fi - env -C "${VCPKG_ROOT_DIR}" CC="ccache ${CC}" CXX="ccache ${CXX}" \ - ./bootstrap-vcpkg.sh + env -C "${VCPKG_ROOT_DIR}" ./bootstrap-vcpkg.sh } # Outputs the root directory where vcpkg is installed (and bootstrapped) function vcpkg::root_dir() { echo "${VCPKG_ROOT_DIR}" } + +# Output common CMake configuration arguments +function vcpkg::cmake_args() { + local binary="cmake-out" + if [[ $# -ge 1 ]]; then + binary="$1" + fi + local args + args=( + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + -DCMAKE_TOOLCHAIN_FILE="${VCPKG_ROOT_DIR}/scripts/buildsystems/vcpkg.cmake" + -DVCPKG_FEATURE_FLAGS="versions,manifest" + ) + printf "%s\n" "${args[@]}" +} diff --git a/ci/cloudbuild/builds/sanitize-address.sh b/ci/cloudbuild/builds/sanitize-address.sh new file mode 100755 index 00000000..69b60cab --- /dev/null +++ b/ci/cloudbuild/builds/sanitize-address.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +export CC=clang +export CXX=clang++ + +source "$(dirname "$0")/../../lib/init.sh" +source module ci/lib/io.sh +source module ci/cloudbuild/builds/lib/vcpkg.sh +source module ci/cloudbuild/builds/lib/cmake.sh + +io::log_h2 "Building with Address Sanitizer" +mapfile -t cmake_args < <(cmake::common_args) +mapfile -t vcpkg_args < <(vcpkg::cmake_args) +io::run cmake "${cmake_args[@]}" "${vcpkg_args[@]}" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_FLAGS="-fsanitize=address -DGRPC_TSAN_SUPPRESSED -DGRPC_ASAN_SUPPRESSED" +io::run cmake --build cmake-out + +mapfile -t ctest_args < <(ctest::common_args) +io::run env ASAN_OPTIONS=detect_leaks=1:color=always ctest "${ctest_args[@]}" diff --git a/ci/cloudbuild/builds/sanitize-thread.sh b/ci/cloudbuild/builds/sanitize-thread.sh new file mode 100755 index 00000000..d438389b --- /dev/null +++ b/ci/cloudbuild/builds/sanitize-thread.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +export CC=clang +export CXX=clang++ + +source "$(dirname "$0")/../../lib/init.sh" +source module ci/lib/io.sh +source module ci/cloudbuild/builds/lib/vcpkg.sh +source module ci/cloudbuild/builds/lib/cmake.sh + +io::log_h2 "Building with Thread Sanitizer" +mapfile -t cmake_args < <(cmake::common_args) +mapfile -t vcpkg_args < <(vcpkg::cmake_args) +io::run cmake "${cmake_args[@]}" "${vcpkg_args[@]}" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_FLAGS="-fsanitize=thread -DGRPC_TSAN_SUPPRESSED -DGRPC_ASAN_SUPPRESSED" +io::run cmake --build cmake-out + +mapfile -t ctest_args < <(ctest::common_args) +io::run env TSAN_OPTIONS=halt_on_error=1:second_deadlock_stack=1 ctest "${ctest_args[@]}" diff --git a/ci/cloudbuild/builds/sanitize-undefined.sh b/ci/cloudbuild/builds/sanitize-undefined.sh new file mode 100755 index 00000000..6135325c --- /dev/null +++ b/ci/cloudbuild/builds/sanitize-undefined.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +export CC=clang +export CXX=clang++ + +source "$(dirname "$0")/../../lib/init.sh" +source module ci/lib/io.sh +source module ci/cloudbuild/builds/lib/vcpkg.sh +source module ci/cloudbuild/builds/lib/cmake.sh + +io::log_h2 "Building with Undefined Behavior Sanitizer" +mapfile -t cmake_args < <(cmake::common_args) +mapfile -t vcpkg_args < <(vcpkg::cmake_args) +io::run cmake "${cmake_args[@]}" "${vcpkg_args[@]}" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_FLAGS="-fsanitize=undefined -DGRPC_TSAN_SUPPRESSED -DGRPC_ASAN_SUPPRESSED" +io::run cmake --build cmake-out + +mapfile -t ctest_args < <(ctest::common_args) +io::run env UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 ctest "${ctest_args[@]}" diff --git a/ci/cloudbuild/cloudbuild.yaml b/ci/cloudbuild/cloudbuild.yaml index d63250a1..15cf6248 100644 --- a/ci/cloudbuild/cloudbuild.yaml +++ b/ci/cloudbuild/cloudbuild.yaml @@ -36,8 +36,8 @@ options: # Variables that can be overridden from the `gcloud builds ...` command using # the `--substitutions=_FOO=bar` flag. substitutions: - _DISTRO: 'fedora-34' - _BUILD_NAME: 'check-api' + _DISTRO: 'unknown' + _BUILD_NAME: 'unknown' _CACHE_BUCKET: '${PROJECT_ID}_cloudbuild' _IMAGE: 'functions-framework-cpp/${_DISTRO}' _TRIGGER_SOURCE: '${_PR_NUMBER:-main}' @@ -45,7 +45,7 @@ substitutions: _LOGS_BUCKET: 'cloud-cpp-community-publiclogs' steps: - - name: 'gcr.io/kaniko-project/executor:v1.12.0' + - name: 'gcr.io/kaniko-project/executor:v1.23.1' args: [ '--log-format=text', '--context=dir:///workspace/ci', diff --git a/ci/cloudbuild/dockerfiles/fedora-34.Dockerfile b/ci/cloudbuild/dockerfiles/fedora-38.Dockerfile similarity index 90% rename from ci/cloudbuild/dockerfiles/fedora-34.Dockerfile rename to ci/cloudbuild/dockerfiles/fedora-38.Dockerfile index 4ef17d42..07f9d300 100644 --- a/ci/cloudbuild/dockerfiles/fedora-34.Dockerfile +++ b/ci/cloudbuild/dockerfiles/fedora-38.Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2021 Google LLC +# Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM fedora:34 +FROM fedora:38 ARG NCPU=4 # Installs the development tools needed by functions-framework-cpp and its @@ -22,10 +22,13 @@ RUN dnf makecache && \ ccache clang clang-analyzer clang-tools-extra \ cmake diffutils doxygen findutils gcc-c++ git \ lcov libcxx-devel libcxxabi-devel \ - libasan libubsan libtsan libcurl-devel make ninja-build \ - openssl-devel patch python python3.8 \ + libasan libubsan libtsan llvm libcurl-devel make ninja-build \ + openssl-devel patch python python3 \ python-pip tar unzip w3m wget which zip zlib-devel +# This is needed to compile OpenSSL with vcpkg +RUN dnf makecache && dnf install -y perl-IPC-Cmd + # Installs Universal Ctags (which is different than the default "Exuberant # Ctags"), which is needed by the ABI checker. See https://ctags.io/ WORKDIR /var/tmp/build diff --git a/ci/cloudbuild/triggers/check-api-ci.yaml b/ci/cloudbuild/triggers/check-api-ci.yaml index ef56772b..18093ede 100644 --- a/ci/cloudbuild/triggers/check-api-ci.yaml +++ b/ci/cloudbuild/triggers/check-api-ci.yaml @@ -7,7 +7,7 @@ github: name: check-api-ci substitutions: _BUILD_NAME: check-api - _DISTRO: fedora-34 + _DISTRO: fedora-38 _TRIGGER_TYPE: ci includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS tags: diff --git a/ci/cloudbuild/triggers/check-api-pr.yaml b/ci/cloudbuild/triggers/check-api-pr.yaml index 1b337f98..d9f38968 100644 --- a/ci/cloudbuild/triggers/check-api-pr.yaml +++ b/ci/cloudbuild/triggers/check-api-pr.yaml @@ -8,7 +8,7 @@ github: name: check-api-pr substitutions: _BUILD_NAME: check-api - _DISTRO: fedora-34 + _DISTRO: fedora-38 _TRIGGER_TYPE: pr includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS tags: diff --git a/ci/cloudbuild/triggers/clang-16-0-ci.yaml b/ci/cloudbuild/triggers/clang-16-0-ci.yaml new file mode 100644 index 00000000..b096960c --- /dev/null +++ b/ci/cloudbuild/triggers/clang-16-0-ci.yaml @@ -0,0 +1,14 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + push: + branch: ^(main|v\d+\..*)$ +name: clang-16-0-ci +substitutions: + _BUILD_NAME: clang-16.0 + _DISTRO: fedora-38 + _TRIGGER_TYPE: ci +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- ci diff --git a/ci/cloudbuild/triggers/clang-16-0-pr.yaml b/ci/cloudbuild/triggers/clang-16-0-pr.yaml new file mode 100644 index 00000000..d6dd3b25 --- /dev/null +++ b/ci/cloudbuild/triggers/clang-16-0-pr.yaml @@ -0,0 +1,15 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + pullRequest: + branch: ^(main|v\d+\..*)$ + commentControl: COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY +name: clang-16-0-pr +substitutions: + _BUILD_NAME: clang-16.0 + _DISTRO: fedora-38 + _TRIGGER_TYPE: pr +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- pr diff --git a/ci/cloudbuild/triggers/clang-tidy-ci.yaml b/ci/cloudbuild/triggers/clang-tidy-ci.yaml new file mode 100644 index 00000000..650d3339 --- /dev/null +++ b/ci/cloudbuild/triggers/clang-tidy-ci.yaml @@ -0,0 +1,14 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + push: + branch: ^(main|v\d+\..*)$ +name: clang-tidy-ci +substitutions: + _BUILD_NAME: clang-tidy + _DISTRO: fedora-38 + _TRIGGER_TYPE: ci +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- ci diff --git a/ci/cloudbuild/triggers/clang-tidy-pr.yaml b/ci/cloudbuild/triggers/clang-tidy-pr.yaml new file mode 100644 index 00000000..17344ead --- /dev/null +++ b/ci/cloudbuild/triggers/clang-tidy-pr.yaml @@ -0,0 +1,15 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + pullRequest: + branch: ^(main|v\d+\..*)$ + commentControl: COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY +name: clang-tidy-pr +substitutions: + _BUILD_NAME: clang-tidy + _DISTRO: fedora-38 + _TRIGGER_TYPE: pr +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- pr diff --git a/ci/cloudbuild/triggers/gcc-13-1-ci.yaml b/ci/cloudbuild/triggers/gcc-13-1-ci.yaml new file mode 100644 index 00000000..45c257e8 --- /dev/null +++ b/ci/cloudbuild/triggers/gcc-13-1-ci.yaml @@ -0,0 +1,14 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + push: + branch: ^(main|v\d+\..*)$ +name: gcc-13-1-ci +substitutions: + _BUILD_NAME: gcc-13.1 + _DISTRO: fedora-38 + _TRIGGER_TYPE: ci +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- ci diff --git a/ci/cloudbuild/triggers/gcc-13-1-pr.yaml b/ci/cloudbuild/triggers/gcc-13-1-pr.yaml new file mode 100644 index 00000000..45190c1d --- /dev/null +++ b/ci/cloudbuild/triggers/gcc-13-1-pr.yaml @@ -0,0 +1,15 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + pullRequest: + branch: ^(main|v\d+\..*)$ + commentControl: COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY +name: gcc-13-1-pr +substitutions: + _BUILD_NAME: gcc-13.1 + _DISTRO: fedora-38 + _TRIGGER_TYPE: pr +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- pr diff --git a/ci/cloudbuild/triggers/sanitize-address-ci.yaml b/ci/cloudbuild/triggers/sanitize-address-ci.yaml new file mode 100644 index 00000000..96b6ae38 --- /dev/null +++ b/ci/cloudbuild/triggers/sanitize-address-ci.yaml @@ -0,0 +1,14 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + push: + branch: ^(main|v\d+\..*)$ +name: sanitize-address-ci +substitutions: + _BUILD_NAME: sanitize-address + _DISTRO: fedora-38 + _TRIGGER_TYPE: ci +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- ci diff --git a/ci/cloudbuild/triggers/sanitize-address-pr.yaml b/ci/cloudbuild/triggers/sanitize-address-pr.yaml new file mode 100644 index 00000000..a910f505 --- /dev/null +++ b/ci/cloudbuild/triggers/sanitize-address-pr.yaml @@ -0,0 +1,15 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + pullRequest: + branch: ^(main|v\d+\..*)$ + commentControl: COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY +name: sanitize-address-pr +substitutions: + _BUILD_NAME: sanitize-address + _DISTRO: fedora-38 + _TRIGGER_TYPE: pr +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- pr diff --git a/ci/cloudbuild/triggers/sanitize-thread-ci.yaml b/ci/cloudbuild/triggers/sanitize-thread-ci.yaml new file mode 100644 index 00000000..358bcab8 --- /dev/null +++ b/ci/cloudbuild/triggers/sanitize-thread-ci.yaml @@ -0,0 +1,14 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + push: + branch: ^(main|v\d+\..*)$ +name: sanitize-thread-ci +substitutions: + _BUILD_NAME: sanitize-thread + _DISTRO: fedora-38 + _TRIGGER_TYPE: ci +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- ci diff --git a/ci/cloudbuild/triggers/sanitize-thread-pr.yaml b/ci/cloudbuild/triggers/sanitize-thread-pr.yaml new file mode 100644 index 00000000..bdb4efe9 --- /dev/null +++ b/ci/cloudbuild/triggers/sanitize-thread-pr.yaml @@ -0,0 +1,15 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + pullRequest: + branch: ^(main|v\d+\..*)$ + commentControl: COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY +name: sanitize-thread-pr +substitutions: + _BUILD_NAME: sanitize-thread + _DISTRO: fedora-38 + _TRIGGER_TYPE: pr +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- pr diff --git a/ci/cloudbuild/triggers/sanitize-undefined-ci.yaml b/ci/cloudbuild/triggers/sanitize-undefined-ci.yaml new file mode 100644 index 00000000..76b943cf --- /dev/null +++ b/ci/cloudbuild/triggers/sanitize-undefined-ci.yaml @@ -0,0 +1,14 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + push: + branch: ^(main|v\d+\..*)$ +name: sanitize-undefined-ci +substitutions: + _BUILD_NAME: sanitize-undefined + _DISTRO: fedora-38 + _TRIGGER_TYPE: ci +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- ci diff --git a/ci/cloudbuild/triggers/sanitize-undefined-pr.yaml b/ci/cloudbuild/triggers/sanitize-undefined-pr.yaml new file mode 100644 index 00000000..6141eb18 --- /dev/null +++ b/ci/cloudbuild/triggers/sanitize-undefined-pr.yaml @@ -0,0 +1,15 @@ +filename: ci/cloudbuild/cloudbuild.yaml +github: + name: functions-framework-cpp + owner: GoogleCloudPlatform + pullRequest: + branch: ^(main|v\d+\..*)$ + commentControl: COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY +name: sanitize-undefined-pr +substitutions: + _BUILD_NAME: sanitize-undefined + _DISTRO: fedora-38 + _TRIGGER_TYPE: pr +includeBuildLogs: INCLUDE_BUILD_LOGS_WITH_STATUS +tags: +- pr diff --git a/ci/etc/vcpkg-config.sh b/ci/etc/vcpkg-config.sh index 3045c56d..60a84114 100644 --- a/ci/etc/vcpkg-config.sh +++ b/ci/etc/vcpkg-config.sh @@ -23,4 +23,4 @@ fi # include guard # # Common configuration parameters. # -export VCPKG_RELEASE_VERSION="7e7bcf89171b7ed84ece845b1fa596a018e462f2" +export VCPKG_RELEASE_VERSION="2024.09.30" diff --git a/ci/generate-build-examples.sh b/ci/generate-build-examples.sh index 38dda597..93b0605b 100755 --- a/ci/generate-build-examples.sh +++ b/ci/generate-build-examples.sh @@ -18,7 +18,7 @@ set -eu cat <<'_EOF_' # WARNING: DO NOT EDIT THIS FILE # This file is automatically generated by ci/generate-build-examples.sh -timeout: 3600s +timeout: 7200s options: machineType: 'N1_HIGHCPU_32' diskSizeGb: '512' @@ -33,6 +33,7 @@ steps: # Create the docker images for the buildpacks builder. - name: 'gcr.io/kaniko-project/executor:v1.12.0' + id: 'create run-image' args: [ "--context=dir:///workspace/", "--dockerfile=build_scripts/Dockerfile", @@ -44,9 +45,11 @@ steps: waitFor: ['-'] timeout: 1800s - name: 'gcr.io/cloud-builders/docker' + id: 'pull run-image' args: ['pull', 'gcr.io/${PROJECT_ID}/ci/run-image:${BUILD_ID}'] - name: 'gcr.io/kaniko-project/executor:v1.12.0' + id: 'create build-image' args: [ "--context=dir:///workspace/", "--dockerfile=build_scripts/Dockerfile", @@ -56,20 +59,25 @@ steps: "--destination=gcr.io/${PROJECT_ID}/ci/build-image:${BUILD_ID}", ] waitFor: ['-'] - timeout: 1800s + timeout: 3600s - name: 'gcr.io/cloud-builders/docker' + id: 'pull build-image' args: ['pull', 'gcr.io/${PROJECT_ID}/ci/build-image:${BUILD_ID}'] # Setup local names for the builder images. - name: 'gcr.io/cloud-builders/docker' + id: 'tag build-image' args: ['tag', 'gcr.io/${PROJECT_ID}/ci/build-image:${BUILD_ID}', 'ci-build-image:latest'] - name: 'gcr.io/cloud-builders/docker' + id: 'tag run-image' args: ['tag', 'gcr.io/${PROJECT_ID}/ci/run-image:${BUILD_ID}', 'ci-run-image:latest'] # Create the buildpacks builder, and make it the default. - name: 'pack' + id: 'create builder' args: ['builder', 'create', 'gcf-cpp-builder:bionic', '--config', 'ci/pack/builder.toml', ] - name: 'pack' + id: 'set builder as trusted' args: ['config', 'trusted-builders', 'add', 'gcf-cpp-builder:bionic', ] - name: 'pack' args: ['config', 'default-builder', 'gcf-cpp-builder:bionic', ] @@ -213,6 +221,7 @@ cat <<_EOF_ # Remove the images created by this build. - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' allowFailure: true + id: 'delete images from this build' entrypoint: 'bash' args: - '-c' @@ -228,6 +237,7 @@ cat <<_EOF_ # build does. - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' allowFailure: true + id: 'garbage collect old images' waitFor: ['-'] entrypoint: 'bash' args: diff --git a/ci/pack/buildpack/bin/build b/ci/pack/buildpack/bin/build index 61cb5103..b6802074 100755 --- a/ci/pack/buildpack/bin/build +++ b/ci/pack/buildpack/bin/build @@ -31,7 +31,9 @@ fi if [[ ! -d "${VCPKG_ROOT}" ]]; then echo "-----> Install vcpkg" mkdir -p "${VCPKG_ROOT}" - curl -sSL https://github.com/Microsoft/vcpkg/archive/dfcd4e4b30799c4ce02fe3939b62576fec444224.tar.gz | \ + # This version of vcpkg should match the version in build_scripts/Dockerfile + # otherwise the contents of the vcpkg cache may not be used. + curl -sSL https://github.com/Microsoft/vcpkg/archive/2024.09.30.tar.gz | \ tar -C "${VCPKG_ROOT}" -xzf - --strip-components=1 cat >"${VCPKG_ROOT}/triplets/x64-linux-nodebug.cmake" <<_EOF_ set(VCPKG_BUILD_TYPE release) @@ -131,9 +133,9 @@ generate_http_main_no_namespace() { cat <<_EOF_ #include namespace gcf = ::google::cloud::functions; -extern gcf::HttpResponse ${function}(gcf::HttpRequest); +extern gcf::Function ${function}(); int main(int argc, char* argv[]) { - return gcf::Run(argc, argv, gcf::UserHttpFunction(${function})); + return gcf::Run(argc, argv, ${function}()); } _EOF_ } @@ -146,10 +148,10 @@ generate_http_main_with_namespace() { #include namespace gcf = ::google::cloud::functions; namespace ${namespace} { - extern gcf::HttpResponse ${function}(gcf::HttpRequest); + extern gcf::Function ${function}(); } // namespace int main(int argc, char* argv[]) { - return gcf::Run(argc, argv, gcf::UserHttpFunction(::${namespace}::${function})); + return gcf::Run(argc, argv, ::${namespace}::${function}()); } _EOF_ } @@ -159,9 +161,9 @@ generate_cloud_event_main_no_namespace() { cat <<_EOF_ #include namespace gcf = ::google::cloud::functions; -extern void ${function}(gcf::CloudEvent); +extern gcf::Function ${function}(); int main(int argc, char* argv[]) { - return gcf::Run(argc, argv, gcf::UserCloudEventFunction(${function})); + return gcf::Run(argc, argv, ${function}()); } _EOF_ } @@ -174,10 +176,10 @@ generate_cloud_event_main_with_namespace() { #include namespace gcf = ::google::cloud::functions; namespace ${namespace} { - extern void ${function}(gcf::CloudEvent); + extern gcf::Function ${function}(); } // namespace int main(int argc, char* argv[]) { - return gcf::Run(argc, argv, gcf::UserCloudEventFunction(::${namespace}::${function})); + return gcf::Run(argc, argv, ::${namespace}::${function}()); } _EOF_ } @@ -266,12 +268,16 @@ cache = true launch = false _EOF_ -/usr/local/bin/cmake -S "${layers}/source" -B "${layers}/binary" -GNinja -DCMAKE_MAKE_PROGRAM=/usr/local/bin/ninja \ +echo "--> cmake configure" +/usr/local/bin/cmake -S "${layers}/source" -B "${layers}/binary" \ + -GNinja -DCMAKE_MAKE_PROGRAM=/usr/local/bin/ninja \ -DCNB_APP_DIR="${PWD}" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX="${layers}/local" \ -DVCPKG_TARGET_TRIPLET="${VCPKG_DEFAULT_TRIPLET}" \ -DCMAKE_TOOLCHAIN_FILE="${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + +echo "--> cmake build" /usr/local/bin/cmake --build "${layers}/binary" --target install cat >"${layers}/local.toml" <<_EOF_ diff --git a/examples/README.md b/examples/README.md index c3ad8448..65ac5666 100644 --- a/examples/README.md +++ b/examples/README.md @@ -80,7 +80,7 @@ docker kill ${ID} ## Deploying to Cloud Run This example assumes that `GOOGLE_CLOUD_PROJECT` is set to a GCP project with -the right services enabled: +the correct services enabled: ```sh GOOGLE_CLOUD_PROJECT=... # use a real project @@ -102,11 +102,16 @@ Push this image to Google Container Registry: docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-world:latest ``` +Set the active project: + +```sh +gcloud config set project ${GOOGLE_CLOUD_PROJECT} +``` + Deploy this application to Cloud Run: ```sh gcloud run deploy gcf-cpp-hello \ - "--project=${GOOGLE_CLOUD_PROJECT}" \ "--image=gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-world:latest" \ "--region=${GOOGLE_CLOUD_REGION}" \ "--platform=managed" \ @@ -117,7 +122,6 @@ Fetch the service URL: ```bash SERVICE_URL=$(gcloud run services list \ - "--project=${GOOGLE_CLOUD_PROJECT}" \ "--platform=managed" \ '--format=csv[no-heading](URL)' \ "--filter=SERVICE:gcf-cpp-hello") diff --git a/examples/howto_use_legacy_code/README.md b/examples/howto_use_legacy_code/README.md index 5b3e7e11..f3d9d3d9 100644 --- a/examples/howto_use_legacy_code/README.md +++ b/examples/howto_use_legacy_code/README.md @@ -14,7 +14,11 @@ any external tool to compile some code. Often this function also downloads the code from some external repository, but it can use code in your source tree. -[ExternalProject_Add]: https://cmake.org/cmake/help/latest/module/ExternalProject.html +> **WARNING:** The development version of this document may not work with the +> released version of the functions framework. Please use this document as it +> appears in the [corresponding release][github-releases] if you are using a +> released version of the library. In particular, buildpacks use the latest +> release. ## Installing Dependencies @@ -146,3 +150,5 @@ You can just interrupt (`Ctrl-C`) the program to terminate it. [vcpkg-install]: https://github.com/microsoft/vcpkg#getting-started [cmake]: https://cmake.org [cmake-install]: https://cmake.org/install/ +[ExternalProject_Add]: https://cmake.org/cmake/help/latest/module/ExternalProject.html +[github-releases]: https://github.com/GoogleCloudPlatform/functions-framework-cpp/releases diff --git a/examples/site/howto_create_container/README.md b/examples/site/howto_create_container/README.md index 34e8818f..d4d7ca10 100644 --- a/examples/site/howto_create_container/README.md +++ b/examples/site/howto_create_container/README.md @@ -3,6 +3,12 @@ This guide shows you how to create a container image for an example function, and how to run said image in a local container on your workstation. +> **WARNING:** The development version of this document may not work with the +> released version of the functions framework. Please use this document as it +> appears in the [corresponding release][github-releases] if you are using a +> released version of the library. In particular, buildpacks use the latest +> release. + ## Pre-requisites Verify the [docker tool][docker] is functional on your workstation: @@ -132,3 +138,4 @@ docker image rm gcf-cpp-hello-world-http [sudoless docker]: https://docs.docker.com/engine/install/linux-postinstall/ [pack-install]: https://buildpacks.io/docs/install-pack/ [Google Cloud buildpack]: https://github.com/GoogleCloudPlatform/buildpacks +[github-releases]: https://github.com/GoogleCloudPlatform/functions-framework-cpp/releases diff --git a/examples/site/howto_deploy_cloud_event/README.md b/examples/site/howto_deploy_cloud_event/README.md index 80c1b6c2..cc68cd5f 100644 --- a/examples/site/howto_deploy_cloud_event/README.md +++ b/examples/site/howto_deploy_cloud_event/README.md @@ -1,5 +1,14 @@ # How-to Guide: Deploy a C++ Pub/Sub function to Cloud Run +This guide shows how to deploy a C++ function consuming cloud events to +[Cloud Run]. + +> **WARNING:** The development version of this document may not work with the +> released version of the functions framework. Please use this document as it +> appears in the [corresponding release][github-releases] if you are using a +> released version of the library. In particular, buildpacks use the latest +> release. + ## Pre-requisites This guide assumes you are familiar with Google Cloud, and that you have a GCP @@ -108,9 +117,14 @@ To deploy this image in Cloud Run use this command. You need to select a Cloud Run region for your deployment. We will use `us-central1` in this guide: +Set the active project: + +```sh +gcloud config set project ${GOOGLE_CLOUD_PROJECT} +``` + ```shell gcloud run deploy gcf-cpp-hello-world-pubsub \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-cpp-hello-world-pubsub:latest" \ --region="us-central1" \ --platform="managed" \ @@ -121,7 +135,6 @@ Verify unauthenticated requests are allowed: ```shell gcloud run services get-iam-policy gcf-cpp-hello-world-pubsub \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --region="us-central1" \ --platform="managed" ``` @@ -143,7 +156,6 @@ proceed run this command (maybe with an addition `--topic-transport` option): ```shell gcloud beta eventarc triggers create gcf-cpp-hello-world-pubsub-trigger \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --location="us-central1" \ --destination-run-service="gcf-cpp-hello-world-pubsub" \ --destination-run-region="us-central1" \ @@ -154,7 +166,6 @@ Find out what topic is used to this new trigger: ```shell TOPIC=$(gcloud beta eventarc triggers describe gcf-cpp-hello-world-pubsub-trigger \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --location="us-central1" \ --format="value(transport.pubsub.topic)") ``` @@ -172,7 +183,6 @@ to verify the Pub/Sub message was received: ```shell gcloud logging read \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --format="value(textPayload)" \ "resource.type=cloud_run_revision AND resource.labels.service_name=gcf-cpp-hello-world-pubsub AND logName:stdout" # Output: Hello Event @@ -184,7 +194,6 @@ Delete the trigger: ```shell gcloud beta eventarc triggers delete gcf-cpp-hello-world-pubsub-trigger \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --location="us-central1" ``` @@ -192,7 +201,6 @@ Delete the Cloud Run deployment: ```sh gcloud run services delete gcf-cpp-hello-world-pubsub \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --region="us-central1" \ --platform="managed" ``` @@ -215,3 +223,5 @@ gcloud container images delete \ [pack-install]: https://buildpacks.io/docs/install-pack/ [gcloud-eventarc-create]: https://cloud.google.com/sdk/gcloud/reference/beta/eventarc/triggers/create [Google Cloud buildpack]: https://github.com/GoogleCloudPlatform/buildpacks +[Cloud Run]: https://cloud.google.com/run +[github-releases]: https://github.com/GoogleCloudPlatform/functions-framework-cpp/releases diff --git a/examples/site/howto_deploy_to_cloud_run/README.md b/examples/site/howto_deploy_to_cloud_run/README.md index ec58f57d..09622bdd 100644 --- a/examples/site/howto_deploy_to_cloud_run/README.md +++ b/examples/site/howto_deploy_to_cloud_run/README.md @@ -1,14 +1,13 @@ # How-to Guide: Deploy your function to Cloud Run -[repository-gh]: https://github.com/GoogleCloudPlatform/functions-framework-cpp -[howto-create-container]: /examples/site/howto_create_container/README.md -[cloud-run-quickstarts]: https://cloud.google.com/run/docs/quickstarts -[gcp-quickstarts]: https://cloud.google.com/resource-manager/docs/creating-managing-projects -[buildpacks]: https://buildpacks.io -[docker]: https://docker.com/ -[docker-install]: https://store.docker.com/search?type=edition&offering=community -[sudoless docker]: https://docs.docker.com/engine/install/linux-postinstall/ -[pack-install]: https://buildpacks.io/docs/install-pack/ +This guide shows how to deploy a C++ function handling HTTP requests to +[Cloud Run]. + +> **WARNING:** The development version of this document may not work with the +> released version of the functions framework. Please use this document as it +> appears in the [corresponding release][github-releases] if you are using a +> released version of the library. In particular, buildpacks use the latest +> release. ## Pre-requisites @@ -120,9 +119,14 @@ To deploy this image in Cloud Run use this command. You need to select a Cloud Run region for your deployment. We will use `us-central1` in this guide: +Set the active project: + +```sh +gcloud config set project ${GOOGLE_CLOUD_PROJECT} +``` + ```sh gcloud run deploy gcf-cpp-hello-world-http \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-cpp-hello-world-http:latest" \ --region="us-central1" \ --platform="managed" \ @@ -135,7 +139,6 @@ Find out what URL was assigned to your function, and use `curl` to send a reques ```shell HTTP_SERVICE_URL=$(gcloud run services describe \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --platform="managed" \ --region="us-central1" \ --format="value(status.url)" \ @@ -151,7 +154,6 @@ Delete the Cloud Run deployment: ```sh gcloud run services delete gcf-cpp-hello-world-http \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --region="us-central1" \ --platform="managed" ``` @@ -162,3 +164,15 @@ And the container image: gcloud container images delete \ "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-cpp-hello-world-http:latest" ``` + +[repository-gh]: https://github.com/GoogleCloudPlatform/functions-framework-cpp +[howto-create-container]: /examples/site/howto_create_container/README.md +[cloud-run-quickstarts]: https://cloud.google.com/run/docs/quickstarts +[gcp-quickstarts]: https://cloud.google.com/resource-manager/docs/creating-managing-projects +[buildpacks]: https://buildpacks.io +[docker]: https://docker.com/ +[docker-install]: https://store.docker.com/search?type=edition&offering=community +[sudoless docker]: https://docs.docker.com/engine/install/linux-postinstall/ +[pack-install]: https://buildpacks.io/docs/install-pack/ +[Cloud Run]: https://cloud.google.com/run +[github-releases]: https://github.com/GoogleCloudPlatform/functions-framework-cpp/releases diff --git a/examples/site/howto_local_development/README.md b/examples/site/howto_local_development/README.md index 2792bcaf..bbb8a47c 100644 --- a/examples/site/howto_local_development/README.md +++ b/examples/site/howto_local_development/README.md @@ -4,6 +4,12 @@ This guide describes how to compile and run a function locally. This can be useful when writing unit test, or to accelerate the edit -> compile -> test cycle. +> **WARNING:** The development version of this document may not work with the +> released version of the functions framework. Please use this document as it +> appears in the [corresponding release][github-releases] if you are using a +> released version of the library. In particular, buildpacks use the latest +> release. + ## Installing Dependencies Because the Functions Framework for C++ uses C++17, you will need a working C++ @@ -134,3 +140,4 @@ You can just interrupt (`Ctrl-C`) the program to terminate it. [vcpkg-install]: https://github.com/microsoft/vcpkg#getting-started [cmake]: https://cmake.org [cmake-install]: https://cmake.org/install/ +[github-releases]: https://github.com/GoogleCloudPlatform/functions-framework-cpp/releases diff --git a/examples/site/http_content/http_content.cc b/examples/site/http_content/http_content.cc index e52b107a..5d586e7e 100644 --- a/examples/site/http_content/http_content.cc +++ b/examples/site/http_content/http_content.cc @@ -66,7 +66,7 @@ std::string urldecode(std::string const& encoded) { auto const* end = encoded.data() + i + 3; auto r = std::from_chars(encoded.data() + i + 1, end, value, kUrlEncodingBase); - if (r.ptr == end) { + if (r.ec == std::errc{} && r.ptr == end) { result.push_back(value); i += 2; } else { diff --git a/examples/site/http_form_data/http_form_data.cc b/examples/site/http_form_data/http_form_data.cc index 06f4aee5..2f5e8e72 100644 --- a/examples/site/http_form_data/http_form_data.cc +++ b/examples/site/http_form_data/http_form_data.cc @@ -73,10 +73,10 @@ gcf::HttpResponse http_form_data_impl(gcf::HttpRequest request) { auto delimiter = FormDataDelimiter::FromHeader(header->second); auto payload = std::move(request).payload(); - std::vector parts = + std::vector const parts = absl::StrSplit(payload, delimiter, absl::SkipEmpty{}); nlohmann::json result{{"parts", std::vector{}}}; - for (auto& p : parts) { + for (auto const& p : parts) { std::vector components = absl::StrSplit(p, absl::MaxSplits("\r\n\r\n", 2)); auto const body_size = components.size() == 2 ? components[0].size() : 0; diff --git a/examples/site/testing_pubsub/README.md b/examples/site/testing_pubsub/README.md index 2bcd6958..d572b754 100644 --- a/examples/site/testing_pubsub/README.md +++ b/examples/site/testing_pubsub/README.md @@ -80,12 +80,17 @@ pack build \ "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-pubsub" ``` +Set the active project: + +```sh +gcloud config set project ${GOOGLE_CLOUD_PROJECT} +``` + Deploy this function to Cloud Run: ```shell docker push "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-pubsub" gcloud run deploy gcf-hello-world-storage \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-pubsub:latest" \ --region="us-central1" \ --platform="managed" \ @@ -96,7 +101,6 @@ Setup a Pub/Sub trigger: ```shell gcloud beta eventarc triggers create gcf-hello-world-pubsub-trigger \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --location="us-central1" \ --destination-run-service="gcf-hello-world-pubsub" \ --destination-run-region="us-central1" \ diff --git a/examples/site/testing_pubsub/pubsub_integration_test.cc b/examples/site/testing_pubsub/pubsub_integration_test.cc index 51fa2df0..e0fc489c 100644 --- a/examples/site/testing_pubsub/pubsub_integration_test.cc +++ b/examples/site/testing_pubsub/pubsub_integration_test.cc @@ -92,10 +92,10 @@ TEST_F(PubsubIntegrationTest, Basic) { } })js"); - struct TestCases { + struct { std::string data; std::string expected; - } cases[]{ + } const cases[]{ // The magic string was obtained using: // /bin/echo -n 'C++' | openssl base64 -e {"Qysr", "Hello C++"}, diff --git a/examples/site/testing_pubsub/pubsub_system_test.cc b/examples/site/testing_pubsub/pubsub_system_test.cc index f010d725..2fa05d9a 100644 --- a/examples/site/testing_pubsub/pubsub_system_test.cc +++ b/examples/site/testing_pubsub/pubsub_system_test.cc @@ -13,8 +13,8 @@ // limitations under the License. // [START functions_pubsub_system_test] +#include #include -#include #include #include #include @@ -26,6 +26,7 @@ namespace { namespace bp = ::boost::process; namespace pubsub = ::google::cloud::pubsub; +namespace pubsub_admin = ::google::cloud::pubsub_admin; using ::testing::AnyOf; using ::testing::HasSubstr; @@ -43,9 +44,10 @@ class PubsubSystemTest : public ::testing::Test { // Automatically setup the test environment, create the topic if it does // not exist. - auto admin = pubsub::TopicAdminClient(pubsub::MakeTopicAdminConnection()); + auto admin = pubsub_admin::TopicAdminClient( + pubsub_admin::MakeTopicAdminConnection()); topic_ = pubsub::Topic(project_id, topic_id); - auto topic_metadata = admin.CreateTopic(pubsub::TopicBuilder(topic())); + auto topic_metadata = admin.CreateTopic(topic_.FullName()); // If we get an error other than kAlreadyExists, abort the test. ASSERT_THAT(topic_metadata.status().code(), AnyOf(google::cloud::StatusCode::kOk, @@ -63,16 +65,15 @@ class PubsubSystemTest : public ::testing::Test { }; TEST_F(PubsubSystemTest, Basic) { - struct TestCases { + struct { std::string data; std::string expected; - } cases[]{ + } const cases[]{ {"C++", "Hello C++"}, {"World", "Hello World"}, }; - auto publisher = - pubsub::Publisher(pubsub::MakePublisherConnection(topic(), {})); + auto publisher = pubsub::Publisher(pubsub::MakePublisherConnection(topic())); for (auto const& test : cases) { SCOPED_TRACE("Testing for " + test.expected); diff --git a/examples/site/testing_pubsub/pubsub_unit_test.cc b/examples/site/testing_pubsub/pubsub_unit_test.cc index 140d83b0..b9f3495f 100644 --- a/examples/site/testing_pubsub/pubsub_unit_test.cc +++ b/examples/site/testing_pubsub/pubsub_unit_test.cc @@ -47,10 +47,10 @@ TEST(PubsubUnitTest, Basic) { return be; }(); - struct TestCases { + struct { std::string data; std::string expected; - } cases[]{ + } const cases[]{ // The magic string was obtained using: // /bin/echo -n 'C++' | openssl base64 -e {R"js({"message": {"data": "Qysr"}})js", "Hello C++"}, diff --git a/examples/site/testing_storage/README.md b/examples/site/testing_storage/README.md index a0aff3a5..2a4a8ec8 100644 --- a/examples/site/testing_storage/README.md +++ b/examples/site/testing_storage/README.md @@ -73,12 +73,17 @@ pack build \ "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-storage" ``` +Set the active project: + +```sh +gcloud config set project ${GOOGLE_CLOUD_PROJECT} +``` + Then deploy this function to Cloud Run: ```shell docker push "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-storage" gcloud run deploy gcf-hello-world-storage \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --image="gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-hello-world-storage:latest" \ --region="us-central1" \ --platform="managed" \ @@ -105,7 +110,6 @@ topic: ```shell gcloud beta eventarc triggers create gcf-hello-world-storage-trigger \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --location="us-central1" \ --destination-run-service="gcf-hello-world-storage" \ --destination-run-region="us-central1" \ @@ -129,7 +133,6 @@ Remember to remove your deployment and the image once you have finished: ```sh gcloud run services delete gcf-cpp-hello-world-storage \ - --project="${GOOGLE_CLOUD_PROJECT}" \ --region="us-central1" \ --platform="managed" gcloud container images delete \ diff --git a/examples/site/testing_storage/storage_integration_test.cc b/examples/site/testing_storage/storage_integration_test.cc index d43bbf1f..e7252cb6 100644 --- a/examples/site/testing_storage/storage_integration_test.cc +++ b/examples/site/testing_storage/storage_integration_test.cc @@ -99,10 +99,10 @@ TEST_F(StorageIntegrationTest, Basic) { } })js"); - struct TestCases { + struct { std::string name; std::string expected; - } cases[]{ + } const cases[]{ {"object1.txt", "Object: object1.txt"}, {"object/with/longer/name.txt", "Object: object/with/longer/name.txt"}, }; diff --git a/examples/site/testing_storage/storage_unit_test.cc b/examples/site/testing_storage/storage_unit_test.cc index 77781680..2538a8f0 100644 --- a/examples/site/testing_storage/storage_unit_test.cc +++ b/examples/site/testing_storage/storage_unit_test.cc @@ -47,10 +47,10 @@ TEST(StorageUnitTest, Basic) { return be; }(); - struct TestCases { + struct { std::string name; std::string expected; - } cases[]{ + } const cases[]{ {"object1.txt", "Object: object1.txt"}, {"object/with/longer/name.txt", "Object: object/with/longer/name.txt"}, }; diff --git a/examples/site/tips_gcp_apis/tips_gcp_apis.cc b/examples/site/tips_gcp_apis/tips_gcp_apis.cc index 5ce1843c..da8616b4 100644 --- a/examples/site/tips_gcp_apis/tips_gcp_apis.cc +++ b/examples/site/tips_gcp_apis/tips_gcp_apis.cc @@ -15,7 +15,7 @@ // [START functions_pubsub_publish] // [START functions_tips_gcp_apis] #include -#include +#include #include #include #include @@ -26,20 +26,13 @@ namespace gcf = ::google::cloud::functions; namespace pubsub = ::google::cloud::pubsub; namespace { -pubsub::Publisher GetPublisher(pubsub::Topic topic) { - using Map = std::unordered_map>; - +pubsub::BlockingPublisher GetPublisher() { static std::mutex mu; - static Map connections; + static std::shared_ptr connection; - std::lock_guard lk(mu); - auto [pos, inserted] = connections.emplace( - topic.FullName(), std::shared_ptr()); - if (inserted) { - pos->second = pubsub::MakePublisherConnection(std::move(topic), {}); - } - return pubsub::Publisher(pos->second); + std::lock_guard const lk(mu); + if (!connection) connection = pubsub::MakeBlockingPublisherConnection(); + return pubsub::BlockingPublisher(connection); } } // namespace @@ -51,18 +44,18 @@ gcf::HttpResponse tips_gcp_apis_impl(gcf::HttpRequest const& request) { auto const topic_id = body.value("topic", ""); if (topic_id.empty()) throw std::runtime_error("Missing topic in request"); - auto publisher = GetPublisher(pubsub::Topic(project, topic_id)); + auto publisher = GetPublisher(); auto id = publisher.Publish( + pubsub::Topic(project, topic_id), pubsub::MessageBuilder().SetData("Test message").Build()); - gcf::HttpResponse response; - if (!id.get()) { - response.set_result(gcf::HttpResponse::kInternalServerError); - } else { - response.set_payload("1 message published"); - response.set_header("content-type", "text/plain"); + if (!id) { + return gcf::HttpResponse{}.set_result( + gcf::HttpResponse::kInternalServerError); } - return response; + return gcf::HttpResponse{} + .set_payload("1 message published") + .set_header("content-type", "text/plain"); } gcf::Function tips_gcp_apis() { return gcf::MakeFunction(tips_gcp_apis_impl); } diff --git a/examples/site/tutorial_cloud_bigtable/tutorial_cloud_bigtable.cc b/examples/site/tutorial_cloud_bigtable/tutorial_cloud_bigtable.cc index 2db99308..4ffb0aef 100644 --- a/examples/site/tutorial_cloud_bigtable/tutorial_cloud_bigtable.cc +++ b/examples/site/tutorial_cloud_bigtable/tutorial_cloud_bigtable.cc @@ -29,18 +29,13 @@ namespace { cbt::Table get_table_client(std::string project_id, std::string instance_id, std::string const& table_id) { static std::mutex mu; - static std::unique_ptr table; - std::lock_guard lk(mu); - if (table == nullptr || table->table_id() != table_id || - table->instance_id() != instance_id || - table->project_id() != project_id) { - table = std::make_unique( - cbt::CreateDefaultDataClient(std::move(project_id), - std::move(instance_id), - cbt::ClientOptions{}), - table_id); - } - return *table; + static std::shared_ptr connection; + std::lock_guard const lk(mu); + if (!connection) connection = cbt::MakeDataConnection(); + + return cbt::Table(connection, + cbt::TableResource(std::move(project_id), + std::move(instance_id), table_id)); } gcf::HttpResponse handle_request(gcf::HttpRequest const& request) { diff --git a/examples/site_test.cc b/examples/site_test.cc index 1d91e000..13d9970e 100644 --- a/examples/site_test.cc +++ b/examples/site_test.cc @@ -327,7 +327,7 @@ TEST(ExamplesSiteTest, HelloWorldPubSub) { } })js"; - struct TestCase { + struct { std::string name; std::string body; } const cases[] = { @@ -399,7 +399,7 @@ TEST(ExamplesSiteTest, HelloWorldStorage) { "datacontenttype": "application/json" })js"; - struct TestCase { + struct { std::string name; std::string body; std::string content_type; diff --git a/google/cloud/functions/CMakeLists.txt b/google/cloud/functions/CMakeLists.txt index 2b9506b4..ef70c03b 100644 --- a/google/cloud/functions/CMakeLists.txt +++ b/google/cloud/functions/CMakeLists.txt @@ -23,6 +23,7 @@ configure_file(internal/version_info.h.in find_package(absl REQUIRED) find_package(Boost REQUIRED COMPONENTS program_options) find_package(Threads REQUIRED) +find_package(nlohmann_json REQUIRED) add_library( functions_framework_cpp # cmake-format: sort @@ -79,10 +80,14 @@ target_include_directories(functions_framework_cpp target_include_directories(functions_framework_cpp SYSTEM PUBLIC $) target_link_libraries( - functions_framework_cpp PUBLIC absl::time Boost::headers - Boost::program_options Threads::Threads) -target_compile_definitions(functions_framework_cpp - PUBLIC BOOST_BEAST_USE_STD_STRING_VIEW) + functions_framework_cpp + PUBLIC absl::time Boost::headers Boost::program_options Threads::Threads + PRIVATE nlohmann_json::nlohmann_json) + +if ("${Boost_VERSION_STRING}" VERSION_LESS "1.81") + target_compile_definitions(functions_framework_cpp + PUBLIC BOOST_BEAST_USE_STD_STRING_VIEW) +endif () set_target_properties( functions_framework_cpp PROPERTIES EXPORT_NAME functions-framework-cpp::framework @@ -121,6 +126,18 @@ if (BUILD_TESTING) functions_framework_cpp_add_common_options(${target}) add_test(NAME ${target} COMMAND ${target}) endforeach () + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # GCC turns on -Wmaybe-unitialized with -Wall. This results in false + # positives in this test, but the warning was useful in other tests. + # + # https://godbolt.org/z/xhj57Y6qG shows an example of these false + # positives. + # + # It seems the GTEST_*() macros trigger a new version of: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635 + target_compile_options(cloud_event_test + PRIVATE "-Wno-maybe-uninitialized") + endif () add_subdirectory(integration_tests) endif () diff --git a/google/cloud/functions/cloud_event_test.cc b/google/cloud/functions/cloud_event_test.cc index 4ce258b9..1b98ac02 100644 --- a/google/cloud/functions/cloud_event_test.cc +++ b/google/cloud/functions/cloud_event_test.cc @@ -43,8 +43,7 @@ TEST(CloudEventTest, WithVersion) { TEST(CloudEventTest, DataContentType) { auto actual = CloudEvent("test-id", "test-source", "test-type"); actual.set_data_content_type("test-value"); - ASSERT_TRUE(actual.data_content_type().has_value()); - EXPECT_EQ(*actual.data_content_type(), "test-value"); + EXPECT_EQ(actual.data_content_type().value_or(""), "test-value"); actual.reset_data_content_type(); EXPECT_FALSE(actual.data_content_type().has_value()); } @@ -52,8 +51,7 @@ TEST(CloudEventTest, DataContentType) { TEST(CloudEventTest, DataSchema) { auto actual = CloudEvent("test-id", "test-source", "test-type"); actual.set_data_schema("test-value"); - ASSERT_TRUE(actual.data_schema().has_value()); - EXPECT_EQ(*actual.data_schema(), "test-value"); + EXPECT_EQ(actual.data_schema().value_or(""), "test-value"); actual.reset_data_schema(); EXPECT_FALSE(actual.data_schema().has_value()); } @@ -61,8 +59,7 @@ TEST(CloudEventTest, DataSchema) { TEST(CloudEventTest, Subject) { auto actual = CloudEvent("test-id", "test-source", "test-type"); actual.set_subject("test-value"); - ASSERT_TRUE(actual.subject().has_value()); - EXPECT_EQ(*actual.subject(), "test-value"); + EXPECT_EQ(actual.subject().value_or(""), "test-value"); actual.reset_subject(); EXPECT_FALSE(actual.subject().has_value()); } @@ -71,17 +68,16 @@ TEST(CloudEventTest, Time) { auto actual = CloudEvent("test-id", "test-source", "test-type"); auto const tp = CloudEvent::ClockType::now(); actual.set_time(tp); - ASSERT_TRUE(actual.time().has_value()); - EXPECT_EQ(*actual.time(), tp); + EXPECT_EQ(actual.time().value_or(tp + std::chrono::seconds(5)), tp); actual.reset_time(); EXPECT_FALSE(actual.time().has_value()); } TEST(CloudEventTest, TimeString) { auto actual = CloudEvent("test-id", "test-source", "test-type"); - std::string valid[] = {"2020-11-30T12:34:45Z", "2020-11-30T12:34:45.678Z", - "2020-11-30T12:34:45.678-05:00", - "2020-11-30T12:34:45.678+05:00"}; + std::string const valid[] = { + "2020-11-30T12:34:45Z", "2020-11-30T12:34:45.678Z", + "2020-11-30T12:34:45.678-05:00", "2020-11-30T12:34:45.678+05:00"}; auto to_system_clock_tp = [](std::string const& s) { std::string err; absl::Time t; @@ -101,8 +97,7 @@ TEST(CloudEventTest, TimeString) { TEST(CloudEventTest, Data) { auto actual = CloudEvent("test-id", "test-source", "test-type"); actual.set_data("test-value"); - ASSERT_TRUE(actual.data().has_value()); - EXPECT_EQ(*actual.data(), "test-value"); + EXPECT_EQ(actual.data().value_or(""), "test-value"); actual.reset_data(); EXPECT_FALSE(actual.data().has_value()); } @@ -111,8 +106,7 @@ TEST(CloudEventTest, DataMove) { auto actual = CloudEvent("test-id", "test-source", "test-type"); actual.set_data("test-value"); auto d = std::move(actual).data(); - ASSERT_TRUE(d.has_value()); - EXPECT_EQ(*d, "test-value"); + EXPECT_EQ(d.value_or(""), "test-value"); } } // namespace diff --git a/google/cloud/functions/config.cmake.in b/google/cloud/functions/config.cmake.in index 6c8c3e34..aebc8d38 100644 --- a/google/cloud/functions/config.cmake.in +++ b/google/cloud/functions/config.cmake.in @@ -16,6 +16,7 @@ include(CMakeFindDependencyMacro) find_dependency(absl) find_dependency(Boost COMPONENTS program_options) find_dependency(Threads) +find_dependency(nlohmann_json) set(FUNCTIONS_FRAMEWORK_CPP_VERSION @PROJECT_VERSION@) diff --git a/google/cloud/functions/integration_tests/cloud_event_conformance.cc b/google/cloud/functions/integration_tests/cloud_event_conformance.cc index 66d04510..88b947c5 100644 --- a/google/cloud/functions/integration_tests/cloud_event_conformance.cc +++ b/google/cloud/functions/integration_tests/cloud_event_conformance.cc @@ -35,7 +35,7 @@ void CloudEventConformance(functions::CloudEvent const& ev) { struct { std::string name; std::optional value; - } optional_fields[]{ + } const optional_fields[]{ {"datacontenttype", ev.data_content_type()}, {"dataschema", ev.data_schema()}, {"subject", ev.subject()}, diff --git a/google/cloud/functions/internal/parse_cloud_event_legacy.cc b/google/cloud/functions/internal/parse_cloud_event_legacy.cc index 6ed0acba..4fbc515d 100644 --- a/google/cloud/functions/internal/parse_cloud_event_legacy.cc +++ b/google/cloud/functions/internal/parse_cloud_event_legacy.cc @@ -234,7 +234,7 @@ functions::CloudEvent ParseLegacyFirebaseAuth(nlohmann::json const& json, gcf.subject = "users/" + uid; auto modified = json["data"]; - std::pair renames[] = { + std::pair const renames[] = { {"createdAt", "createTime"}, {"lastSignedInAt", "lastSignInTime"}}; auto& metadata = modified["metadata"]; for (auto const& [old_name, new_name] : renames) { diff --git a/google/cloud/functions/internal/parse_cloud_event_legacy_test.cc b/google/cloud/functions/internal/parse_cloud_event_legacy_test.cc index 14e0ccc1..91927a00 100644 --- a/google/cloud/functions/internal/parse_cloud_event_legacy_test.cc +++ b/google/cloud/functions/internal/parse_cloud_event_legacy_test.cc @@ -162,7 +162,7 @@ TEST(ParseCloudEventLegacy, MapEventTypePrefixToEventType) { struct { std::string gcf_event_type; std::string expected_service; - } cases[] = { + } const cases[] = { {"providers/cloud.firestore/eventTypes/document.write", "firestore.googleapis.com"}, {"providers/google.firebase.analytics/eventTypes/event.log", @@ -208,7 +208,7 @@ TEST(ParseCloudEventLegacy, MapEventType) { struct { std::string gcf_event_type; std::string expected; - } cases[] = { + } const cases[] = { {"google.pubsub.topic.publish", "google.cloud.pubsub.topic.v1.messagePublished"}, {"providers/cloud.pubsub/eventTypes/topic.publish", diff --git a/google/cloud/functions/internal/parse_cloud_event_storage.cc b/google/cloud/functions/internal/parse_cloud_event_storage.cc index 2ad234be..27d87be3 100644 --- a/google/cloud/functions/internal/parse_cloud_event_storage.cc +++ b/google/cloud/functions/internal/parse_cloud_event_storage.cc @@ -58,7 +58,7 @@ functions::CloudEvent ParseCloudEventStorage(functions::CloudEvent e) { event.set_data_content_type("application/json"); event.set_data_schema("google.events.cloud.storage.v1.StorageObjectData"); event.set_subject("objects/" + attributes.value("objectId", "")); - if (e.time().has_value()) event.set_time(e.time().value()); + if (auto t = e.time(); t.has_value()) event.set_time(*t); event.set_data(Base64Decode(message.value("data", ""))); return event; diff --git a/google/cloud/functions/internal/parse_cloud_event_storage_test.cc b/google/cloud/functions/internal/parse_cloud_event_storage_test.cc index d2d67bfd..6865bc1c 100644 --- a/google/cloud/functions/internal/parse_cloud_event_storage_test.cc +++ b/google/cloud/functions/internal/parse_cloud_event_storage_test.cc @@ -24,10 +24,10 @@ FUNCTIONS_FRAMEWORK_CPP_INLINE_NAMESPACE_BEGIN namespace { TEST(ParseCloudEventJson, EmulateStorageBase) { - struct TestCase { + struct { std::string event_type; std::string expected_type; - } test_cases[] = { + } const test_cases[] = { {"OBJECT_FINALIZE", "google.cloud.storage.object.v1.finalized"}, {"OBJECT_METADATA_UPDATE", "google.cloud.storage.object.v1.metadataUpdated"}, @@ -210,9 +210,9 @@ TEST(ParseCloudEventJson, EmulateStorageMissingData) { } TEST(ParseCloudEventJson, EmulateStorageMissingAttributeField) { - struct TestCase { + struct { std::string field_name; - } test_cases[] = { + } const test_cases[] = { {"notificationConfig"}, {"eventType"}, {"payloadFormat"}, {"bucketId"}, {"objectId"}, {"objectGeneration"}, }; @@ -271,9 +271,9 @@ TEST(ParseCloudEventJson, EmulateStorageMissingAttributeField) { } TEST(ParseCloudEventJson, EmulateStorageMissingInvalidAttributeField) { - struct TestCase { + struct { std::string field_name; - } test_cases[] = { + } const test_cases[] = { {"eventType"}, {"payloadFormat"}, }; diff --git a/google/cloud/functions/internal/parse_options.cc b/google/cloud/functions/internal/parse_options.cc index ba3a2b5c..b466ffa2 100644 --- a/google/cloud/functions/internal/parse_options.cc +++ b/google/cloud/functions/internal/parse_options.cc @@ -14,6 +14,7 @@ #include "google/cloud/functions/internal/parse_options.h" #include +#include #include #include #include diff --git a/google/cloud/functions/internal/parse_options_test.cc b/google/cloud/functions/internal/parse_options_test.cc index 586b9469..75d7473c 100644 --- a/google/cloud/functions/internal/parse_options_test.cc +++ b/google/cloud/functions/internal/parse_options_test.cc @@ -43,7 +43,7 @@ TEST(WrapRequestTest, ExceptionOnUnknown) { "unused", "--invalid-option-never-named-an-option-this", }; - int argc = sizeof(argv) / sizeof(argv[0]); + int const argc = sizeof(argv) / sizeof(argv[0]); EXPECT_THROW(ParseOptions(argc, argv), std::exception); } @@ -78,21 +78,21 @@ TEST(WrapRequestTest, CommandLineOverridesEnv) { TEST(WrapRequestTest, PortEnvInvalid) { SetEnv("PORT", "not-a-number"); char const* argv[] = {"unused"}; - int argc = sizeof(argv) / sizeof(argv[0]); + int const argc = sizeof(argv) / sizeof(argv[0]); EXPECT_THROW(ParseOptions(argc, argv), std::exception); } TEST(WrapRequestTest, PortEnvTooLow) { SetEnv("PORT", "-1"); char const* argv[] = {"unused"}; - int argc = sizeof(argv) / sizeof(argv[0]); + int const argc = sizeof(argv) / sizeof(argv[0]); EXPECT_THROW(ParseOptions(argc, argv), std::exception); } TEST(WrapRequestTest, PortEnvTooHigh) { SetEnv("PORT", "65536"); char const* argv[] = {"unused"}; - int argc = sizeof(argv) / sizeof(argv[0]); + int const argc = sizeof(argv) / sizeof(argv[0]); EXPECT_THROW(ParseOptions(argc, argv), std::exception); } diff --git a/google/cloud/functions/internal/version_info.h b/google/cloud/functions/internal/version_info.h index 2dca1acd..70c969b7 100644 --- a/google/cloud/functions/internal/version_info.h +++ b/google/cloud/functions/internal/version_info.h @@ -15,8 +15,10 @@ #ifndef FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_INTERNAL_VERSION_INFO_H #define FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_INTERNAL_VERSION_INFO_H -#define FUNCTIONS_FRAMEWORK_CPP_VERSION_MAJOR 1 -#define FUNCTIONS_FRAMEWORK_CPP_VERSION_MINOR 2 -#define FUNCTIONS_FRAMEWORK_CPP_VERSION_PATCH 0 +// clang-format off +#define FUNCTIONS_FRAMEWORK_CPP_VERSION_MAJOR 1 // NOLINT(modernize-macro-to-enum) +#define FUNCTIONS_FRAMEWORK_CPP_VERSION_MINOR 3 // NOLINT(modernize-macro-to-enum) +#define FUNCTIONS_FRAMEWORK_CPP_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum) +// clang-format on #endif // FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_INTERNAL_VERSION_INFO_H diff --git a/google/cloud/functions/internal/version_info.h.in b/google/cloud/functions/internal/version_info.h.in index 0543aff6..0224465b 100644 --- a/google/cloud/functions/internal/version_info.h.in +++ b/google/cloud/functions/internal/version_info.h.in @@ -15,8 +15,10 @@ #ifndef FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_INTERNAL_VERSION_INFO_H #define FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_INTERNAL_VERSION_INFO_H -#define FUNCTIONS_FRAMEWORK_CPP_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ -#define FUNCTIONS_FRAMEWORK_CPP_VERSION_MINOR @PROJECT_VERSION_MINOR@ -#define FUNCTIONS_FRAMEWORK_CPP_VERSION_PATCH @PROJECT_VERSION_PATCH@ +// clang-format off +#define FUNCTIONS_FRAMEWORK_CPP_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ // NOLINT(modernize-macro-to-enum) +#define FUNCTIONS_FRAMEWORK_CPP_VERSION_MINOR @PROJECT_VERSION_MINOR@ // NOLINT(modernize-macro-to-enum) +#define FUNCTIONS_FRAMEWORK_CPP_VERSION_PATCH @PROJECT_VERSION_PATCH@ // NOLINT(modernize-macro-to-enum) +// clang-format on #endif // FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_INTERNAL_VERSION_INFO_H diff --git a/vcpkg.json b/vcpkg.json index e43d0c8f..453e222a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "functions-framework-cpp-dev", - "version-string": "0.6.0", + "version-string": "1.2.0", "homepage": "https://github.com/GoogleCloudPlatform/functions-framework-cpp/", "description": [ "A functions as a service (FaaS) framework for writing portable C++ functions.",