CI/CD Integration
Soup integrates with any CI/CD system that can run shell commands.
Authentication
Section titled “Authentication”Service Tokens
Section titled “Service Tokens”For CI/CD, create a dedicated API token:
- Cloud: Go to Settings → API Tokens → Create Token
- Self-hosted: Use the CLI to create a token
Store the token as a secret in your CI/CD system.
Environment Variables
Section titled “Environment Variables”Set SOUP_TOKEN in your pipeline:
export SOUP_TOKEN=your-tokensoup get my-app production DATABASE_URLGitHub Actions
Section titled “GitHub Actions”Basic Example
Section titled “Basic Example”name: Deploy
on: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Install Soup CLI run: curl -fsSL https://soup.dev/install.sh | sh
- name: Deploy with secrets env: SOUP_TOKEN: ${{ secrets.SOUP_TOKEN }} run: | eval $(soup export my-app production) ./deploy.shReusable Action
Section titled “Reusable Action”Create .github/actions/soup/action.yml:
name: 'Soup Secrets'description: 'Load secrets from Soup'inputs: project: description: 'Soup project name' required: true environment: description: 'Soup environment' required: true token: description: 'Soup API token' required: trueruns: using: 'composite' steps: - name: Install Soup shell: bash run: curl -fsSL https://soup.dev/install.sh | sh
- name: Export secrets shell: bash env: SOUP_TOKEN: ${{ inputs.token }} run: | soup export ${{ inputs.project }} ${{ inputs.environment }} --format shell >> $GITHUB_ENVUse it:
- uses: ./.github/actions/soup with: project: my-app environment: production token: ${{ secrets.SOUP_TOKEN }}
- name: Deploy run: echo $DATABASE_URL # Secret is availableGitLab CI
Section titled “GitLab CI”stages: - deploy
deploy: stage: deploy image: alpine:latest before_script: - apk add curl bash - curl -fsSL https://soup.dev/install.sh | sh script: - eval $(soup export my-app production) - ./deploy.sh variables: SOUP_TOKEN: $SOUP_TOKEN # Set in GitLab CI/CD settingsCircleCI
Section titled “CircleCI”version: 2.1
jobs: deploy: docker: - image: cimg/base:stable steps: - checkout - run: name: Install Soup command: curl -fsSL https://soup.dev/install.sh | sh - run: name: Deploy command: | eval $(soup export my-app production) ./deploy.sh
workflows: deploy: jobs: - deploy: context: soup-secrets # Contains SOUP_TOKENJenkins
Section titled “Jenkins”pipeline { agent any
environment { SOUP_TOKEN = credentials('soup-token') }
stages { stage('Install Soup') { steps { sh 'curl -fsSL https://soup.dev/install.sh | sh' } }
stage('Deploy') { steps { sh ''' eval $(soup export my-app production) ./deploy.sh ''' } } }}Docker Builds
Section titled “Docker Builds”Build-time Secrets
Section titled “Build-time Secrets”# DockerfileFROM node:20-alpine
# Install soup CLIRUN curl -fsSL https://soup.dev/install.sh | sh
# Build with secrets (use BuildKit)RUN --mount=type=secret,id=soup_token \ export SOUP_TOKEN=$(cat /run/secrets/soup_token) && \ eval $(soup export my-app production) && \ npm run buildBuild with:
DOCKER_BUILDKIT=1 docker build \ --secret id=soup_token,env=SOUP_TOKEN \ -t my-app .Runtime Secrets
Section titled “Runtime Secrets”Better approach - inject at runtime:
FROM node:20-alpine
# Install appCOPY . .RUN npm install
# Entrypoint loads secretsCOPY entrypoint.sh /entrypoint.shENTRYPOINT ["/entrypoint.sh"]CMD ["npm", "start"]#!/bin/sheval $(soup export my-app production)exec "$@"Kubernetes
Section titled “Kubernetes”Using Init Container
Section titled “Using Init Container”apiVersion: v1kind: Podspec: initContainers: - name: load-secrets image: alpine:latest command: - sh - -c - | curl -fsSL https://soup.dev/install.sh | sh soup export my-app production --format dotenv > /secrets/.env env: - name: SOUP_TOKEN valueFrom: secretKeyRef: name: soup-credentials key: token volumeMounts: - name: secrets mountPath: /secrets
containers: - name: app image: my-app:latest command: ["sh", "-c", "source /secrets/.env && npm start"] volumeMounts: - name: secrets mountPath: /secrets
volumes: - name: secrets emptyDir: {}External Secrets Operator
Section titled “External Secrets Operator”(Coming soon) Native integration with External Secrets Operator.
Best Practices
Section titled “Best Practices”1. Use Dedicated Tokens
Section titled “1. Use Dedicated Tokens”Create separate tokens for each CI/CD pipeline with minimal permissions.
2. Rotate Tokens Regularly
Section titled “2. Rotate Tokens Regularly”Update tokens periodically and after team member changes.
3. Cache the CLI
Section titled “3. Cache the CLI”In frequently-run pipelines, cache the Soup CLI installation:
# GitHub Actions- uses: actions/cache@v4 with: path: ~/.local/bin/soup key: soup-cli-${{ runner.os }}4. Fail Fast
Section titled “4. Fail Fast”Check for Soup CLI installation and authentication early:
#!/bin/bashset -e
# Verify soup is installed and authenticatedsoup whoami || exit 1
# Continue with deploymenteval $(soup export my-app production)./deploy.sh5. Log (Safely)
Section titled “5. Log (Safely)”Log that secrets were loaded without logging values:
echo "Loading secrets from Soup..."SECRETS=$(soup export my-app production)echo "Loaded $(echo "$SECRETS" | wc -l) secrets"eval "$SECRETS"