Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1b7e4c4
Initial plan
Copilot May 4, 2026
aa78ed0
Enable slow tests in ADO nightly pipeline and add on-demand trigger v…
Copilot May 4, 2026
bb312a0
Address review feedback: use boolean types and allow flexible trigger…
Copilot May 4, 2026
02a99ab
Fix pre-commit: remove unnecessary quotes in YAML description field
Copilot May 4, 2026
e9f4b11
Change on-demand trigger commands from @copilot to /qdk prefix
Copilot May 4, 2026
a3807d9
Change on-demand trigger command from /qdk to /qdkbot
Copilot May 12, 2026
d893557
Merge branch 'main' into copilot/configure-cicd-slow-tests
lorisercole May 20, 2026
b5d4b32
Gate on-demand workflow to non-fork PRs, dispatch before ack, add tem…
Copilot May 21, 2026
e48afd2
temporarily comment if condition to test the workflow.
lorisercole May 21, 2026
d4fdda7
Add failure-notification comment when dispatch fails
Copilot May 21, 2026
1ee7588
rename wf to qdk-bot
lorisercole May 21, 2026
554d9cf
Add author_association authorization check for /qdkbot commands
Copilot May 21, 2026
6b5ffd2
Get rid of qdk-bot. We can trigger tests manually
lorisercole May 21, 2026
4466250
examples+tests: guard against qiskit dependency
lorisercole May 22, 2026
a50bd10
Merge branch 'main' into copilot/configure-cicd-slow-tests
lorisercole May 27, 2026
195bddf
add grouping in demo and fix identity check in energy estimator
RushiGong May 27, 2026
8d1da98
fix qiskit dependent test
RushiGong May 27, 2026
4165599
apply AI code review comment on test
RushiGong May 27, 2026
99b93bd
Merge branch 'main' into copilot/configure-cicd-slow-tests
lorisercole May 28, 2026
fa8aa08
Expose ADO slow-test parameter
Copilot May 28, 2026
5c15fb2
Implement retry logic for conda bootstrap and add retry count for mac…
lorisercole May 29, 2026
eb197b6
Merge branch 'main' into copilot/configure-cicd-slow-tests
lorisercole Jun 1, 2026
5839475
Merge branch 'main' into copilot/configure-cicd-slow-tests
lorisercole Jun 2, 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
8 changes: 7 additions & 1 deletion .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ on:
- '**'
merge_group:
workflow_dispatch:
inputs:
run_slow_tests:
description: Run slow tests
required: false
default: false
type: boolean

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -344,7 +350,7 @@ jobs:
- name: Run Python tests
env:
OMP_NUM_THREADS: ${{ matrix.python-test-threads }}
QDK_CHEMISTRY_RUN_SLOW_TESTS: 0
QDK_CHEMISTRY_RUN_SLOW_TESTS: ${{ inputs.run_slow_tests && '1' || '0' }}
Comment thread
lorisercole marked this conversation as resolved.
working-directory: python
run: |
set -e
Expand Down
163 changes: 93 additions & 70 deletions .pipelines/pip-scripts/bootstrap-conda.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,75 +62,98 @@ case "$(uname -s):$(uname -m)" in
;;
esac

echo "Installing ${ENSURECONDA_PKG} (on $(uname -s):$(uname -m)) and bootstrapping conda..."
# Use a throwaway venv so we don't fight PEP 668 (Homebrew Python on macOS
# and apt Python on Ubuntu 24.04 are both externally managed).
# Clean any stale venv first (idempotent on self-hosted agents / retries).
rm -rf /tmp/bootstrap-venv
python3 -m venv /tmp/bootstrap-venv
# shellcheck disable=SC1091
. /tmp/bootstrap-venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install "${ENSURECONDA_PKG}"
# All network-sensitive operations (pip install, conda download, env creation)
# are wrapped in a single retryable function to handle transient failures.
_BOOTSTRAP_MAX_ATTEMPTS=3
_BOOTSTRAP_RETRY_DELAY=30

