Skip to content

Commit 336198a

Browse files
committed
✨ add continuous testing workflow for running against the latest Qiskit main branch
Signed-off-by: burgholzer <burgholzer@me.com>
1 parent ae6f34f commit 336198a

File tree

2 files changed

+137
-6
lines changed

2 files changed

+137
-6
lines changed

.github/workflows/upstream.yml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: Qiskit Upstream Tests
2+
on:
3+
schedule:
4+
# Run every Monday at 00:00 UTC
5+
- cron: "0 0 * * 1"
6+
pull_request:
7+
paths:
8+
- ".github/workflows/upstream.yml"
9+
workflow_dispatch: # Allow manual triggering
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
13+
cancel-in-progress: true
14+
15+
permissions:
16+
contents: read
17+
issues: write # Needed to create/update issues
18+
19+
jobs:
20+
qiskit-upstream-tests:
21+
name: 🐍⚛️
22+
strategy:
23+
fail-fast: false
24+
matrix:
25+
os: [ubuntu-24.04, macos-15, windows-2025]
26+
uses: cda-tum/mqt-workflows/.github/workflows/reusable-qiskit-upstream.yml@v1.7
27+
with:
28+
runs-on: ${{ matrix.os }}
29+
setup-z3: true
30+
31+
create-issue-on-failure:
32+
name: Create issue on failure
33+
if: ${{ always() }}
34+
needs: qiskit-upstream-tests
35+
runs-on: ubuntu-latest
36+
steps:
37+
- name: Get latest Qiskit commit
38+
id: qiskit-commit
39+
run: |
40+
QISKIT_COMMIT=$(curl -s https://api.github.com/repos/Qiskit/qiskit/commits/main | jq -r '.sha')
41+
QISKIT_COMMIT_URL="https://github.com/Qiskit/qiskit/commit/${QISKIT_COMMIT}"
42+
QISKIT_COMMIT_DATE=$(curl -s https://api.github.com/repos/Qiskit/qiskit/commits/${QISKIT_COMMIT} | jq -r '.commit.author.date')
43+
echo "url=${QISKIT_COMMIT_URL}" >> $GITHUB_OUTPUT
44+
echo "date=${QISKIT_COMMIT_DATE}" >> $GITHUB_OUTPUT
45+
46+
- name: Create or update issue
47+
if: ${{ needs.qiskit-upstream-tests.result != 'success' }}
48+
uses: actions/github-script@v6
49+
with:
50+
github-token: ${{ github.token }}
51+
script: |
52+
const runId = context.runId;
53+
const workflowRunUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
54+
const testResult = '${{ needs.qiskit-upstream-tests.result }}';
55+
const qiskitCommitUrl = '${{ steps.qiskit-commit.outputs.url }}';
56+
const qiskitCommitDate = '${{ steps.qiskit-commit.outputs.date }}';
57+
58+
// Search for existing open issues with a specific title pattern
59+
const issueTitle = "❌ Qiskit Upstream Tests Failure";
60+
61+
const issues = await github.rest.issues.listForRepo({
62+
owner: context.repo.owner,
63+
repo: context.repo.repo,
64+
state: 'open',
65+
});
66+
67+
// Find matching issues
68+
const matchingIssue = issues.data.find(issue => issue.title === issueTitle);
69+
70+
const today = new Date().toISOString().split('T')[0];
71+
const body = `## Qiskit Upstream Tests Failed on ${today}
72+
73+
The weekly Qiskit upstream test has failed.
74+
75+
### Workflow Details
76+
77+
- **Workflow Run**: [View Logs and Details](${workflowRunUrl})
78+
- **Result**: \`${testResult}\`
79+
- **Triggered by**: ${context.eventName}
80+
- **Qiskit Commit Tested**: ${qiskitCommitUrl} (${qiskitCommitDate})
81+
82+
Please investigate and fix this issue to ensure compatibility with the latest version of Qiskit.
83+
84+
> This issue was automatically generated by a GitHub Action.
85+
`;
86+
87+
// If we found an existing issue, update it, otherwise create a new one
88+
if (matchingIssue) {
89+
// Add a comment with the new failure
90+
await github.rest.issues.createComment({
91+
owner: context.repo.owner,
92+
repo: context.repo.repo,
93+
issue_number: matchingIssue.number,
94+
body: `New failure detected on ${today}.
95+
- [View workflow run](${workflowRunUrl})
96+
- **Qiskit Commit Tested**: ${qiskitCommitUrl} (${qiskitCommitDate})`
97+
});
98+
99+
console.log(`Updated existing issue #${matchingIssue.number}`);
100+
} else {
101+
// Create a new issue
102+
const newIssue = await github.rest.issues.create({
103+
owner: context.repo.owner,
104+
repo: context.repo.repo,
105+
title: issueTitle,
106+
body: body,
107+
labels: ['bug', 'python', 'dependencies']
108+
});
109+
110+
console.log(`Created new issue #${newIssue.data.number}`);
111+
}

noxfile.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ def _run_tests(
3737
session: nox.Session,
3838
*,
3939
install_args: Sequence[str] = (),
40-
run_args: Sequence[str] = (),
40+
extra_command: Sequence[str] = (),
41+
pytest_run_args: Sequence[str] = (),
4142
) -> None:
4243
env = {"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}
4344
if os.environ.get("CI", None) and sys.platform == "win32":
@@ -57,7 +58,6 @@ def _run_tests(
5758
"build",
5859
"--only-group",
5960
"test",
60-
"--verbose",
6161
# Build mqt-core from source to work around pybind believing that two
6262
# compiled extensions might not be binary compatible.
6363
# This will be fixed in a new pybind11 release that includes https://github.com/pybind/pybind11/pull/5439.
@@ -73,14 +73,23 @@ def _run_tests(
7373
)
7474
session.run(
7575
"uv",
76-
"run",
76+
"sync",
77+
"--inexact",
7778
"--no-dev", # do not auto-install dev dependencies
7879
"--no-build-isolation-package",
7980
"mqt-qmap", # build the project without isolation
80-
"--verbose",
81+
*install_args,
82+
env=env,
83+
)
84+
if extra_command:
85+
session.run(*extra_command, env=env)
86+
session.run(
87+
"uv",
88+
"run",
89+
"--no-sync", # do not sync as everything is already installed
8190
*install_args,
8291
"pytest",
83-
*run_args,
92+
*pytest_run_args,
8493
*session.posargs,
8594
"--cov-config=pyproject.toml",
8695
env=env,
@@ -99,13 +108,24 @@ def minimums(session: nox.Session) -> None:
99108
_run_tests(
100109
session,
101110
install_args=["--resolution=lowest-direct"],
102-
run_args=["-Wdefault"],
111+
pytest_run_args=["-Wdefault"],
103112
)
104113
env = {"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}
105114
session.run("uv", "tree", "--frozen", env=env)
106115
session.run("uv", "lock", "--refresh", env=env)
107116

108117

118+
@nox.session(reuse_venv=True, venv_backend="uv", python=PYTHON_ALL_VERSIONS)
119+
def qiskit(session: nox.Session) -> None:
120+
"""Tests against the latest version of Qiskit."""
121+
_run_tests(
122+
session,
123+
extra_command=["uv", "pip", "install", "qiskit[qasm3-import] @ git+https://github.com/Qiskit/qiskit.git"],
124+
)
125+
env = {"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}
126+
session.run("uv", "pip", "show", "qiskit", env=env)
127+
128+
109129
@nox.session(reuse_venv=True)
110130
def docs(session: nox.Session) -> None:
111131
"""Build the docs. Use "--non-interactive" to avoid serving. Pass "-b linkcheck" to check links."""

0 commit comments

Comments
 (0)