From 0b0d329b9b1e9a8320dc7f25a8badcf7ec656534 Mon Sep 17 00:00:00 2001 From: Stephan D Date: Sun, 23 Nov 2025 15:37:45 +0100 Subject: [PATCH] build script update --- .woodpecker/bump_version.yml | 10 +- api/chain/gateway/config.yml | 6 +- api/chain/gateway/entrypoint.sh | 15 + .../internal/keymanager/vault/manager.go | 4 +- ci/prod/compose/chain_gateway.dockerfile | 6 +- ci/prod/compose/chain_gateway.yml | 44 ++- ci/prod/compose/vault-agent/chain-gateway.hcl | 20 ++ ci/prod/scripts/deploy/chain_gateway.sh | 17 +- ci/scripts/chain_gateway/deploy.sh | 7 +- ci/scripts/common/bump_version.sh | 280 ++---------------- infra/vault/docker-compose.yml | 51 ++++ 11 files changed, 188 insertions(+), 272 deletions(-) create mode 100644 api/chain/gateway/entrypoint.sh create mode 100644 ci/prod/compose/vault-agent/chain-gateway.hcl create mode 100644 infra/vault/docker-compose.yml diff --git a/.woodpecker/bump_version.yml b/.woodpecker/bump_version.yml index 49e5703..9c13308 100644 --- a/.woodpecker/bump_version.yml +++ b/.woodpecker/bump_version.yml @@ -12,8 +12,8 @@ depends_on: - payments_orchestrator when: - - event: push - branch: main + event: push + branch: main steps: - name: bump-version @@ -21,7 +21,13 @@ steps: environment: GIT_AUTHOR_NAME: woodpecker GIT_AUTHOR_EMAIL: ci@sendico.io + GIT_COMMITTER_NAME: woodpecker + GIT_COMMITTER_EMAIL: ci@sendico.io commands: - set -euo pipefail - apk add --no-cache git + # make sure git knows who commits + - git config user.name "$GIT_AUTHOR_NAME" + - git config user.email "$GIT_AUTHOR_EMAIL" + # run your script (must do commit + push) - sh ci/scripts/common/bump_version.sh diff --git a/api/chain/gateway/config.yml b/api/chain/gateway/config.yml index dbd48ce..05dada2 100644 --- a/api/chain/gateway/config.yml +++ b/api/chain/gateway/config.yml @@ -50,8 +50,8 @@ service_wallet: key_management: driver: vault settings: - address: "https://vault.sendico.io:8200" - token_env: CHAIN_GATEWAY_VAULT_TOKEN + address: "https://vault.sendico.io" + token_env: VAULT_TOKEN namespace: "" - mount_path: secret + mount_path: kv key_prefix: chain/gateway/wallets diff --git a/api/chain/gateway/entrypoint.sh b/api/chain/gateway/entrypoint.sh new file mode 100644 index 0000000..965b66d --- /dev/null +++ b/api/chain/gateway/entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/sh +set -eu + +if [ -n "${VAULT_TOKEN_FILE:-}" ] && [ -f "${VAULT_TOKEN_FILE}" ]; then + token="$(cat "${VAULT_TOKEN_FILE}" 2>/dev/null | tr -d '[:space:]')" + if [ -n "${token}" ]; then + export VAULT_TOKEN="${token}" + fi +fi + +if [ -z "${VAULT_TOKEN:-}" ]; then + echo "[entrypoint] VAULT_TOKEN is not set; expected Vault Agent sink to write a token to ${VAULT_TOKEN_FILE:-/run/vault/token}" >&2 +fi + +exec /app/chain-gateway "$@" diff --git a/api/chain/gateway/internal/keymanager/vault/manager.go b/api/chain/gateway/internal/keymanager/vault/manager.go index 85f9b37..9e7db59 100644 --- a/api/chain/gateway/internal/keymanager/vault/manager.go +++ b/api/chain/gateway/internal/keymanager/vault/manager.go @@ -55,8 +55,8 @@ func New(logger mlogger.Logger, cfg Config) (*Manager, error) { } token := strings.TrimSpace(os.Getenv(tokenEnv)) if token == "" { - logger.Error("vault token env not set", zap.String("env", tokenEnv)) - return nil, merrors.InvalidArgument("vault key manager: token env " + tokenEnv + " is not set") + logger.Error("vault token missing; expected Vault Agent to export token", zap.String("env", tokenEnv)) + return nil, merrors.InvalidArgument("vault key manager: token env " + tokenEnv + " is not set (expected Vault Agent sink to populate it)") } mountPath := strings.Trim(strings.TrimSpace(cfg.MountPath), "/") if mountPath == "" { diff --git a/ci/prod/compose/chain_gateway.dockerfile b/ci/prod/compose/chain_gateway.dockerfile index 028eaa6..b02d311 100644 --- a/ci/prod/compose/chain_gateway.dockerfile +++ b/ci/prod/compose/chain_gateway.dockerfile @@ -35,7 +35,9 @@ RUN apk add --no-cache ca-certificates tzdata wget WORKDIR /app COPY api/chain/gateway/config.yml /app/config.yml COPY api/chain/gateway/env /app/env +COPY api/chain/gateway/entrypoint.sh /app/entrypoint.sh COPY --from=build /out/chain-gateway /app/chain-gateway +RUN chmod +x /app/entrypoint.sh EXPOSE 50070 9403 -ENTRYPOINT ["/app/chain-gateway"] -CMD ["--config.file", "/app/config.yml"] +ENTRYPOINT ["/app/entrypoint.sh"] +CMD ["/app/chain-gateway","--config.file","/app/config.yml"] diff --git a/ci/prod/compose/chain_gateway.yml b/ci/prod/compose/chain_gateway.yml index 66fc404..4a3a770 100644 --- a/ci/prod/compose/chain_gateway.yml +++ b/ci/prod/compose/chain_gateway.yml @@ -5,6 +5,14 @@ x-common-env: &common-env - ../env/.env.runtime - ../env/.env.version +volumes: + chain-gateway-vault-run: + driver: local + driver_opts: + type: tmpfs + device: tmpfs + o: size=8m,uid=0,gid=0,mode=0700 + networks: sendico-net: external: true @@ -33,11 +41,16 @@ services: CHAIN_GATEWAY_ARBITRUM_RPC_URL: ${CHAIN_GATEWAY_ARBITRUM_RPC_URL} CHAIN_GATEWAY_SERVICE_WALLET_KEY: ${CHAIN_GATEWAY_SERVICE_WALLET_KEY} CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS: ${CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS} - CHAIN_GATEWAY_VAULT_TOKEN: ${CHAIN_GATEWAY_VAULT_TOKEN} + VAULT_TOKEN_FILE: /run/vault/token command: ["--config.file", "/app/config.yml"] ports: - "0.0.0.0:${CHAIN_GATEWAY_GRPC_PORT}:50070" - "0.0.0.0:${CHAIN_GATEWAY_METRICS_PORT}:9403" + volumes: + - chain-gateway-vault-run:/run/vault:ro + depends_on: + sendico_chain_gateway_vault_agent: + condition: service_healthy healthcheck: test: ["CMD-SHELL","wget -qO- http://localhost:9403/health | grep -q '\"status\":\"ok\"'"] interval: 30s @@ -46,3 +59,32 @@ services: start_period: 60s networks: - sendico-net + + sendico_chain_gateway_vault_agent: + <<: *common-env + container_name: sendico-chain-gateway-vault-agent + restart: unless-stopped + image: hashicorp/vault:latest + pull_policy: always + cap_add: ["IPC_LOCK"] + environment: + VAULT_ADDR: ${VAULT_ADDR} + CHAIN_GATEWAY_VAULT_ROLE_ID: ${CHAIN_GATEWAY_VAULT_ROLE_ID} + CHAIN_GATEWAY_VAULT_SECRET_ID: ${CHAIN_GATEWAY_VAULT_SECRET_ID} + command: > + sh -lc 'set -euo pipefail; umask 077; + : "${CHAIN_GATEWAY_VAULT_ROLE_ID:?}"; : "${CHAIN_GATEWAY_VAULT_SECRET_ID:?}"; + printf "%s" "$CHAIN_GATEWAY_VAULT_ROLE_ID" > /run/vault/role_id; + printf "%s" "$CHAIN_GATEWAY_VAULT_SECRET_ID" > /run/vault/secret_id; + unset CHAIN_GATEWAY_VAULT_ROLE_ID CHAIN_GATEWAY_VAULT_SECRET_ID; + exec vault agent -config=/etc/vault/agent/chain-gateway.hcl' + volumes: + - ./vault-agent/chain-gateway.hcl:/etc/vault/agent/chain-gateway.hcl:ro + - chain-gateway-vault-run:/run/vault + healthcheck: + test: ["CMD","test","-s","/run/vault/token"] + interval: 10s + timeout: 5s + retries: 6 + networks: + - sendico-net diff --git a/ci/prod/compose/vault-agent/chain-gateway.hcl b/ci/prod/compose/vault-agent/chain-gateway.hcl new file mode 100644 index 0000000..3dbfc80 --- /dev/null +++ b/ci/prod/compose/vault-agent/chain-gateway.hcl @@ -0,0 +1,20 @@ +vault { + address = "https://vault.sendico.io" +} + +auto_auth { + method "approle" { + mount_path = "auth/approle" + config = { + role_id_file_path = "/run/vault/role_id" + secret_id_file_path = "/run/vault/secret_id" + } + } + + sink "file" { + config = { + path = "/run/vault/token" + mode = 0600 + } + } +} diff --git a/ci/prod/scripts/deploy/chain_gateway.sh b/ci/prod/scripts/deploy/chain_gateway.sh index 8207a74..d31d5dd 100755 --- a/ci/prod/scripts/deploy/chain_gateway.sh +++ b/ci/prod/scripts/deploy/chain_gateway.sh @@ -21,7 +21,8 @@ REQUIRED_SECRETS=( CHAIN_GATEWAY_ARBITRUM_RPC_URL CHAIN_GATEWAY_SERVICE_WALLET_KEY CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS - CHAIN_GATEWAY_VAULT_TOKEN + CHAIN_GATEWAY_VAULT_ROLE_ID + CHAIN_GATEWAY_VAULT_SECRET_ID NATS_USER NATS_PASSWORD NATS_URL @@ -48,7 +49,8 @@ CHAIN_GATEWAY_MONGO_PASSWORD_B64="$(b64enc "${CHAIN_GATEWAY_MONGO_PASSWORD}")" CHAIN_GATEWAY_ARBITRUM_RPC_URL_B64="$(b64enc "${CHAIN_GATEWAY_ARBITRUM_RPC_URL}")" CHAIN_GATEWAY_SERVICE_WALLET_KEY_B64="$(b64enc "${CHAIN_GATEWAY_SERVICE_WALLET_KEY}")" CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS_B64="$(b64enc "${CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS}")" -CHAIN_GATEWAY_VAULT_TOKEN_B64="$(b64enc "${CHAIN_GATEWAY_VAULT_TOKEN}")" +CHAIN_GATEWAY_VAULT_ROLE_ID_B64="$(b64enc "${CHAIN_GATEWAY_VAULT_ROLE_ID}")" +CHAIN_GATEWAY_VAULT_SECRET_ID_B64="$(b64enc "${CHAIN_GATEWAY_VAULT_SECRET_ID}")" NATS_USER_B64="$(b64enc "${NATS_USER}")" NATS_PASSWORD_B64="$(b64enc "${NATS_PASSWORD}")" NATS_URL_B64="$(b64enc "${NATS_URL}")" @@ -67,7 +69,7 @@ fi RSYNC_FLAGS=(-az --delete) [[ "${DEBUG_DEPLOY:-0}" = "1" ]] && RSYNC_FLAGS=(-avz --delete) -ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" "mkdir -p ${REMOTE_DIR}/{compose,env}" +ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" "mkdir -p ${REMOTE_DIR}/compose/secrets ${REMOTE_DIR}/env" rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" ci/prod/compose/ "$REMOTE_TARGET:${REMOTE_DIR}/compose/" rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" ci/prod/.env.runtime "$REMOTE_TARGET:${REMOTE_DIR}/env/.env.runtime" @@ -85,7 +87,8 @@ ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" \ CHAIN_GATEWAY_ARBITRUM_RPC_URL_B64="$CHAIN_GATEWAY_ARBITRUM_RPC_URL_B64" \ CHAIN_GATEWAY_SERVICE_WALLET_KEY_B64="$CHAIN_GATEWAY_SERVICE_WALLET_KEY_B64" \ CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS_B64="$CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS_B64" \ - CHAIN_GATEWAY_VAULT_TOKEN_B64="$CHAIN_GATEWAY_VAULT_TOKEN_B64" \ + CHAIN_GATEWAY_VAULT_ROLE_ID_B64="$CHAIN_GATEWAY_VAULT_ROLE_ID_B64" \ + CHAIN_GATEWAY_VAULT_SECRET_ID_B64="$CHAIN_GATEWAY_VAULT_SECRET_ID_B64" \ NATS_USER_B64="$NATS_USER_B64" \ NATS_PASSWORD_B64="$NATS_PASSWORD_B64" \ NATS_URL_B64="$NATS_URL_B64" \ @@ -135,7 +138,8 @@ CHAIN_GATEWAY_MONGO_PASSWORD="$(decode_b64 "$CHAIN_GATEWAY_MONGO_PASSWORD_B64")" CHAIN_GATEWAY_ARBITRUM_RPC_URL="$(decode_b64 "$CHAIN_GATEWAY_ARBITRUM_RPC_URL_B64")" CHAIN_GATEWAY_SERVICE_WALLET_KEY="$(decode_b64 "$CHAIN_GATEWAY_SERVICE_WALLET_KEY_B64")" CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS="$(decode_b64 "$CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS_B64")" -CHAIN_GATEWAY_VAULT_TOKEN="$(decode_b64 "$CHAIN_GATEWAY_VAULT_TOKEN_B64")" +CHAIN_GATEWAY_VAULT_ROLE_ID="$(decode_b64 "$CHAIN_GATEWAY_VAULT_ROLE_ID_B64")" +CHAIN_GATEWAY_VAULT_SECRET_ID="$(decode_b64 "$CHAIN_GATEWAY_VAULT_SECRET_ID_B64")" NATS_USER="$(decode_b64 "$NATS_USER_B64")" NATS_PASSWORD="$(decode_b64 "$NATS_PASSWORD_B64")" NATS_URL="$(decode_b64 "$NATS_URL_B64")" @@ -143,8 +147,9 @@ NATS_URL="$(decode_b64 "$NATS_URL_B64")" export CHAIN_GATEWAY_MONGO_USER CHAIN_GATEWAY_MONGO_PASSWORD export CHAIN_GATEWAY_ARBITRUM_RPC_URL export CHAIN_GATEWAY_SERVICE_WALLET_KEY CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS -export CHAIN_GATEWAY_VAULT_TOKEN +export CHAIN_GATEWAY_VAULT_ROLE_ID CHAIN_GATEWAY_VAULT_SECRET_ID export NATS_USER NATS_PASSWORD NATS_URL + COMPOSE_PROJECT_NAME="$COMPOSE_PROJECT" export COMPOSE_PROJECT_NAME read -r -a SERVICES <<<"${SERVICES_LINE}" diff --git a/ci/scripts/chain_gateway/deploy.sh b/ci/scripts/chain_gateway/deploy.sh index f3d701b..417b070 100755 --- a/ci/scripts/chain_gateway/deploy.sh +++ b/ci/scripts/chain_gateway/deploy.sh @@ -61,7 +61,12 @@ export CHAIN_GATEWAY_ARBITRUM_RPC_URL="$(./ci/vlt kv_get kv "${CHAIN_GATEWAY_RPC export CHAIN_GATEWAY_SERVICE_WALLET_KEY="$(./ci/vlt kv_get kv "${CHAIN_GATEWAY_WALLET_SECRET_PATH}" private_key)" export CHAIN_GATEWAY_SERVICE_WALLET_ADDRESS="$(./ci/vlt kv_get kv "${CHAIN_GATEWAY_WALLET_SECRET_PATH}" address || true)" -export CHAIN_GATEWAY_VAULT_TOKEN="$(./ci/vlt kv_get kv "${CHAIN_GATEWAY_VAULT_SECRET_PATH}" token)" +export CHAIN_GATEWAY_VAULT_ROLE_ID="$(./ci/vlt kv_get kv "${CHAIN_GATEWAY_VAULT_SECRET_PATH}" role_id)" +export CHAIN_GATEWAY_VAULT_SECRET_ID="$(./ci/vlt kv_get kv "${CHAIN_GATEWAY_VAULT_SECRET_PATH}" secret_id)" +if [ -z "${CHAIN_GATEWAY_VAULT_ROLE_ID}" ] || [ -z "${CHAIN_GATEWAY_VAULT_SECRET_ID}" ]; then + echo "[chain-gateway-deploy] vault approle creds are empty for path ${CHAIN_GATEWAY_VAULT_SECRET_PATH}" >&2 + exit 1 +fi export NATS_USER="$(./ci/vlt kv_get kv sendico/nats user)" export NATS_PASSWORD="$(./ci/vlt kv_get kv sendico/nats password)" diff --git a/ci/scripts/common/bump_version.sh b/ci/scripts/common/bump_version.sh index eba26d1..e126ad6 100755 --- a/ci/scripts/common/bump_version.sh +++ b/ci/scripts/common/bump_version.sh @@ -1,264 +1,34 @@ -#!/bin/sh -set -eu +# /bin/bash -log() { - printf '[bump-version] %s\n' "$*" -} +echo "====================================" +echo "Incrementing build version..." +echo "====================================" +VERSION_FILE=./version -error() { - printf '[bump-version] %s\n' "$*" >&2 -} +NEW_VERSION=$(cat $VERSION_FILE | awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{$NF=sprintf("%0*d", length($NF), ($NF+1)); print}') +echo $NEW_VERSION > $VERSION_FILE -die() { - error "${1:-fatal error}" - exit "${2:-1}" -} +echo "New version is "$NEW_VERSION -var_value() { - # shellcheck disable=SC2039 - eval "printf '%s' \"\${$1:-}\"" -} - -normalize_host() { - value="$1" - if [ -z "${value}" ]; then - printf '%s' "" - return - fi - printf '%s' "${value}" | sed -E ' - s#^[[:alpha:]][[:alnum:]+.-]*://##; - s#^[^@]*@##; - s#[:/].*$##; - ' -} - -extract_proto() { - url="$1" - if printf '%s' "${url}" | grep -Eq '^[[:alpha:]][[:alnum:]+.-]*://'; then - printf '%s' "${url}" | sed -E 's#^([[:alpha:]][[:alnum:]+.-]*://).*#\1#' | tr -d ':/' - return - fi - if printf '%s' "${url}" | grep -Eq '^[^@]+@[^:]+:'; then - printf 'ssh' - return - fi - printf 'https' -} - -discover_env_credentials() { - DEFAULT_GIT_USER="${GIT_AUTH_DEFAULT_USER:-woodpecker}" - while IFS=: read -r user_var pass_var; do - [ -n "${pass_var}" ] || continue - pass="$(var_value "${pass_var}")" - [ -n "${pass}" ] || continue - if [ "${user_var}" = "-" ] || [ -z "${user_var}" ]; then - user="" - else - user="$(var_value "${user_var}")" - fi - if [ -z "${user}" ]; then - user="${DEFAULT_GIT_USER}" - fi - GIT_AUTH_USER="${user}" - GIT_AUTH_PASS="${pass}" - GIT_AUTH_SOURCE="env:${user_var:--}/${pass_var}" - return 0 - done <<'EOF' -CI_GIT_USERNAME:CI_GIT_PASSWORD -CI_GIT_USERNAME:CI_GIT_TOKEN -CI_GIT_USERNAME:CI_GIT_PASS -CI_GIT_USER:CI_GIT_PASSWORD -CI_GIT_USER:CI_GIT_TOKEN -CI_NETRC_USERNAME:CI_NETRC_PASSWORD -CI_NETRC_LOGIN:CI_NETRC_PASSWORD -WOODPECKER_GIT_USERNAME:WOODPECKER_GIT_PASSWORD -WOODPECKER_GIT_USERNAME:WOODPECKER_GIT_TOKEN -WOODPECKER_NETRC_USERNAME:WOODPECKER_NETRC_PASSWORD -WOODPECKER_NETRC_LOGIN:WOODPECKER_NETRC_PASSWORD -DRONE_GIT_USERNAME:DRONE_GIT_PASSWORD -DRONE_GIT_USERNAME:DRONE_GIT_TOKEN -DRONE_NETRC_USERNAME:DRONE_NETRC_PASSWORD -DRONE_NETRC_LOGIN:DRONE_NETRC_PASSWORD -GIT_USERNAME:GIT_PASSWORD -GIT_USER:GIT_PASS -GIT_AUTH_USERNAME:GIT_AUTH_PASSWORD --:GIT_PASSWORD --:GIT_PASS -EOF - - for token_var in CI_GIT_TOKEN WOODPECKER_GIT_TOKEN DRONE_GIT_TOKEN GIT_TOKEN GITEA_TOKEN; do - token="$(var_value "${token_var}")" - if [ -n "${token}" ]; then - user="$(var_value CI_GIT_USERNAME)" - [ -n "${user}" ] || user="$(var_value WOODPECKER_GIT_USERNAME)" - [ -n "${user}" ] || user="$(var_value DRONE_GIT_USERNAME)" - [ -n "${user}" ] || user="${DEFAULT_GIT_USER}" - GIT_AUTH_USER="${user}" - GIT_AUTH_PASS="${token}" - GIT_AUTH_SOURCE="env:${token_var}" - return 0 - fi - done - return 1 -} - -discover_vault_credentials() { - VAULT_MOUNT="${GIT_CREDENTIALS_VAULT_MOUNT:-kv}" - VAULT_PATH="${GIT_CREDENTIALS_VAULT_PATH:-${CI_GIT_VAULT_PATH:-}}" - [ -n "${VAULT_PATH}" ] || return 1 - VLT_BIN="${GIT_VAULT_HELPER:-./ci/vlt}" - if [ ! -x "${VLT_BIN}" ]; then - return 1 - fi - user_field="${GIT_CREDENTIALS_VAULT_USER_FIELD:-username}" - pass_field="${GIT_CREDENTIALS_VAULT_PASSWORD_FIELD:-password}" - if ! GIT_AUTH_USER="$("${VLT_BIN}" kv_get "${VAULT_MOUNT}" "${VAULT_PATH}" "${user_field}" 2>/dev/null)"; then - return 1 - fi - if ! GIT_AUTH_PASS="$("${VLT_BIN}" kv_get "${VAULT_MOUNT}" "${VAULT_PATH}" "${pass_field}" 2>/dev/null)"; then - return 1 - fi - GIT_AUTH_SOURCE="vault:${VAULT_MOUNT}/${VAULT_PATH}" - return 0 -} - -write_netrc() { - host="$1" - user="$2" - pass="$3" - file="${HOME:-/root}/.netrc" - { - printf 'machine %s\n' "${host}" - printf 'login %s\n' "${user}" - printf 'password %s\n' "${pass}" - } > "${file}" - chmod 600 "${file}" -} - -setup_https_credentials() { - host="$1" - netrc="${HOME:-/root}/.netrc" - if [ -s "${netrc}" ] && awk -v host="${host}" ' - $1 == "machine" && $2 == host { found=1; exit } - END { exit found ? 0 : 1 } - ' "${netrc}"; then - log "reusing credentials already present in ${netrc}" - return 0 - fi - if discover_env_credentials; then - masked="$(printf '%s' "${GIT_AUTH_USER}" | cut -c1-2)***" - log "using ${GIT_AUTH_SOURCE} for ${host} (user ${masked})" - write_netrc "${host}" "${GIT_AUTH_USER}" "${GIT_AUTH_PASS}" - return 0 - fi - if discover_vault_credentials; then - masked="$(printf '%s' "${GIT_AUTH_USER}" | cut -c1-2)***" - log "using ${GIT_AUTH_SOURCE} for ${host} (user ${masked})" - write_netrc "${host}" "${GIT_AUTH_USER}" "${GIT_AUTH_PASS}" - return 0 - fi - return 1 -} - -START_DIR="$(pwd)" -log "invoked from ${START_DIR}" - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -REPO_ROOT="" -if command -v git >/dev/null 2>&1; then - REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)" -fi -if [ -z "${REPO_ROOT}" ]; then - REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)" -fi -log "repo root resolved to ${REPO_ROOT}" -cd "${REPO_ROOT}" - -VERSION_FILE="./version" -if [ ! -f "${VERSION_FILE}" ]; then - if git cat-file -e "HEAD:version" 2>/dev/null; then - error "version file missing in workspace, restoring from HEAD" - git show "HEAD:version" > "${VERSION_FILE}" - else - die "version file not found: ${VERSION_FILE}" - fi +echo "====================================" +echo "Bumping client version..." +echo "====================================" +FILE="./frontend/mweb/pubspec.yaml" +if sed --version >/dev/null 2>&1; then + # GNU sed + sed -i "s/^version: .*/version: ${NEW_VERSION}+1/" "$FILE" +else + # BSD/macOS sed + sed -i '' -e "s/^version: .*/version: ${NEW_VERSION}+1/" "$FILE" fi -CURRENT_VERSION="$(cat "${VERSION_FILE}")" -NEXT_VERSION="$(printf '%s' "${CURRENT_VERSION}" | awk -F. -v OFS=. ' - function pad(value, width, result, i) { - result=value "" - if (length(result) >= width) { - return result - } - i = width - length(result) - while (i-- > 0) { - result = "0" result - } - return result - } - NF==1 { print ++$NF; next } - { - last = $NF + 1 - $NF = pad(last, length($NF)) - print - }')" +set -euo pipefail -printf '%s\n' "${NEXT_VERSION}" > "${VERSION_FILE}" -log "${CURRENT_VERSION} -> ${NEXT_VERSION}" +# update version file(s) here +# e.g.: ./ci/scripts/common/update_version_file.sh -git add "${VERSION_FILE}" -if git diff --cached --quiet; then - log "no changes staged, skipping commit" - exit 0 +if ! git diff --quiet; then + git add . + git commit -m "chore: bump build version [skip ci]" + git push origin HEAD:main fi - -AUTHOR_NAME="${GIT_AUTHOR_NAME:-woodpecker}" -AUTHOR_EMAIL="${GIT_AUTHOR_EMAIL:-ci@sendico.io}" -git config user.name "${AUTHOR_NAME}" -git config user.email "${AUTHOR_EMAIL}" - -git commit -m "chore(ci): bump version to ${NEXT_VERSION}" - -BRANCH="${WOODPECKER_BRANCH:-}" -if [ -z "${BRANCH}" ] || [ "${BRANCH}" = "HEAD" ]; then - BRANCH="$(git rev-parse --abbrev-ref HEAD)" -fi - -REMOTE_URL="${CI_REPO_REMOTE:-${WOODPECKER_GIT_REMOTE:-${DRONE_REMOTE_URL:-}}}" -if [ -z "${REMOTE_URL}" ]; then - REMOTE_URL="$(git config --get remote.origin.url 2>/dev/null || true)" -fi -[ -n "${REMOTE_URL}" ] || die "unable to determine git remote url" - -REMOTE_PROTO="$(extract_proto "${REMOTE_URL}")" -REMOTE_HOST="$(normalize_host "${REMOTE_URL}")" -[ -n "${REMOTE_HOST}" ] || die "unable to determine remote host from ${REMOTE_URL}" - -log "using remote ${REMOTE_URL}" -git remote set-url origin "${REMOTE_URL}" - -case "${REMOTE_PROTO}" in - ssh) - if [ -n "${GIT_SSH_KEY_B64:-}" ]; then - SSH_KEY_FILE="${HOME:-/root}/.ssh/id_ci" - mkdir -p "$(dirname "${SSH_KEY_FILE}")" - printf '%s' "${GIT_SSH_KEY_B64}" | base64 -d > "${SSH_KEY_FILE}" - chmod 600 "${SSH_KEY_FILE}" - export GIT_SSH_COMMAND="ssh -i ${SSH_KEY_FILE} -o StrictHostKeyChecking=no" - log "configured SSH key for git push" - else - log "no SSH key provided, relying on existing agent configuration" - fi - ;; - http|https) - if ! setup_https_credentials "${REMOTE_HOST}"; then - die "no git credentials detected (set CI_GIT_USERNAME/CI_GIT_PASSWORD, WOODPECKER_GIT_USERNAME/WOODPECKER_GIT_PASSWORD, or configure GIT_CREDENTIALS_VAULT_PATH)" - fi - ;; - *) - log "unknown git protocol ${REMOTE_PROTO}, attempting push without extra credentials" - ;; -esac - -git push origin "HEAD:${BRANCH}" diff --git a/infra/vault/docker-compose.yml b/infra/vault/docker-compose.yml new file mode 100644 index 0000000..d4f2a9a --- /dev/null +++ b/infra/vault/docker-compose.yml @@ -0,0 +1,51 @@ +networks: + cicd: + external: true + +volumes: + vault1_data: + vault2_data: + vault3_data: + +services: + vault: + image: hashicorp/vault:latest + cap_add: [ "IPC_LOCK" ] + ulimits: { memlock: { soft: -1, hard: -1 } } + environment: { VAULT_ADDR: "http://127.0.0.1:8200" } + command: vault server -config=/vault/config/vault.hcl + volumes: + - vault1_data:/vault/file + - ./config/vault1.hcl:/vault/config/vault.hcl:ro + networks: [ cicd ] + labels: + - "traefik.enable=true" + - "traefik.docker.network=cicd" + - "traefik.http.routers.vault.rule=Host(`vault.sendico.io`)" + - "traefik.http.routers.vault.entrypoints=websecure" + - "traefik.http.routers.vault.tls.certresolver=letsencrypt" + - "traefik.http.routers.vault.middlewares=secure-headers@file" + - "traefik.http.services.vault.loadbalancer.server.port=8200" + - "traefik.http.services.vault.loadbalancer.server.scheme=http" + + vault2: + image: hashicorp/vault:latest + cap_add: [ "IPC_LOCK" ] + ulimits: { memlock: { soft: -1, hard: -1 } } + environment: { VAULT_ADDR: "http://127.0.0.1:8200" } + command: vault server -config=/vault/config/vault.hcl + volumes: + - vault2_data:/vault/file + - ./config/vault2.hcl:/vault/config/vault.hcl:ro + networks: [ cicd ] + + vault3: + image: hashicorp/vault:latest + cap_add: [ "IPC_LOCK" ] + ulimits: { memlock: { soft: -1, hard: -1 } } + environment: { VAULT_ADDR: "http://127.0.0.1:8200" } + command: vault server -config=/vault/config/vault.hcl + volumes: + - vault3_data:/vault/file + - ./config/vault3.hcl:/vault/config/vault.hcl:ro + networks: [ cicd ] \ No newline at end of file