if [ "$USE_MS_ENSURECONDA" = "1" ]; then
# ms-ensureconda's --envfile flag dumps CONDA_BASH_HOOK + friends to a
# dotenv file we then source to wire up conda for this shell.
python3 -m ensureconda --envfile /tmp/ensureconda.env
deactivate
set -a; . /tmp/ensureconda.env; set +a
# shellcheck disable=SC1090
. "$CONDA_BASH_HOOK"
else
# Public ensureconda has no --envfile (it's an ms-ensureconda extension);
# it just prints the discovered / installed conda binary path on stdout.
# Force it to install conda-standalone (default would be micromamba, which
# uses a different CLI: `micromamba shell hook --shell bash` instead of
# `conda shell.bash hook`, plus mamba-specific `create`/`activate`).
CONDA_EXE=$(python3 -m ensureconda --no-mamba --no-micromamba --conda --conda-exe)
deactivate
export CONDA_EXE
# shellcheck disable=SC1090
eval "$("$CONDA_EXE" shell.bash hook)"
fi
_bootstrap_conda() {
echo "Installing ${ENSURECONDA_PKG} (on $(uname -s):$(uname -m)) and bootstrapping conda..."
# Use a throwaway venv so we don't fight PEP 668 (Homebrew Python on macOS
# and apt Python on Ubuntu 24.04 are both externally managed).
# Clean any stale venv first (idempotent on self-hosted agents / retries).
rm -rf /tmp/bootstrap-venv
python3 -m venv /tmp/bootstrap-venv
# shellcheck disable=SC1091
. /tmp/bootstrap-venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install "${ENSURECONDA_PKG}"

echo "Creating conda environment '${CONDA_ENV_NAME}' with Python ${PYTHON_VERSION}..."
# Explicitly include `pip` — fresh conda envs created with conda-standalone do
# not include pip by default, which would break `python3 -m pip ...` below.
#
# On Linux x86_64 (ms-ensureconda path) we are running under 1ES network
# isolation (CFSClean): public conda channels (conda.anaconda.org,
# repo.anaconda.com) are blocked. Force conda to install everything from the
# Azure Artifacts feed's Conda channel (proxied through the
# azure-feed://mseng/Anaconda@Published upstream).
#
# The feed exposes its upstream conda channels as named subpaths under
# /Conda/repo/<channel>/ (the feed root /Conda/repo/ itself returns 404 — it
# is not a channel). We use `main` (the Anaconda defaults channel that hosts
# python+pip) and `conda-forge` as a fallback for any package that defaults
# wouldn't carry.
#
# Auth: the conda install shipped by ms-ensureconda has a pre-registered
# azure_artifacts_conda_auth plugin that injects auth on every Azure
# Artifacts HTTPS request by reading $ARTIFACTS_CONDA_TOKEN. We just need to
# set that env var (to the pipeline's System.AccessToken). The plugin then
# handles auth; the channel URL itself must NOT inline the token (the plugin
# crashes with UnboundLocalError if the var is missing, even when basic-auth
# creds are present in the URL).
#
# Remove any existing conda env with the same name first (idempotent on
# self-hosted agents and on retries).
conda env remove -y -n "${CONDA_ENV_NAME}" 2>/dev/null || true
if [ "$USE_MS_ENSURECONDA" = "1" ]; then
: "${SYSTEM_ACCESSTOKEN:?SYSTEM_ACCESSTOKEN must be set when bootstrapping conda from the Azure Artifacts feed}"
{ set +x; } 2>/dev/null
export ARTIFACTS_CONDA_TOKEN="${SYSTEM_ACCESSTOKEN}"
set -x
CONDA_FEED_ROOT="https://pkgs.dev.azure.com/ms-azurequantum/AzureQuantum/_packaging/quantum-apps-dependencies/Conda/repo"
conda create --override-channels \
--channel "${CONDA_FEED_ROOT}/main" \
--channel "${CONDA_FEED_ROOT}/conda-forge" \
--yes --quiet --name "${CONDA_ENV_NAME}" "python=${PYTHON_VERSION}" pip
else
conda create --yes --quiet --name "${CONDA_ENV_NAME}" "python=${PYTHON_VERSION}" pip
fi
if [ "$USE_MS_ENSURECONDA" = "1" ]; then
# ms-ensureconda's --envfile flag dumps CONDA_BASH_HOOK + friends to a
# dotenv file we then source to wire up conda for this shell.
python3 -m ensureconda --envfile /tmp/ensureconda.env
deactivate
set -a; . /tmp/ensureconda.env; set +a
# shellcheck disable=SC1090
. "$CONDA_BASH_HOOK"
else
# Public ensureconda has no --envfile (it's an ms-ensureconda extension);
# it just prints the discovered / installed conda binary path on stdout.
# Force it to install conda-standalone (default would be micromamba, which
# uses a different CLI: `micromamba shell hook --shell bash` instead of
# `conda shell.bash hook`, plus mamba-specific `create`/`activate`).
CONDA_EXE=$(python3 -m ensureconda --no-mamba --no-micromamba --conda --conda-exe)
deactivate
export CONDA_EXE
# shellcheck disable=SC1090
eval "$("$CONDA_EXE" shell.bash hook)"
fi

echo "Creating conda environment '${CONDA_ENV_NAME}' with Python ${PYTHON_VERSION}..."
# Explicitly include `pip` — fresh conda envs created with conda-standalone do
# not include pip by default, which would break `python3 -m pip ...` below.
#
# On Linux x86_64 (ms-ensureconda path) we are running under 1ES network
# isolation (CFSClean): public conda channels (conda.anaconda.org,
# repo.anaconda.com) are blocked. Force conda to install everything from the
# Azure Artifacts feed's Conda channel (proxied through the
# azure-feed://mseng/Anaconda@Published upstream).
#
# The feed exposes its upstream conda channels as named subpaths under
# /Conda/repo/<channel>/ (the feed root /Conda/repo/ itself returns 404 — it
# is not a channel). We use `main` (the Anaconda defaults channel that hosts
# python+pip) and `conda-forge` as a fallback for any package that defaults
# wouldn't carry.
#
# Auth: the conda install shipped by ms-ensureconda has a pre-registered
# azure_artifacts_conda_auth plugin that injects auth on every Azure
# Artifacts HTTPS request by reading $ARTIFACTS_CONDA_TOKEN. We just need to
# set that env var (to the pipeline's System.AccessToken). The plugin then
# handles auth; the channel URL itself must NOT inline the token (the plugin
# crashes with UnboundLocalError if the var is missing, even when basic-auth
# creds are present in the URL).
#
# Remove any existing conda env with the same name first (idempotent on
# self-hosted agents and on retries).
conda env remove -y -n "${CONDA_ENV_NAME}" 2>/dev/null || true
if [ "$USE_MS_ENSURECONDA" = "1" ]; then
: "${SYSTEM_ACCESSTOKEN:?SYSTEM_ACCESSTOKEN must be set when bootstrapping conda from the Azure Artifacts feed}"
{ set +x; } 2>/dev/null
export ARTIFACTS_CONDA_TOKEN="${SYSTEM_ACCESSTOKEN}"
set -x
CONDA_FEED_ROOT="https://pkgs.dev.azure.com/ms-azurequantum/AzureQuantum/_packaging/quantum-apps-dependencies/Conda/repo"
conda create --override-channels \
--channel "${CONDA_FEED_ROOT}/main" \
--channel "${CONDA_FEED_ROOT}/conda-forge" \
--yes --quiet --name "${CONDA_ENV_NAME}" "python=${PYTHON_VERSION}" pip
else
conda create --yes --quiet --name "${CONDA_ENV_NAME}" "python=${PYTHON_VERSION}" pip
fi
}

