Skip to content

CI/CD Integration

df-cli is designed to work in automated pipelines. This guide covers non-interactive authentication, build validation, automated publishing, reproducible dependency resolution, and exit code handling.

Authentication

Interactive OAuth login is not available in CI. Use token-based authentication instead:

df-cli login --endpoint https://packages.dataflex.dev \
  --access-token "$ACCESS_TOKEN"

Optionally include a refresh token so df-cli can automatically refresh the session when the access token expires:

df-cli login --endpoint https://packages.dataflex.dev \
  --access-token "$ACCESS_TOKEN" \
  --refresh-token "$REFRESH_TOKEN"

Tokens are JWT-based and validated locally for expiration before being stored. On Windows runners, credentials are persisted in Windows Credential Manager.

Generate tokens through the admin panel at packages.dataflex.dev and store them as pipeline secrets.


Build Validation

Check If a Build Is Needed

The --check flag validates whether any files need recompilation without actually producing output:

df-cli build MyProject.sws --check
Exit Code Meaning
0 Build is up to date — no recompilation needed.
-1 Rebuild is needed.
Other Configuration or compilation error.

This is useful as a gate step to skip expensive build stages when nothing has changed.

Build with Error Handling

df-cli build MyProject.sws --target MyApp

A non-zero exit code indicates failure. Combine with --verbose for detailed compiler output in build logs:

df-cli build MyProject.sws --target MyApp --verbose

Force Build Past Configuration Errors

If the workspace configuration has non-fatal issues (e.g. a missing optional dependency) but you want the build to proceed anyway:

df-cli build MyProject.sws --force

Without --force, configuration errors abort the build immediately. With it, df-cli skips dependency cache verification and file installation, logs a warning, and continues to build. Dependency paths are still registered so the compiler can find include directories, but no files are copied or hash-checked. This is most useful when combined with a lock file that pins known-good dependency versions.


Reproducible Builds with Lock Files

The .sws.lock file pins every dependency to an exact version. When present, df-cli uses the locked versions instead of resolving the latest compatible release from the repository.

Workflow

  1. A developer runs df-cli package install or df-cli package upgrade locally, which creates or updates MyProject.sws.lock.
  2. The lock file is committed to version control.
  3. In CI, df-cli build reads the lock file and installs the exact same dependency versions.

This ensures that builds are deterministic — a pipeline will never break because a dependency published a new version overnight.

When the Lock File Is Ignored

If a version constraint in the .sws file changes and the locked version no longer satisfies it, the lock is bypassed for that dependency and a new version is fetched. The lock file is updated after successful resolution.


Automated Publishing

To publish a package from CI without interactive prompts:

# Authenticate (once per pipeline, or cached)
df-cli login --endpoint https://packages.dataflex.dev \
  --access-token "$ACCESS_TOKEN"

# Push without confirmation prompt
df-cli package push MyLibrary.sws my-repository -y

The -y / --yes flag skips the confirmation dialog that normally displays the license and asks for approval. The full pipeline for a new version would be:

# Validate the workspace configuration
df-cli config MyLibrary.sws

# Build to verify compilation succeeds
df-cli build MyLibrary.sws

# Push the package
df-cli package push MyLibrary.sws my-repository -y

After pushing, the version must still be published through the admin panel at packages.dataflex.dev. See Creating and Publishing Packages for the full workflow.


Machine-Readable Output

The config command supports --output-json for parsing workspace information programmatically:

df-cli config MyProject.sws --output-json

This outputs the full workspace configuration as JSON to stdout, including: - Workspace name, version, and license - All configured paths - The complete dependency tree (recursively loaded) - Project list with toolchain info - Repair information (broken dependencies, cache mismatches) - Package metadata

When --output-json is active, all interactive prompts are disabled and informational log messages are suppressed, making the output safe to pipe into tools like jq:

# Extract the product version
df-cli config MyProject.sws --output-json | jq -r '.product_version'

# List all direct dependencies
df-cli config MyProject.sws --output-json | jq '.dependencies | keys[]'

# Check if workspace loaded successfully
df-cli config MyProject.sws --output-json | jq '.loadedSuccessfully'

Colored Output

df-cli detects whether stdout is a terminal and disables color when output is piped. Some CI systems (GitHub Actions, GitLab CI, Azure Pipelines) support ANSI colors in their log viewers. To force colored output in these environments:

df-cli build MyProject.sws --force-color

Pipeline Examples

GitHub Actions — Build and Validate

jobs:
  build:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4

      - name: Check if build needed
        run: df-cli build MyProject.sws --check
        continue-on-error: true
        id: check

      - name: Build
        if: steps.check.outcome == 'failure'
        run: df-cli build MyProject.sws --verbose --force-color

GitHub Actions — Publish Package

jobs:
  publish:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4

      - name: Authenticate
        run: >
          df-cli login
          --endpoint https://packages.dataflex.dev
          --access-token "${{ secrets.DF_ACCESS_TOKEN }}"

      - name: Build
        run: df-cli build MyLibrary.sws --force-color

      - name: Push package
        run: df-cli package push MyLibrary.sws my-repository -y

GitHub Actions — Auto-Bump Version and Publish

This example reads the current version from the .sws file, bumps the patch number, commits the change, and pushes the package. It uses jq to modify the JSON in place.

jobs:
  release:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4

      - name: Bump patch version
        shell: bash
        run: |
          # Read current version from the .sws file
          CURRENT=$(jq -r '.package.version' MyLibrary.sws)
          echo "Current version: $CURRENT"

          # Split into major.minor.patch and increment patch
          IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
          NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))"
          echo "New version: $NEW_VERSION"

          # Write back to .sws file
          jq --arg v "$NEW_VERSION" '.package.version = $v' MyLibrary.sws > tmp.sws && mv tmp.sws MyLibrary.sws

      - name: Commit version bump
        run: |
          git config user.name "CI"
          git config user.email "ci@example.com"
          git add MyLibrary.sws
          git commit -m "chore: bump version to $(jq -r '.package.version' MyLibrary.sws)"
          git push

      - name: Authenticate
        run: >
          df-cli login
          --endpoint https://packages.dataflex.dev
          --access-token "${{ secrets.DF_ACCESS_TOKEN }}"

      - name: Build and push
        run: |
          df-cli build MyLibrary.sws --force-color
          df-cli package push MyLibrary.sws my-repository -y

To bump the minor version instead, replace the increment line:

NEW_VERSION="$MAJOR.$((MINOR + 1)).0"

GitLab CI — Build and Push

build:
  stage: build
  script:
    - df-cli build MyProject.sws --verbose --force-color

publish:
  stage: deploy
  script:
    - df-cli login --endpoint https://packages.dataflex.dev --access-token "$ACCESS_TOKEN"
    - df-cli package push MyLibrary.sws my-repository -y
  only:
    - tags