Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ci/Jenkinsfile.combined
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env groovy

library 'status-jenkins-lib@v1.9.27'
library 'status-jenkins-lib@refactor-common-secrets'

/* Object to store public URLs for description. */
urls = [:]
Expand Down
30 changes: 25 additions & 5 deletions ci/Jenkinsfile.linux
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.27'
library 'status-jenkins-lib@refactor-common-secrets'

/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
Expand Down Expand Up @@ -94,12 +94,12 @@ pipeline {
}

stages {
stage('Cleanup Workspace') {
stage('Clean') {
steps {
sh './scripts/clean-git.sh'
}
}
stage('Fetch submodules') {
stage('Submodules') {
steps {
sh 'git submodule update --init --recursive'
}
Expand All @@ -111,7 +111,7 @@ pipeline {
}
}

stage('status-go') {
stage('Status-go') {
steps {
sh "echo USE_NWAKU is ${USE_NWAKU}"
sh 'make status-go'
Expand All @@ -125,7 +125,27 @@ pipeline {
} }
}

stage('Parallel Upload') {
stage('Audit') {
steps { script {
sh "tar -xzf ${env.STATUS_CLIENT_TARBALL} -C ${env.WORKSPACE_TMP}"

def appImagePath = sh(
script: "basename ${env.STATUS_CLIENT_APPIMAGE}",
returnStdout: true
).trim()

sh "chmod +x ${env.WORKSPACE_TMP}/${appImagePath}"

desktop.withCommonCredentials([]) {
sh(
script: "${env.WORKSPACE_TMP}/${appImagePath} --verify-credentials"
)
}

} }
}

stage('Publish') {
parallel {
stage('Upload') {
steps { script {
Expand Down
2 changes: 1 addition & 1 deletion ci/Jenkinsfile.linux-nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env groovy

library 'status-jenkins-lib@v1.9.27'
library 'status-jenkins-lib@refactor-common-secrets'

/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
Expand Down
25 changes: 20 additions & 5 deletions ci/Jenkinsfile.macos
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.27'
library 'status-jenkins-lib@refactor-common-secrets'

/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
Expand Down Expand Up @@ -101,12 +101,12 @@ pipeline {
}

stages {
stage('Cleanup Workspace') {
stage('Clean') {
steps {
sh './scripts/clean-git.sh'
}
}
stage('Fetch submodules') {
stage('Submodules') {
steps {
sh 'git submodule update --init --recursive'
}
Expand All @@ -126,7 +126,7 @@ pipeline {
}
}

stage('status-go') {
stage('Status-go') {
steps {
sh "echo USE_NWAKU is ${USE_NWAKU}"
sh 'make status-go'
Expand All @@ -140,14 +140,29 @@ pipeline {
} }
}

stage('Audit') {
steps { script {
sh "hdiutil attach ${env.STATUS_CLIENT_DMG} -mountpoint /tmp/status-mount"

desktop.withCommonCredentials([]) {
sh(
script: "/tmp/status-mount/Status.app/Contents/MacOS/nim_status_client --verify-credentials"
)
}

sh "hdiutil detach /tmp/status-mount"

} }
}

stage('Notarize') {
when { expression { utils.isReleaseBuild() } }
steps { script {
macos.notarize()
} }
}

stage('Parallel Upload') {
stage('Publish') {
parallel {
stage('Upload') {
steps { script {
Expand Down
2 changes: 1 addition & 1 deletion ci/Jenkinsfile.tests-e2e
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.16'
library 'status-jenkins-lib@refactor-common-secrets'

pipeline {

Expand Down
2 changes: 1 addition & 1 deletion ci/Jenkinsfile.tests-nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.16'
library 'status-jenkins-lib@refactor-common-secrets'

/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
Expand Down
2 changes: 1 addition & 1 deletion ci/Jenkinsfile.tests-ui
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.16'
library 'status-jenkins-lib@refactor-common-secrets'

/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
Expand Down
28 changes: 23 additions & 5 deletions ci/Jenkinsfile.windows
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.27'
library 'status-jenkins-lib@refactor-common-secrets'

/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
Expand Down Expand Up @@ -96,12 +96,12 @@ pipeline {
}

stages {
stage('Cleanup Workspace') {
stage('Clean') {
steps {
sh './scripts/clean-git.sh'
}
}
stage('Fetch submodules') {
stage('Submodules') {
steps {
sh 'git submodule update --init --recursive'
}
Expand All @@ -113,7 +113,7 @@ pipeline {
}
}

stage('status-go') {
stage('Status-go') {
steps {
sh 'make status-go'
}
Expand All @@ -125,7 +125,25 @@ pipeline {
} }
}

stage('Parallel Upload') {
stage('Audit') {
steps { script {
sh "7z x ${env.STATUS_CLIENT_7Z} -o${env.WORKSPACE_TMP}/extracted"

def exeName = sh(
script: "basename ${env.STATUS_CLIENT_EXE}",
returnStdout: true
).trim()

desktop.withCommonCredentials([]) {
sh(
script: "${env.WORKSPACE_TMP}/extracted/${exeName} --verify-credentials"
)
}

} }
}

stage('Publish') {
/* Uploads on Windows are slow. */
parallel {
stage('Upload 7Z') {
Expand Down
28 changes: 28 additions & 0 deletions src/app/core/credential_verifier.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os, strutils, sequtils

proc runCredentialVerification*(): int =
echo "Starting credential verification"

let thingsToCheck = getEnv("THINGS_TO_CHECK")
if thingsToCheck.len == 0:
echo "ERROR: THINGS_TO_CHECK environment variable not set"
return 1
Comment on lines +6 to +9
Copy link
Member

@jakubgs jakubgs Sep 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seem way to complicated to me. Why can't we write a wrapper around getEnv() in src/env_cli_vars.nim:

const
DEFAULT_INFURA_TOKEN = "220a1abb4b6943a093c35d0ce4fb0732"
BUILD_INFURA_TOKEN = getEnv(BUILD_TIME_PREFIX & BASE_NAME_INFURA_TOKEN, DEFAULT_INFURA_TOKEN)

And just check if it's an empty string and fail on that with an assert or something.

I thought we could use existsEnv() but empty string is an invalid value so just checking that is better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to docs static blocks are executed at built time:
https://nim-lang.org/docs/manual.html#statements-and-expressions-static-statementslashexpression

But I don't see any usage of static in src/env_cli_vars.nim or src/constants.nim.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key point is that we want a way that live closest to where the vars are sourced, that way we have a better chance of developers also maintaining that. We could define a mustGetEnv() that is used only for secrets, or even more explicit ciMustGetEnv() that only fails on missing value when CI=true.


let credNames = thingsToCheck.splitLines().mapIt(it.strip()).filterIt(it.len > 0)
if credNames.len == 0:
echo "ERROR: No credentials to check"
return 1

var missingCreds: seq[string] = @[]

for credName in credNames:
if not existsEnv(credName):
missingCreds.add(credName)
echo "ERROR: Missing environment variable: ", credName

if missingCreds.len > 0:
echo "ERROR: Credential verification failed. Missing ", missingCreds.len, " out of ", credNames.len, " credentials"
return 1
else:
echo "SUCCESS: All ", credNames.len, " credentials verified successfully"
return 0
7 changes: 6 additions & 1 deletion src/env_cli_vars.nim
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@ type StatusDesktopConfig = object
desc: "Sets address for prometheus metrics"
name: "METRICS_ADDRESS"
abbr: "metrics-address" .}: string
verifyCredentials* {.
defaultValue: false
desc: "Verify that all required credentials are present and exit"
name: "VERIFY_CREDENTIALS"
abbr: "verify-credentials" .}: bool

# On macOS the first time when a user gets the "App downloaded from the
# internet" warning, and clicks the Open button, the OS passes a unique process
Expand All @@ -310,4 +315,4 @@ else:
if defined(macosx):
cliParams.keepIf(proc(p: string): bool = not p.startsWith("-psn_"))

let desktopConfig = StatusDesktopConfig.load(cmdLine = cliParams, envVarsPrefix = RUN_TIME_PREFIX)
let desktopConfig* = StatusDesktopConfig.load(cmdLine = cliParams, envVarsPrefix = RUN_TIME_PREFIX)
7 changes: 6 additions & 1 deletion src/nim_status_client.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import

import status_go
import app/core/main
import app/core/credential_verifier
import constants as main_constants
import statusq_bridge

import app/global/global_singleton
import app/global/local_app_settings
import app/boot/app_controller
import env_cli_vars

featureGuard KEYCARD_ENABLED:
import keycard_go
Expand Down Expand Up @@ -118,7 +120,7 @@ proc ensureDirectories*(dataDir, tmpDir, logDir: string) =
proc logHandlerCallback(messageType: cint, message: cstring, category: cstring, file: cstring, function: cstring, line: cint) {.cdecl, exportc.} =
# Initialize Nim GC stack bottom for foreign threads
# https://status-im.github.io/nim-style-guide/interop.html#calling-nim-code-from-other-languages
when declared(setupForeignThreadGc):
when declared(setupForeignThreadGc):
setupForeignThreadGc()
when declared(nimGC_setStackBottom):
var locals {.volatile, noinit.}: pointer
Expand Down Expand Up @@ -154,6 +156,9 @@ proc logHandlerCallback(messageType: cint, message: cstring, category: cstring,
warn "qt message of unknown type", messageType = int(messageType)

proc mainProc() =
# used in CI
if env_cli_vars.desktopConfig.verifyCredentials:
quit(runCredentialVerification())

when defined(macosx) and defined(arm64):
var signalStack: cstring = cast[cstring](allocShared(SIGSTKSZ))
Expand Down