_bootstrap_attempt=1
while true; do
if _bootstrap_conda; then
break
fi
if [ "$_bootstrap_attempt" -ge "$_BOOTSTRAP_MAX_ATTEMPTS" ]; then
echo "ERROR: bootstrap-conda.sh failed after ${_BOOTSTRAP_MAX_ATTEMPTS} attempts." >&2
return 1 2>/dev/null || exit 1
fi
echo "WARNING: bootstrap attempt ${_bootstrap_attempt}/${_BOOTSTRAP_MAX_ATTEMPTS} failed; retrying in ${_BOOTSTRAP_RETRY_DELAY}s..." >&2
sleep "$_BOOTSTRAP_RETRY_DELAY"
_bootstrap_attempt=$((_bootstrap_attempt + 1))
done
unset _bootstrap_attempt _BOOTSTRAP_MAX_ATTEMPTS _BOOTSTRAP_RETRY_DELAY
unset -f _bootstrap_conda
7 changes: 7 additions & 0 deletions .pipelines/python-wheels.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ parameters:
type: string
default: None
displayName: PyPI Development Tag (e.g. 'dev1', 'rc1', etc.)
- name: runSlowTests
type: boolean
default: true
displayName: Run slow tests

variables:
- group: QdkChemistry
Expand Down Expand Up @@ -169,6 +173,7 @@ extends:
dockerImage: mcr.microsoft.com/mirror/docker/library/ubuntu:24.04
imageTag: linux/amd64
pythonVersion: $(pythonVersion)
runSlowTests: ${{ parameters.runSlowTests }}

