diff --git a/.github/actions/install-boost/action.yml b/.github/actions/install-boost/action.yml index b7d05d852..b39568e48 100644 --- a/.github/actions/install-boost/action.yml +++ b/.github/actions/install-boost/action.yml @@ -40,7 +40,7 @@ runs: shell: bash run: | brew install boost - echo "BOOST_ROOT=$(boost --prefix boost@1.82)" >> $GITHUB_OUTPUT + echo "BOOST_ROOT=$(brew --prefix boost)" >> $GITHUB_OUTPUT - name: Determine root id: determine-root diff --git a/.github/actions/install-openssl/action.yml b/.github/actions/install-openssl/action.yml index a6db037f5..b2e4ff4b2 100644 --- a/.github/actions/install-openssl/action.yml +++ b/.github/actions/install-openssl/action.yml @@ -1,6 +1,10 @@ name: Install OpenSSL description: 'Install OpenSSL >= 3 if not already present.' +outputs: + OPENSSL_ROOT_DIR: + description: The location of the installed OpenSSL. + value: ${{ steps.determine-root.outputs.OPENSSL_ROOT_DIR }} runs: using: composite steps: @@ -13,20 +17,40 @@ runs: # The Mac runner already has OpenSSL > 3 via brew, but we need to expose its # install path to CMake. - name: Install for Mac + id: brew-action if: runner.os == 'macOS' shell: bash - run: echo "OPENSSL_ROOT_DIR=$(brew --prefix openssl@3)" >> "$GITHUB_ENV" + run: | + echo "OpenSSL Prefix: $(brew --prefix openssl@3)" + echo "OPENSSL_ROOT_DIR=$(brew --prefix openssl@3)" >> $GITHUB_OUTPUT # The Windows runner has an older version of OpenSSL and needs to be upgraded. - # Additionally it seems to randomly be installed in OpenSSL-Win64 or OpenSSL depending on + # Additionally, it seems to randomly be installed in OpenSSL-Win64 or OpenSSL depending on # the runner Github gives us. - name: Install for Windows + id: choco-action if: runner.os == 'Windows' shell: bash run: | choco upgrade openssl --no-progress if [ -d "C:\Program Files\OpenSSL-Win64" ]; then - echo "OPENSSL_ROOT_DIR=C:\Program Files\OpenSSL-Win64" >> "$GITHUB_ENV" + echo "OPENSSL_ROOT_DIR=C:\Program Files\OpenSSL-Win64" >> $GITHUB_OUTPUT else - echo "OPENSSL_ROOT_DIR=C:\Program Files\OpenSSL" >> "$GITHUB_ENV" + echo "OPENSSL_ROOT_DIR=C:\Program Files\OpenSSL" >> $GITHUB_OUTPUT + fi + + - name: Determine root + id: determine-root + shell: bash + run: | + if [ ! -z "$ROOT_CHOCO" ]; then + echo "OPENSSL_ROOT_DIR=$ROOT_CHOCO" >> $GITHUB_OUTPUT + echo Setting OPENSSL_ROOT_DIR to "$ROOT_CHOCO" + elif [ ! -z "$ROOT_BREW" ]; then + echo "OPENSSL_ROOT_DIR=$ROOT_BREW" >> $GITHUB_OUTPUT + echo Setting OPENSSL_ROOT_DIR to "$ROOT_BREW" fi + + env: + ROOT_CHOCO: ${{ steps.choco-action.outputs.OPENSSL_ROOT_DIR }} + ROOT_BREW: ${{ steps.brew-action.outputs.OPENSSL_ROOT_DIR }} diff --git a/.github/workflows/hello-apps.yml b/.github/workflows/hello-apps.yml new file mode 100644 index 000000000..07ed35b8c --- /dev/null +++ b/.github/workflows/hello-apps.yml @@ -0,0 +1,45 @@ +name: hello-apps + +on: + push: + branches: [ main ] + paths-ignore: + - '**.md' #Do not need to run CI for markdown changes. + pull_request: + branches: [ main, "feat/**" ] + paths-ignore: + - '**.md' + + +jobs: + smoketest: + strategy: + matrix: + os: [ "ubuntu-22.04", "macos-12", "windows-2022" ] + fail-fast: false + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - uses: ilammy/msvc-dev-cmd@v1 + - name: Install Ninja + uses: ./.github/actions/install-ninja + - name: Install boost + uses: ./.github/actions/install-boost + id: install-boost + - name: Install OpenSSL + uses: ./.github/actions/install-openssl + id: install-openssl + - name: Statically Linked Hello Apps + shell: bash + run: ./scripts/run-hello-apps.sh static hello-c-client hello-cpp-client hello-c-server hello-cpp-server + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + OPENSSL_ROOT_DIR: ${{ steps.install-openssl.outputs.OPENSSL_ROOT_DIR }} + - name: Dynamically Linked Hello Apps + shell: bash + continue-on-error: true # TODO(SC-223804) + # Only the C bindings work with dynamic linking because C++ symbols are hidden + run: ./scripts/run-hello-apps.sh dynamic hello-c-client hello-c-server + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + OPENSSL_ROOT_DIR: ${{ steps.install-openssl.outputs.OPENSSL_ROOT_DIR }} diff --git a/examples/hello-c-client/main.c b/examples/hello-c-client/main.c index 4915ff191..fd8e48f63 100644 --- a/examples/hello-c-client/main.c +++ b/examples/hello-c-client/main.c @@ -18,16 +18,20 @@ // the client to become initialized. #define INIT_TIMEOUT_MILLISECONDS 3000 +char const* get_with_env_fallback(char const* source_val, + char const* env_variable, + char const* error_msg); + int main() { - if (!strlen(MOBILE_KEY)) { - printf( - "*** Please edit main.c to set MOBILE_KEY to your LaunchDarkly " - "mobile key first\n\n"); - return 1; - } + char const* mobile_key = get_with_env_fallback( + MOBILE_KEY, "LD_MOBILE_KEY", + "Please edit main.c to set MOBILE_KEY to your LaunchDarkly mobile key " + "first.\n\nAlternatively, set the LD_MOBILE_KEY environment " + "variable.\n" + "The value of MOBILE_KEY in main.c takes priority over LD_MOBILE_KEY."); LDClientConfigBuilder config_builder = - LDClientConfigBuilder_New(MOBILE_KEY); + LDClientConfigBuilder_New(mobile_key); LDClientConfig config = NULL; LDStatus config_status = @@ -76,3 +80,19 @@ int main() { return 0; } + +char const* get_with_env_fallback(char const* source_val, + char const* env_variable, + char const* error_msg) { + if (strlen(source_val)) { + return source_val; + } + + char const* from_env = getenv(env_variable); + if (from_env && strlen(from_env)) { + return from_env; + } + + printf("*** %s\n\n", error_msg); + exit(1); +} diff --git a/examples/hello-c-server/main.c b/examples/hello-c-server/main.c index 4b3f68fcd..5c1acc69a 100644 --- a/examples/hello-c-server/main.c +++ b/examples/hello-c-server/main.c @@ -18,15 +18,20 @@ // the client to become initialized. #define INIT_TIMEOUT_MILLISECONDS 3000 +char const* get_with_env_fallback(char const* source_val, + char const* env_variable, + char const* error_msg); + int main() { - if (!strlen(SDK_KEY)) { - printf( - "*** Please edit main.c to set SDK_KEY to your LaunchDarkly " - "SDK key first\n\n"); - return 1; - } + char const* sdk_key = get_with_env_fallback( + SDK_KEY, "LD_SDK_KEY", + "Please edit main.c to set SDK_KEY to your LaunchDarkly server-side " + "SDK key " + "first.\n\nAlternatively, set the LD_SDK_KEY environment " + "variable.\n" + "The value of SDK_KEY in main.c takes priority over LD_SDK_KEY."); - LDServerConfigBuilder config_builder = LDServerConfigBuilder_New(SDK_KEY); + LDServerConfigBuilder config_builder = LDServerConfigBuilder_New(sdk_key); LDServerConfig config = NULL; LDStatus config_status = @@ -76,3 +81,19 @@ int main() { return 0; } + +char const* get_with_env_fallback(char const* source_val, + char const* env_variable, + char const* error_msg) { + if (strlen(source_val)) { + return source_val; + } + + char const* from_env = getenv(env_variable); + if (from_env && strlen(from_env)) { + return from_env; + } + + printf("*** %s\n\n", error_msg); + exit(1); +} diff --git a/examples/hello-cpp-client/main.cpp b/examples/hello-cpp-client/main.cpp index 99ed3c849..ab7d3d232 100644 --- a/examples/hello-cpp-client/main.cpp +++ b/examples/hello-cpp-client/main.cpp @@ -14,16 +14,20 @@ // the client to become initialized. #define INIT_TIMEOUT_MILLISECONDS 3000 +char const* get_with_env_fallback(char const* source_val, + char const* env_variable, + char const* error_msg); + using namespace launchdarkly; int main() { - if (!strlen(MOBILE_KEY)) { - printf( - "*** Please edit main.cpp to set MOBILE_KEY to your LaunchDarkly " - "mobile key first\n\n"); - return 1; - } + char const* mobile_key = get_with_env_fallback( + MOBILE_KEY, "LD_MOBILE_KEY", + "Please edit main.c to set MOBILE_KEY to your LaunchDarkly mobile key " + "first.\n\nAlternatively, set the LD_MOBILE_KEY environment " + "variable.\n" + "The value of MOBILE_KEY in main.c takes priority over LD_MOBILE_KEY."); - auto config = client_side::ConfigBuilder(MOBILE_KEY).Build(); + auto config = client_side::ConfigBuilder(mobile_key).Build(); if (!config) { std::cout << "error: config is invalid: " << config.error() << '\n'; return 1; @@ -57,3 +61,19 @@ int main() { return 0; } + +char const* get_with_env_fallback(char const* source_val, + char const* env_variable, + char const* error_msg) { + if (strlen(source_val)) { + return source_val; + } + + char const* from_env = std::getenv(env_variable); + if (from_env && strlen(from_env)) { + return from_env; + } + + std::cout << "*** " << error_msg << std::endl; + std::exit(1); +} diff --git a/examples/hello-cpp-server/main.cpp b/examples/hello-cpp-server/main.cpp index 64be85022..8cac4908d 100644 --- a/examples/hello-cpp-server/main.cpp +++ b/examples/hello-cpp-server/main.cpp @@ -6,7 +6,7 @@ #include // Set SDK_KEY to your LaunchDarkly SDK key. -#define SDK_KEY "foo" +#define SDK_KEY "" // Set FEATURE_FLAG_KEY to the feature flag key you want to evaluate. #define FEATURE_FLAG_KEY "my-boolean-flag" @@ -15,28 +15,22 @@ // the client to become initialized. #define INIT_TIMEOUT_MILLISECONDS 3000 +char const* get_with_env_fallback(char const* source_val, + char const* env_variable, + char const* error_msg); using namespace launchdarkly; using namespace launchdarkly::server_side; int main() { - if (!strlen(SDK_KEY)) { - printf( - "*** Please edit main.cpp to set SDK_KEY to your LaunchDarkly " - "SDK key first\n\n"); - return 1; - } - - auto cfg_builder = ConfigBuilder(SDK_KEY); - - using BackgroundSync = DataSystemBuilder::BackgroundSync; - - auto data_system = BackgroundSync().Synchronizer( - BackgroundSync::Streaming().InitialReconnectDelay( - std::chrono::seconds(1))); - - cfg_builder.DataSystem().Method(data_system); - - auto config = cfg_builder.Build(); + char const* sdk_key = get_with_env_fallback( + SDK_KEY, "LD_SDK_KEY", + "Please edit main.c to set SDK_KEY to your LaunchDarkly server-side " + "SDK key " + "first.\n\nAlternatively, set the LD_SDK_KEY environment " + "variable.\n" + "The value of SDK_KEY in main.c takes priority over LD_SDK_KEY."); + + auto config = ConfigBuilder(sdk_key).Build(); if (!config) { std::cout << "error: config is invalid: " << config.error() << '\n'; return 1; @@ -70,3 +64,19 @@ int main() { return 0; } + +char const* get_with_env_fallback(char const* source_val, + char const* env_variable, + char const* error_msg) { + if (strlen(source_val)) { + return source_val; + } + + char const* from_env = std::getenv(env_variable); + if (from_env && strlen(from_env)) { + return from_env; + } + + std::cout << "*** " << error_msg << std::endl; + std::exit(1); +} diff --git a/release-please-config.json b/release-please-config.json index 1a5d6687b..b9b9fd9b5 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -19,8 +19,7 @@ "CMakeLists.txt" ], "prerelease": true, - "bump-minor-pre-major": true, - "release-as": "0.1.0" + "bump-minor-pre-major": true }, "libs/server-sent-events": { "initial-version": "0.1.0" diff --git a/scripts/run-hello-apps.sh b/scripts/run-hello-apps.sh new file mode 100755 index 000000000..9b87fed5d --- /dev/null +++ b/scripts/run-hello-apps.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# This script builds a set of hello-app cmake targets +# using static or dynamic linkage. +# This script should be ran from the root directory of the project. +# Example: +# ./scripts/run-hello-apps.sh dynamic hello-cpp-client hello-c-client +# +# $1 is the linkage, either 'static' or 'dynamic'. +# Subsequent arguments are cmake target names. + +if [ "$1" != "static" ] && [ "$1" != "dynamic" ] +then + echo "Linkage must be specified ('static' or 'dynamic')" + exit 1 +fi + +dynamic_linkage="Off" +if [ "$1" == "dynamic" ]; then + dynamic_linkage="On" +fi + +shift + +function cleanup { + cd .. +} + +mkdir -p build-"$1" +cd build-"$1" || exit + +# After we enter the directory we want to make sure we always exit it when the +# script ends. +trap cleanup EXIT + +cmake -G Ninja -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTING=OFF -D LD_BUILD_SHARED_LIBS=$dynamic_linkage .. + +export LD_MOBILE_KEY="bogus" +export LD_SDK_KEY="bogus" + +for target in "$@" +do + cmake --build . --target "$target" + ./examples/"$target"/"$target" | tee "$target"_output.txt + grep "failed to initialize" "$target"_output.txt || (echo "$target: expected connection to LD to fail" && exit 1) +done