@@ -75,70 +75,81 @@ jobs:
7575 BUILD_TOKEN : ${{ secrets.BUILD_TOKEN }}
7676 run : |
7777 # Generate development_config.cpp with real credentials from secrets
78- cat > src/infrastructure/network/development_config.cpp << 'DEVCONFIG_EOF'
79- /**
80- * @file development_config.cpp
81- * @brief Development mode configuration with credentials from CI secrets
82- */
83-
84- #include <cstring>
85-
86- #include "rac/core/rac_logger.h"
87- #include "rac/infrastructure/network/rac_dev_config.h"
88-
89- namespace {
90-
91- DEVCONFIG_EOF
92-
93- # Inject secrets (avoiding heredoc variable expansion issues)
94- echo "constexpr const char* SUPABASE_URL = \"${SUPABASE_URL}\";" >> src/infrastructure/network/development_config.cpp
95- echo "constexpr const char* SUPABASE_ANON_KEY = \"${SUPABASE_ANON_KEY}\";" >> src/infrastructure/network/development_config.cpp
96- echo "constexpr const char* BUILD_TOKEN = \"${BUILD_TOKEN:-bt_release_build}\";" >> src/infrastructure/network/development_config.cpp
97- echo "constexpr const char* SENTRY_DSN = nullptr;" >> src/infrastructure/network/development_config.cpp
98-
99- cat >> src/infrastructure/network/development_config.cpp << 'DEVCONFIG_EOF'
100-
101- } // anonymous namespace
102-
103- extern "C" {
104-
105- bool rac_dev_config_is_available(void) {
106- if (SUPABASE_URL == nullptr || SUPABASE_ANON_KEY == nullptr) return false;
107- if (std::strlen(SUPABASE_URL) == 0 || std::strlen(SUPABASE_ANON_KEY) == 0) return false;
108- if (std::strstr(SUPABASE_URL, "YOUR_") != nullptr) return false;
109- if (std::strstr(SUPABASE_ANON_KEY, "YOUR_") != nullptr) return false;
110- return true;
111- }
112-
113- const char* rac_dev_config_get_supabase_url(void) {
114- return SUPABASE_URL;
115- }
116-
117- const char* rac_dev_config_get_supabase_key(void) {
118- return SUPABASE_ANON_KEY;
119- }
120-
121- const char* rac_dev_config_get_build_token(void) {
122- return BUILD_TOKEN;
123- }
124-
125- const char* rac_dev_config_get_sentry_dsn(void) {
126- return SENTRY_DSN;
127- }
128-
129- bool rac_dev_config_has_supabase(void) {
130- return rac_dev_config_is_available();
131- }
132-
133- bool rac_dev_config_has_build_token(void) {
134- return BUILD_TOKEN != nullptr && std::strlen(BUILD_TOKEN) > 0;
135- }
136-
137- } // extern "C"
138- DEVCONFIG_EOF
78+ # Use printf with %s to safely handle secret values (no newline interpretation)
79+
80+ CONFIG_FILE="src/infrastructure/network/development_config.cpp"
81+
82+ # Write the file header and includes
83+ cat > "$CONFIG_FILE" << 'EOF'
84+ /**
85+ * @file development_config.cpp
86+ * @brief Development mode configuration with credentials from CI secrets
87+ */
88+
89+ # include <cstring>
90+
91+ # include "rac/core/rac_logger.h"
92+ # include "rac/infrastructure/network/rac_dev_config.h"
93+
94+ namespace {
95+
96+ EOF
97+
98+ # Inject secrets using printf (safer than echo for special chars)
99+ # Remove any trailing newlines/whitespace from secrets
100+ CLEAN_URL=$(printf '%s' "$SUPABASE_URL" | tr -d '\n\r')
101+ CLEAN_KEY=$(printf '%s' "$SUPABASE_ANON_KEY" | tr -d '\n\r')
102+ CLEAN_TOKEN=$(printf '%s' "${BUILD_TOKEN:-bt_release_build}" | tr -d '\n\r')
103+
104+ printf 'constexpr const char* SUPABASE_URL = "%s";\n' "$CLEAN_URL" >> "$CONFIG_FILE"
105+ printf 'constexpr const char* SUPABASE_ANON_KEY = "%s";\n' "$CLEAN_KEY" >> "$CONFIG_FILE"
106+ printf 'constexpr const char* BUILD_TOKEN = "%s";\n' "$CLEAN_TOKEN" >> "$CONFIG_FILE"
107+ printf 'constexpr const char* SENTRY_DSN = nullptr;\n' >> "$CONFIG_FILE"
108+
109+ # Write the rest of the file
110+ cat >> "$CONFIG_FILE" << 'EOF'
111+
112+ } // anonymous namespace
113+
114+ extern "C" {
115+
116+ bool rac_dev_config_is_available(void) {
117+ if (SUPABASE_URL == nullptr || SUPABASE_ANON_KEY == nullptr) return false;
118+ if (std::strlen(SUPABASE_URL) == 0 || std::strlen(SUPABASE_ANON_KEY) == 0) return false;
119+ if (std::strstr(SUPABASE_URL, "YOUR_") != nullptr) return false;
120+ if (std::strstr(SUPABASE_ANON_KEY, "YOUR_") != nullptr) return false;
121+ return true;
122+ }
123+
124+ const char* rac_dev_config_get_supabase_url(void) {
125+ return SUPABASE_URL;
126+ }
127+
128+ const char* rac_dev_config_get_supabase_key(void) {
129+ return SUPABASE_ANON_KEY;
130+ }
131+
132+ const char* rac_dev_config_get_build_token(void) {
133+ return BUILD_TOKEN;
134+ }
135+
136+ const char* rac_dev_config_get_sentry_dsn(void) {
137+ return SENTRY_DSN;
138+ }
139+
140+ bool rac_dev_config_has_supabase(void) {
141+ return rac_dev_config_is_available();
142+ }
143+
144+ bool rac_dev_config_has_build_token(void) {
145+ return BUILD_TOKEN != nullptr && std::strlen(BUILD_TOKEN) > 0;
146+ }
147+
148+ } // extern "C"
149+ EOF
139150
140151 echo "=== Generated development_config.cpp ==="
141- head -30 src/infrastructure/network/development_config.cpp
152+ head -30 "$CONFIG_FILE"
142153 echo "..."
143154 echo "(credentials redacted)"
144155
@@ -219,67 +230,78 @@ jobs:
219230 BUILD_TOKEN : ${{ secrets.BUILD_TOKEN }}
220231 run : |
221232 # Generate development_config.cpp with real credentials from secrets
222- cat > src/infrastructure/network/development_config.cpp << 'DEVCONFIG_EOF'
223- /**
224- * @file development_config.cpp
225- * @brief Development mode configuration with credentials from CI secrets
226- */
227-
228- #include <cstring>
229-
230- #include "rac/core/rac_logger.h"
231- #include "rac/infrastructure/network/rac_dev_config.h"
232-
233- namespace {
234-
235- DEVCONFIG_EOF
236-
237- # Inject secrets
238- echo "constexpr const char* SUPABASE_URL = \"${SUPABASE_URL}\";" >> src/infrastructure/network/development_config.cpp
239- echo "constexpr const char* SUPABASE_ANON_KEY = \"${SUPABASE_ANON_KEY}\";" >> src/infrastructure/network/development_config.cpp
240- echo "constexpr const char* BUILD_TOKEN = \"${BUILD_TOKEN:-bt_release_build}\";" >> src/infrastructure/network/development_config.cpp
241- echo "constexpr const char* SENTRY_DSN = nullptr;" >> src/infrastructure/network/development_config.cpp
242-
243- cat >> src/infrastructure/network/development_config.cpp << 'DEVCONFIG_EOF'
244-
245- } // anonymous namespace
246-
247- extern "C" {
248-
249- bool rac_dev_config_is_available(void) {
250- if (SUPABASE_URL == nullptr || SUPABASE_ANON_KEY == nullptr) return false;
251- if (std::strlen(SUPABASE_URL) == 0 || std::strlen(SUPABASE_ANON_KEY) == 0) return false;
252- if (std::strstr(SUPABASE_URL, "YOUR_") != nullptr) return false;
253- if (std::strstr(SUPABASE_ANON_KEY, "YOUR_") != nullptr) return false;
254- return true;
255- }
256-
257- const char* rac_dev_config_get_supabase_url(void) {
258- return SUPABASE_URL;
259- }
260-
261- const char* rac_dev_config_get_supabase_key(void) {
262- return SUPABASE_ANON_KEY;
263- }
264-
265- const char* rac_dev_config_get_build_token(void) {
266- return BUILD_TOKEN;
267- }
268-
269- const char* rac_dev_config_get_sentry_dsn(void) {
270- return SENTRY_DSN;
271- }
272-
273- bool rac_dev_config_has_supabase(void) {
274- return rac_dev_config_is_available();
275- }
276-
277- bool rac_dev_config_has_build_token(void) {
278- return BUILD_TOKEN != nullptr && std::strlen(BUILD_TOKEN) > 0;
279- }
280-
281- } // extern "C"
282- DEVCONFIG_EOF
233+ # Use printf with %s to safely handle secret values (no newline interpretation)
234+
235+ CONFIG_FILE="src/infrastructure/network/development_config.cpp"
236+
237+ # Write the file header and includes
238+ cat > "$CONFIG_FILE" << 'EOF'
239+ /**
240+ * @file development_config.cpp
241+ * @brief Development mode configuration with credentials from CI secrets
242+ */
243+
244+ # include <cstring>
245+
246+ # include "rac/core/rac_logger.h"
247+ # include "rac/infrastructure/network/rac_dev_config.h"
248+
249+ namespace {
250+
251+ EOF
252+
253+ # Inject secrets using printf (safer than echo for special chars)
254+ # Remove any trailing newlines/whitespace from secrets
255+ CLEAN_URL=$(printf '%s' "$SUPABASE_URL" | tr -d '\n\r')
256+ CLEAN_KEY=$(printf '%s' "$SUPABASE_ANON_KEY" | tr -d '\n\r')
257+ CLEAN_TOKEN=$(printf '%s' "${BUILD_TOKEN:-bt_release_build}" | tr -d '\n\r')
258+
259+ printf 'constexpr const char* SUPABASE_URL = "%s";\n' "$CLEAN_URL" >> "$CONFIG_FILE"
260+ printf 'constexpr const char* SUPABASE_ANON_KEY = "%s";\n' "$CLEAN_KEY" >> "$CONFIG_FILE"
261+ printf 'constexpr const char* BUILD_TOKEN = "%s";\n' "$CLEAN_TOKEN" >> "$CONFIG_FILE"
262+ printf 'constexpr const char* SENTRY_DSN = nullptr;\n' >> "$CONFIG_FILE"
263+
264+ # Write the rest of the file
265+ cat >> "$CONFIG_FILE" << 'EOF'
266+
267+ } // anonymous namespace
268+
269+ extern "C" {
270+
271+ bool rac_dev_config_is_available(void) {
272+ if (SUPABASE_URL == nullptr || SUPABASE_ANON_KEY == nullptr) return false;
273+ if (std::strlen(SUPABASE_URL) == 0 || std::strlen(SUPABASE_ANON_KEY) == 0) return false;
274+ if (std::strstr(SUPABASE_URL, "YOUR_") != nullptr) return false;
275+ if (std::strstr(SUPABASE_ANON_KEY, "YOUR_") != nullptr) return false;
276+ return true;
277+ }
278+
279+ const char* rac_dev_config_get_supabase_url(void) {
280+ return SUPABASE_URL;
281+ }
282+
283+ const char* rac_dev_config_get_supabase_key(void) {
284+ return SUPABASE_ANON_KEY;
285+ }
286+
287+ const char* rac_dev_config_get_build_token(void) {
288+ return BUILD_TOKEN;
289+ }
290+
291+ const char* rac_dev_config_get_sentry_dsn(void) {
292+ return SENTRY_DSN;
293+ }
294+
295+ bool rac_dev_config_has_supabase(void) {
296+ return rac_dev_config_is_available();
297+ }
298+
299+ bool rac_dev_config_has_build_token(void) {
300+ return BUILD_TOKEN != nullptr && std::strlen(BUILD_TOKEN) > 0;
301+ }
302+
303+ } // extern "C"
304+ EOF
283305
284306 echo "=== Generated development_config.cpp for Android ==="
285307
0 commit comments