# Build - Linux ARM64
- ${{ if and(eq(target.arch, 'aarch64'), eq(target.os, 'linux')) }}:
Expand All @@ -191,6 +196,7 @@ extends:
dockerImage: mcr.microsoft.com/mirror/docker/library/ubuntu:24.04
imageTag: linux/arm64/v8
pythonVersion: $(pythonVersion)
runSlowTests: ${{ parameters.runSlowTests }}

# Build - macOS ARM64
- ${{ if eq(target.os, 'macOS') }}:
Expand All @@ -211,6 +217,7 @@ extends:
agentBuildDirectory: $(Agent.BuildDirectory)
pythonVersion: $(pythonVersion)
macBuild: ON
runSlowTests: ${{ parameters.runSlowTests }}

# SBoM Manifest Generator Task requires we transfer ownership of the wheel directory
# back to the original base image user
Expand Down
1 change: 1 addition & 0 deletions .pipelines/templates/build-pip-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,4 @@ steps:
${{ parameters.libflameVersion }} \
${{ parameters.macBuild }}
displayName: Build wheel (macOS native)
retryCountOnTaskFailure: 2
6 changes: 6 additions & 0 deletions .pipelines/templates/test-pip-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ parameters:
- name: macBuild
type: string
default: OFF
- name: runSlowTests
type: boolean
default: true

steps:
- ${{ if and(eq(parameters.macBuild, 'OFF'), eq(parameters.imageTag, 'linux/amd64')) }}:
Expand All @@ -24,6 +27,7 @@ steps:
-e PIP_INDEX_URL \
-e SYSTEM_ACCESSTOKEN \
-e QSHARP_PYTHON_TELEMETRY=false \
-e QDK_CHEMISTRY_RUN_SLOW_TESTS=${{ parameters.runSlowTests }} \
-v ${{ parameters.agentBuildDirectory }}:/workspace \
-w /workspace/qdk-chemistry/python \
${{ parameters.dockerImage }} \
Expand All @@ -40,6 +44,7 @@ steps:
--platform ${{ parameters.imageTag }} \
-e PIP_INDEX_URL \
-e QSHARP_PYTHON_TELEMETRY=false \
-e QDK_CHEMISTRY_RUN_SLOW_TESTS=${{ parameters.runSlowTests }} \
-v ${{ parameters.agentBuildDirectory }}:/workspace \
-w /workspace/qdk-chemistry/python \
${{ parameters.dockerImage }} \
Expand All @@ -51,6 +56,7 @@ steps:
- script: |
echo "Running wheel tests (native)..."
cd ${{ parameters.agentBuildDirectory }}/qdk-chemistry/python
export QDK_CHEMISTRY_RUN_SLOW_TESTS=${{ parameters.runSlowTests }}
bash ../.pipelines/pip-scripts/test-pip-wheels.sh ${{ parameters.pythonVersion }} \
${{ parameters.macBuild }}
displayName: Test wheel (native)
5 changes: 4 additions & 1 deletion docs/source/_static/examples/python/quickstart.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,12 @@
"circuit_executor",
AlgorithmRef("circuit_executor", "qdk_full_state_simulator"),
)
term_grouper = create("term_grouper", "qubit_wise_commuting")
grouped_hamiltonian = term_grouper.run(qubit_hamiltonian=qubit_hamiltonian)

