Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
dcafa6d
FEAT: Add conda packaging recipes and publish tooling for mssql-python
jahnvi480 Aug 14, 2026
a1ff766
FIX: Address PR review on conda recipes and harness
jahnvi480 Aug 14, 2026
0013f70
FIX: address round-2 conda recipe review (#563)
jahnvi480 Aug 14, 2026
ca0be45
Merge branch 'main' into jahnvi/conda-onboarding
jahnvi480 Aug 17, 2026
e10a4de
CHORE: sync conda build/validate/publish architecture from ADO
jahnvi480 Aug 18, 2026
8e7f217
CHORE: build mssql-python-odbc conda once (python-agnostic) in ODBC_B…
jahnvi480 Aug 18, 2026
43f23a8
Merge branch 'main' into jahnvi/conda-onboarding
jahnvi480 Aug 18, 2026
1f749d1
FIX: fail-closed conda driver-load probe + metadata-based release gate
jahnvi480 Aug 18, 2026
a8d42d6
FIX: genuinely cross-build osx-arm64 conda on the Intel macOS agent (…
jahnvi480 Aug 18, 2026
4695f6b
FIX: declare conda security deps for the ODBC driver companion (P1-4)
jahnvi480 Aug 18, 2026
599f03f
FIX: complete self-contained glibc ODBC payload (bundle libltdl.so.7)
jahnvi480 Aug 18, 2026
6d67a12
FIX: bundle musl libltdl too, add LGPL notice, add binary-audit gate
jahnvi480 Aug 18, 2026
d6e790c
FIX: drop unused libodbc.2.dylib (removes macOS Homebrew-libtool lan…
jahnvi480 Aug 18, 2026
81a34cf
FIX: keep shipped libodbc.2.dylib; make audit reachability-aware
jahnvi480 Aug 18, 2026
4722248
FIX: make conda-declared openssl/krb5 reachable from the ODBC driver …
jahnvi480 Aug 18, 2026
7d2fc1e
FEAT: add a live Encrypt=yes TLS gate that proves the OpenSSL backend…
jahnvi480 Aug 18, 2026
9a2f4c3
FIX: bundle Linux libltdl.so.7 + dual-RUNPATH driver binaries (glibc …
jahnvi480 Aug 18, 2026
e136c1e
FIX: conda openssl Linux-only + pinned <4; surface dlopen error text …
jahnvi480 Aug 19, 2026
50d02fa
FIX: splat DriverCondaDir as hashtable in conda-build step (fixes CON…
jahnvi480 Aug 19, 2026
79eec5c
FIX: skip conda-only unit tests when conda/ sources absent (installed…
jahnvi480 Aug 19, 2026
abd0f66
Declare libtool (libltdl) for conda instead of vendoring it on Linux
jahnvi480 Aug 19, 2026
a0923d1
Merge branch 'main' into jahnvi/conda-onboarding
jahnvi480 Aug 19, 2026
6435a8a
Revert "Declare libtool (libltdl) for conda instead of vendoring it o…
jahnvi480 Aug 19, 2026
9372689
FEAT: make the mssql-python conda package self-contained (vendor the …
jahnvi480 Aug 19, 2026
5386d9b
CHORE: scope PR #720 to conda packaging (drop ODBC driver self-contai…
jahnvi480 Aug 19, 2026
414905f
FEAT: build only the self-contained mssql-python conda package (retir…
jahnvi480 Aug 19, 2026
30bcf81
FEAT: rewire conda release gate for the single self-contained package
jahnvi480 Aug 19, 2026
3e612a2
FEAT: finish single-package conda pipeline wiring (publish/consolidat…
jahnvi480 Aug 19, 2026
cb9bfd3
DOC: drop stale #706/companion references from official-release-pipel…
jahnvi480 Aug 19, 2026
a418428
DOC: drop remaining stale conda #706/companion comments (single self-…
jahnvi480 Aug 19, 2026
e8c6e10
FEAT: add standalone conda-build + conda-release pipelines
jahnvi480 Aug 19, 2026
350e1e0
REFACTOR: remove conda from the PyPI build/release pipelines (conda i…
jahnvi480 Aug 19, 2026
63d90f6
Merge branch 'main' into jahnvi/conda-onboarding
jahnvi480 Aug 19, 2026
61fd60c
REFACTOR: remove conda from the wheel build stage templates (+ odbc-a…
jahnvi480 Aug 19, 2026
12c4d63
REFACTOR: keep wheel-build stage templates + release pipelines pristine
jahnvi480 Aug 19, 2026
c4c7fee
FIX: make the conda package actually fix #563 (RPATH reachability) + …
jahnvi480 Aug 19, 2026
6cf5540
FIX: address conda PR review comments
jahnvi480 Aug 19, 2026
837ac60
FIX: harden the conda #563 fix -- exact RUNPATH audit, assertion-only…
jahnvi480 Aug 19, 2026
43958df
FIX: install pytest in the conda-audit PR workflow
jahnvi480 Aug 19, 2026
6491112
FIX: unblock the conda-audit PR gate + tighten the audit (round-3 rev…
jahnvi480 Aug 20, 2026
433c643
FIX: run conda-audit unit tests with --noconftest
jahnvi480 Aug 20, 2026
9e71d51
FIX: build conda in a dedicated env (GitHub runner base pins python 3…
jahnvi480 Aug 20, 2026
de3b21a
FIX: exempt musl/alpine ODBC variants from the glibc DT_NEEDED audit
jahnvi480 Aug 20, 2026
5169149
FIX: unblock OneBranch conda legs (macOS index, win import shadow, Li…
jahnvi480 Aug 20, 2026
1353360
FIX: create empty noarch/repodata.json so the local conda channel is …
jahnvi480 Aug 20, 2026
7906e59
FIX: verify conda against a token-free channel dir (posix legs)
jahnvi480 Aug 20, 2026
f5a44c2
FIX: reachability gate inspects the host's driver variant, not a blin…
jahnvi480 Aug 21, 2026
517db0b
Merge branch 'main' into jahnvi/conda-onboarding
jahnvi480 Aug 21, 2026
26aad64
FIX: harden the conda TLS probe connection-string handling
jahnvi480 Aug 21, 2026
7920ded
FIX: skip conda TLS gate when CONDA_TLS_PROBE_CONN is not a connectio…
jahnvi480 Aug 21, 2026
82f6cfb
CHORE: reword TLS probe connection-string examples for the ADO credsc…
jahnvi480 Aug 21, 2026
faf17dd
FIX: aarch64 emulated-cross probes best-effort; clear Guardian credsc…
jahnvi480 Aug 21, 2026
caca5b7
CHORE: reference the ODBC EULAs from their canonical location, drop r…
jahnvi480 Aug 21, 2026
2915452
FEAT: add win-arm64 conda cross-build leg (Python 3.12-3.14)
jahnvi480 Aug 25, 2026
3c41ae4
FIX: conda verify loop aborted on native conda stderr under ErrorActi…
jahnvi480 Aug 25, 2026
8cacb7c
FIX: reset conda build script exit code so the win-arm64 best-effort …
jahnvi480 Aug 25, 2026
e5de9f6
FEAT: add dummy/test conda release pipeline (validate + dry-run publi…
jahnvi480 Aug 26, 2026
d08c89a
Remove conda-release provenance commit-match gate
jahnvi480 Aug 26, 2026
7835fb0
Allow reduced win-arm64 Python matrix in conda release gate
jahnvi480 Aug 26, 2026
3c365e8
Fold conda dummy dry-run into release pipeline (publishToConda=false …
jahnvi480 Aug 27, 2026
6f5927a
Select OneBranch template by publishToConda: NonOfficial dry-run, Off…
jahnvi480 Aug 27, 2026
5063a13
Harden conda win-arm64 build and release gates (blocking solve, PE-ar…
jahnvi480 Aug 27, 2026
5be4239
Enforce win-arm64 in v1 (required subdir + blocking build) and add TL…
jahnvi480 Aug 27, 2026
0fade8c
Always verify Miniforge installer SHA256 (pin 26.3.2-3 + baked-in che…
jahnvi480 Aug 27, 2026
0cf3d53
Fix TLS probe 18456/required truthiness bugs, contain win-arm64 blast…
jahnvi480 Aug 27, 2026
635720a
Merge branch 'main' into jahnvi/conda-onboarding
jahnvi480 Aug 27, 2026
42eb644
Verify Miniforge against its published .sha256 sidecar; drop baked ha…
jahnvi480 Aug 27, 2026
4b78206
Add release-time conda re-solve helper (drift gate) + tests
jahnvi480 Aug 27, 2026
c65570c
Defer bulk-copy on win-arm64: strip x64 mssql_py_core from the packag…
jahnvi480 Aug 27, 2026
459b9aa
Merge branch 'main' into jahnvi/conda-onboarding
jahnvi480 Aug 31, 2026
301513f
FIX: osx-arm64 wrong-Python binding + sync recipe with PR #734 review…
jahnvi480 Aug 31, 2026
8097860
FIX: revert host/run python to bare python (>=3.10 range broke conda-…
jahnvi480 Aug 31, 2026
0a583a1
FEAT: macOS OpenSSL reachability -- declare openssl [osx] + activate.…
jahnvi480 Sep 1, 2026
85a78e7
REVERT macOS DYLD_FALLBACK hook + openssl [osx] (0a583a1f): Gaurav pr…
jahnvi480 Sep 2, 2026
3dc063d
DOC: macOS Encrypt=yes needs system OpenSSL (brew/port); conda-env co…
jahnvi480 Sep 2, 2026
d4a50e4
FIX: select ODBC wheel arch-specifically (py3-none-<arch>) so a win-a…
jahnvi480 Sep 2, 2026
4718fa6
Merge branch 'main' into jahnvi/conda-onboarding
jahnvi480 Sep 2, 2026
043771e
FIX: derive conda win ODBC/wheel arch from target_platform, not Pytho…
jahnvi480 Sep 2, 2026
5915761
Merge origin/main into jahnvi/conda-onboarding (PR #737: correct-arch…
jahnvi480 Sep 2, 2026
0e6a8bf
FEAT: keep the arm64 mssql_py_core in win-arm64 conda packages (enabl…
jahnvi480 Sep 2, 2026
cbea6d1
FIX: conda publish-step requiredSubdirs must include win-arm64; guard…
jahnvi480 Sep 3, 2026
d6d1d69
FIX: PR #744 review — renumber dup test_026, reconcile consolidate co…
jahnvi480 Sep 3, 2026
0a6331e
FIX: PR #744 review — reconcile consolidate count (25->28 win-arm64),…
jahnvi480 Sep 3, 2026
4a57f19
FEAT: PR #744 review — add ELF e_machine arch gate to the Linux binar…
jahnvi480 Sep 3, 2026
25a1153
DOC: PR #744 review — correct false osx-arm64 'static arm64-slice aud…
jahnvi480 Sep 3, 2026
8c8375d
REFACTOR: PR #744 ponytail — drop YAGNI describe() marker tables + de…
jahnvi480 Sep 3, 2026
7eacaf9
REFACTOR: PR #744 ponytail — remove vestigial -Package/-DriverCondaDi…
jahnvi480 Sep 3, 2026
9f61db1
FIX: PR #744 review (Sumit) — PE presence gate, drop "missing compani…
jahnvi480 Sep 3, 2026
f470a3c
SECURITY: PR #744 review — source the TLS probe conn string from a SE…
jahnvi480 Sep 3, 2026
2ae2f49
FIX: PR #744 re-review — msodbcsql18 presence gate, proper openssl pa…
jahnvi480 Sep 3, 2026
56a54ad
FIX: build-conda-packages.ps1 — build in a dedicated conda_builder en…
jahnvi480 Sep 3, 2026
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
89 changes: 89 additions & 0 deletions .github/workflows/conda-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
# N3: PR-triggered conda build + masking-immune RUNPATH audit.
#
# The OneBranch conda-build pipeline is `trigger: none` / `pr: none`, so its blocking
# audit never runs on a PR. This lightweight GitHub Actions job builds ONE real
# linux-64 conda package from the SHIPPED PyPI wheels and runs
# eng/scripts/audit_bundled_binaries.py on it, so a regression in the $ORIGIN climb,
# the declared conda deps (krb5/libtool/openssl), or the expected DT_NEEDED set fails
# the PR automatically -- the full-agent runtime masking cannot hide it.
#
# build.sh ALWAYS stamps the relative $ORIGIN climb onto the vendored Linux ODBC .so
# (they are not code-signed, so the patch breaks no signature; an already-baked climb
# is a byte-for-byte no-op). This gate builds one real linux-64 conda package from the
# shipped PyPI wheels and audits the resulting climb (see conda/mssql-python/build.sh).
name: conda-audit

on:
pull_request:
paths:
- 'conda/**'
- 'eng/scripts/audit_bundled_binaries.py'
- 'eng/scripts/assert_pe_machine.py'
- 'eng/scripts/conda_resolve_check.py'
- 'OneBranchPipelines/scripts/build-conda-packages.sh'
- 'tests/test_027_conda_release_metadata.py'
- 'tests/test_029_bundled_binary_audit.py'
- 'tests/test_030_pe_machine_assert.py'
- 'tests/test_031_tls_probe_required.py'
- 'tests/test_032_conda_resolve_check.py'
- '.github/workflows/conda-audit.yml'

permissions:
contents: read

jobs:
linux-conda-audit:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Unit-test the audit + release validator
run: |
python -m pip install --quiet pytest zstandard
# --noconftest: tests/conftest.py imports mssql_python (the native ddbc_bindings
# extension), which is NOT built in this repackage-only gate. test_027/test_029
# are pure conda validator/audit tests using only built-in fixtures, so skip
# conftest to avoid that unrelated import.
python -m pytest --noconftest \
tests/test_029_bundled_binary_audit.py \
tests/test_030_pe_machine_assert.py \
tests/test_031_tls_probe_required.py \
tests/test_032_conda_resolve_check.py \
tests/test_027_conda_release_metadata.py -q

- name: Fetch the shipped linux wheels from PyPI
run: |
set -euo pipefail
mkdir -p wheels
# --no-deps: pull ONLY the two wheels we repackage (not azure-identity etc).
python -m pip download --no-deps mssql-python mssql-python-odbc -d wheels
echo "Downloaded:"; ls -1 wheels

- name: Build + audit a linux-64 conda package
run: |
set -euo pipefail
mssql_whl="$(ls wheels/mssql_python-*.whl | grep -v mssql_python_odbc | head -1)"
odbc_whl="$(ls wheels/mssql_python_odbc-*.whl | head -1)"
MSSQL_VER="$(basename "$mssql_whl" | sed -nE 's/^mssql_python-([^-]+)-.*/\1/p')"
ODBC_VER="$(basename "$odbc_whl" | sed -nE 's/^mssql_python_odbc-([^-]+)-.*/\1/p')"
echo "mssql-python=$MSSQL_VER mssql-python-odbc=$ODBC_VER"
bash OneBranchPipelines/scripts/build-conda-packages.sh \
"$PWD/wheels" \
"$PWD/conda" \
"$RUNNER_TEMP/conda-bld" \
"$MSSQL_VER" \
"$ODBC_VER" \
"3.11" \
"linux-64"

- name: Explicit standalone audit of the built package
run: |
set -euo pipefail
python -m pip install --quiet zstandard
python eng/scripts/audit_bundled_binaries.py --root "$RUNNER_TEMP/conda-bld/bld"
350 changes: 350 additions & 0 deletions OneBranchPipelines/conda-build-pipeline.yml

Large diffs are not rendered by default.

224 changes: 224 additions & 0 deletions OneBranchPipelines/conda-release-pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
# =========================================================================================
# OneBranch STANDALONE Conda Release Pipeline (mssql-python)
# =========================================================================================
# Decoupled from the wheel/PyPI release. Downloads the consolidated conda packages produced
# by the STANDALONE conda-build pipeline (conda-build-pipeline.yml, artifact
# drop_ConsolidateConda_ConsolidateArtifacts) -- NOT the wheel pipeline (def 2199), which no
# longer produces any conda artifact -- enforces the release-readiness gate (conda-release-
# step: required subdirs + full Python matrix + one version), and -- when publishToConda=true -- publishes the SELF-CONTAINED
# mssql-python conda package to Anaconda.org via anaconda-client (conda-publish-step; ESRP
# has no Conda ContentType). There is a single self-contained package (it vendors the ODBC
# Driver 18 payload); no companion. When publishToConda=false (the default), the same gate
# runs and a DRY-RUN step prints the exact `anaconda upload` plan WITHOUT uploading -- so a
# validate-only run of THIS pipeline replaces the old separate dummy pipeline.
#
# TEMPLATE by mode: publishToConda=false (dry run / dummy) extends the NonOfficial template
# (no Production Service-Tree classification required, so a validate-only run passes the
# inventory-compliance gate); publishToConda=true (real release) extends the Official template
# (deliberate, gated production publish -- the definition must be classified Production to
# actually upload). Manual trigger only. The OneBranch YAML needs an actual ADO run to fully validate.
# =========================================================================================
name: $(Year:YY)$(DayOfYear)$(Rev:.r)-CondaRelease

trigger: none
pr: none

parameters:
- name: publishToConda
displayName: 'Publish Conda Packages to Anaconda.org (PRODUCTION)'
type: boolean
default: false # Safety: default to a validate-only dry run.
- name: condaChannel
displayName: 'Anaconda.org channel/org to publish to'
type: string
default: 'microsoft'
- name: condaLabel
displayName: 'Anaconda.org channel label'
type: string
default: 'main'
# Infra setup: ADO definition id of the STANDALONE conda-build pipeline
# (conda-build-pipeline.yml), whose ConsolidateConda stage produces
# drop_ConsolidateConda_ConsolidateArtifacts. This is NOT the wheel pipeline
# (def 2199). Set it once the conda-build pipeline is registered in ADO; 0 is a
# placeholder that must be overridden before a real run.
- name: condaBuildDefinitionId
displayName: 'Conda-build pipeline ADO definition id'
type: number
default: 0
# The exact mssql-python version being released. When set, the readiness gate
# asserts EVERY conda package matches it (not just internal one-version
# consistency). Leave empty only for a consistency-only dry run.
- name: mssqlPythonVersion
displayName: 'Expected mssql-python release version (e.g. 1.13.0)'
type: string
default: ''

variables:
- template: /OneBranchPipelines/variables/common-variables.yml@self
- template: /OneBranchPipelines/variables/onebranch-variables.yml@self
# ANACONDA_API_TOKEN lives in this org-scoped group; included ONLY when publishing so a
# validate-only run never requires the group to exist.
- ${{ if eq(parameters.publishToConda, true) }}:
- group: 'Anaconda Publishing'

resources:
repositories:
- repository: templates
type: git
name: 'OneBranch.Pipelines/GovernedTemplates'
ref: 'refs/heads/main'
# The build pipeline whose consolidated conda artifact this pipeline validates + publishes.
pipelines:
- pipeline: buildPipeline
# Infra setup: the STANDALONE conda-build pipeline (backed by
# conda-build-pipeline.yml), whose ConsolidateConda stage publishes
# drop_ConsolidateConda_ConsolidateArtifacts. Update to its exact ADO
# definition name once registered. NOT the wheel pipeline
# (Build-Release-Package-Pipeline / def 2199), which no longer builds conda.
source: 'Conda-Build-Pipeline'
trigger: none

extends:
# NonOfficial for a validate-only dry run (publishToConda=false): no Production Service-Tree
# classification is required, so the inventory-compliance gate passes. Official for a real
# publish (publishToConda=true): the governed production path.
${{ if eq(parameters.publishToConda, true) }}:
template: 'v2/OneBranch.Official.CrossPlat.yml@templates'
${{ else }}:
template: 'v2/OneBranch.NonOfficial.CrossPlat.yml@templates'
parameters:
featureFlags:
WindowsHostVersion:
Version: '2022'
globalSdl:
baseline:
baselineFile: $(Build.SourcesDirectory)/.gdn/.gdnbaselines
suppressionSet: default
suppression:
suppressionFile: $(Build.SourcesDirectory)/.gdn/.gdnsuppress
suppressionSet: default
credscan:
enabled: true
policheck:
enabled: true
break: true
exclusionFile: '$(REPO_ROOT)/.config/PolicheckExclusions.xml'
publishLogs:
enabled: true
# Official-only heavy gates (binskim break + TSA). The NonOfficial dry run skips them,
# matching the old dummy pipeline's minimal SDL.
${{ if eq(parameters.publishToConda, true) }}:
binskim:
enabled: true
break: true
tsa:
enabled: true
configFile: '$(REPO_ROOT)/.config/tsaoptions.json'

stages:
- stage: CondaRelease
displayName: 'Validate & Publish Conda Release'
jobs:
# Gate: prove the consolidated conda set is complete (required subdirs +
# full Python matrix + one version) before anything is published.
- job: ValidateConda
displayName: 'Validate consolidated conda packages'
pool:
type: windows
isCustom: true
name: Python-1ES-pool
demands:
- imageOverride -equals PYTHON-1ES-MMS2022
variables:
ob_outputDirectory: '$(Build.ArtifactStagingDirectory)'
steps:
# Publishing must PIN the exact version. With the provenance gate removed, an
# unpinned publish (empty version = "accept any single consistent version") could
# ship a stale/unintended artifact. Require a non-empty version when publishing.
- ${{ if eq(parameters.publishToConda, true) }}:
- task: PowerShell@2
displayName: 'Guard: expected mssql-python version is required to publish'
inputs:
targetType: 'inline'
script: |
if ([string]::IsNullOrWhiteSpace('${{ parameters.mssqlPythonVersion }}')) {
Write-Error "publishToConda=true but mssqlPythonVersion is empty. A production publish must pin the exact version (the release-readiness gate then asserts EVERY package matches it). Re-run with mssqlPythonVersion set."
exit 1
}
Write-Host "Publish version pin: ${{ parameters.mssqlPythonVersion }}"
- template: /OneBranchPipelines/steps/conda-release-step.yml@self
parameters:
buildDefinitionId: ${{ parameters.condaBuildDefinitionId }}
mssqlPythonVersion: '${{ parameters.mssqlPythonVersion }}'

# Dry run (publishToConda=false): enumerate every package and print the exact
# `anaconda upload` plan WITHOUT uploading, so a validate-only run shows precisely
# what a real publish WOULD do. Reuses the conda tree the gate already downloaded
# into $(Build.SourcesDirectory)/conda-artifacts. This replaces the old dummy pipeline.
- ${{ if eq(parameters.publishToConda, false) }}:
- task: PowerShell@2
displayName: 'Dry-run publish plan (validate-only): enumerate packages + print the anaconda upload plan (NO upload)'
inputs:
targetType: 'inline'
script: |
$ErrorActionPreference = 'Stop'

$root = "$(Build.SourcesDirectory)/conda-artifacts/conda"
if (-not (Test-Path $root)) {
Write-Error "Consolidated conda tree not found at $root. Did the readiness gate download it?"
exit 1
}

$pkgs = @(Get-ChildItem -Path $root -Recurse -Include *.conda, *.tar.bz2)
if ($pkgs.Count -eq 0) { Write-Error "No conda packages found under $root."; exit 1 }

# mssql-python bindings only (the self-contained model ships no companion).
function Get-Binding($items) { @($items | Where-Object { $_.Name -like 'mssql-python-*' -and $_.Name -notlike 'mssql-python-odbc-*' }) }
$bySubdir = $pkgs | Group-Object { $_.Directory.Name } | Sort-Object Name

Write-Host "====================================="
Write-Host "[DRY-RUN CONDA RELEASE] discovered $($pkgs.Count) package(s) across $($bySubdir.Count) subdir(s):"
foreach ($g in $bySubdir) {
Write-Host (" {0,-14} {1} mssql-python package(s)" -f $g.Name, (Get-Binding $g.Group).Count)
}

# A self-contained release ships ONLY mssql-python; flag (don't fail) a stray companion.
$stray = @($pkgs | Where-Object { $_.Name -like 'mssql-python-odbc-*' })
if ($stray.Count -gt 0) {
Write-Host "##vso[task.logissue type=warning]$($stray.Count) stray mssql-python-odbc package(s) present; the self-contained model ships only mssql-python."
}

Write-Host "`nanaconda upload PLAN (DRY-RUN - NOT executed):"
Write-Host " target channel/org : ${{ parameters.condaChannel }}"
Write-Host " target label : ${{ parameters.condaLabel }}"
foreach ($p in ($pkgs | Sort-Object FullName)) {
$subdir = Split-Path -Leaf (Split-Path -Parent $p.FullName)
Write-Host " WOULD RUN: anaconda upload --user ${{ parameters.condaChannel }} --label ${{ parameters.condaLabel }} --skip-existing $subdir/$($p.Name)"
}

Write-Host "`n====================================="
Write-Host "DRY-RUN COMPLETE: no 'anaconda upload' was executed (publishToConda=false)."
Write-Host "For a real (gated, staged-then-promoted) publish, re-run with publishToConda=true."
Write-Host "====================================="

# PRODUCTION publish (releaseJob) -- runs ONLY when publishToConda=true and
# ONLY after the ValidateConda gate succeeds, so an incomplete set is never
# uploaded. anaconda-client reads ANACONDA_API_TOKEN from the env (never the
# command line), so the token never appears in the logs.
- ${{ if eq(parameters.publishToConda, true) }}:
- job: PublishConda
displayName: 'Publish conda packages to Anaconda.org'
dependsOn: ValidateConda
templateContext:
type: releaseJob
isProduction: true
pool:
type: windows
variables:
ob_outputDirectory: '$(Build.ArtifactStagingDirectory)'
steps:
- template: /OneBranchPipelines/steps/conda-publish-step.yml@self
parameters:
buildDefinitionId: ${{ parameters.condaBuildDefinitionId }}
condaChannel: '${{ parameters.condaChannel }}'
condaLabel: '${{ parameters.condaLabel }}'
Loading
Loading