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
- A developer runs
df-cli package installordf-cli package upgradelocally, which creates or updatesMyProject.sws.lock. - The lock file is committed to version control.
- In CI,
df-cli buildreads 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