energy_results, simulation_data = estimator.run(
circuit=sparse_isometry_circuit,
qubit_hamiltonian=qubit_hamiltonian,
qubit_hamiltonian=grouped_hamiltonian,
total_shots=500000,
)

Expand Down
6 changes: 3 additions & 3 deletions examples/qpe_stretched_n2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
"\n",
"This notebook provides an example of `qdk-chemistry` functionality through an end-to-end workflow estimating the ground state energy of a multi-configurational quantum chemistry system. This is one example of a wide range of functionality in `qdk-chemistry`. Please see <https://github.com/microsoft/qdk-chemistry> for the full documentation.\n",
"\n",
"In addition to [installing `qdk-chemistry`](https://github.com/microsoft/qdk-chemistry/blob/main/INSTALL.md), you will need to install the `jupyter` extra to run this notebook:\n",
"In addition to [installing `qdk-chemistry`](https://github.com/microsoft/qdk-chemistry/blob/main/INSTALL.md), you will need to install the `jupyter` and `qiskit-extras` extras to run this notebook:\n",
"\n",
"```bash\n",
"pip install 'qdk-chemistry[jupyter]'\n",
"pip install 'qdk-chemistry[jupyter,qiskit-extras]'\n",
"```\n",
"\n",
"This installs the additional dependencies required by this notebook (ipykernel, pandas, and pyscf)."
"This installs the additional dependencies required by this notebook (ipykernel, pandas, pyscf, qiskit)."
]
},
{
Expand Down
11 changes: 7 additions & 4 deletions examples/state_prep_energy.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
"This notebook demonstrates an end-to-end multi-configurational quantum chemistry workflow using `qdk-chemistry`.\n",
"It covers molecule loading and visualization, self-consistent-field (SCF) calculation, active-space selection, multi-configurational wavefunction generation, quantum state-preparation circuit construction, and measurement circuits for energy estimation.\n",
"\n",
"**Prerequisites:** In addition to [installing `qdk-chemistry`](https://github.com/microsoft/qdk-chemistry/blob/main/INSTALL.md), you will need to install the `jupyter` extra to run this notebook:\n",
"**Prerequisites:** In addition to [installing `qdk-chemistry`](https://github.com/microsoft/qdk-chemistry/blob/main/INSTALL.md), you will need to install the `jupyter` and `qiskit-extras` extras to run this notebook:\n",
"\n",
"```bash\n",
"pip install 'qdk-chemistry[jupyter]'\n",
"pip install 'qdk-chemistry[jupyter,qiskit-extras]'\n",
"```\n",
"\n",
"This installs the additional dependencies required by this notebook (ipykernel, pandas, and pyscf).\n",
"This installs the additional dependencies required by this notebook (ipykernel, pandas, pyscf, and qiskit).\n",
"\n",
"---\n",
"\n",
Expand Down Expand Up @@ -424,9 +424,12 @@
" algorithm_name=\"qdk\",\n",
" circuit_executor=AlgorithmRef(\"circuit_executor\", \"qdk_sparse_state_simulator\"),\n",
")\n",
"term_grouper = create(\"term_grouper\", \"qubit_wise_commuting\")\n",
"grouped_hamiltonian = term_grouper.run(qubit_hamiltonian=qubit_hamiltonian)\n",
"\n",
"energy_results, simulation_data = estimator.run(\n",
" circuit=sparse_isometry_circuit,\n",
" qubit_hamiltonian=qubit_hamiltonian,\n",
" qubit_hamiltonian=grouped_hamiltonian,\n",
" total_shots=600000,\n",
")\n",
"\n",
Expand Down
Loading
Loading