From e096c9b6fbd59d1015767e9d127021a9e3d0ada0 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <raynelfss@hotmail.com>
Date: Thu, 21 Nov 2024 16:17:37 -0500
Subject: [PATCH 01/25] Initial: Move docs and lint to gh actions

---
 .azure/lint_docs-linux.yml      | 45 --------------------------
 .github/workflows/lint_docs.yml | 57 +++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 45 deletions(-)
 delete mode 100644 .azure/lint_docs-linux.yml
 create mode 100644 .github/workflows/lint_docs.yml

diff --git a/.azure/lint_docs-linux.yml b/.azure/lint_docs-linux.yml
deleted file mode 100644
index b9e0c37892df..000000000000
--- a/.azure/lint_docs-linux.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-parameters:
-  - name: "pythonVersion"
-    type: string
-    displayName: "Version of Python to use"
-
-jobs:
-  - job: 'Lint_Docs'
-    displayName: 'Lint and documentation'
-    pool: {vmImage: 'ubuntu-latest'}
-
-    variables:
-      PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip
-      RUST_DEBUG: 1
-
-    steps:
-      - checkout: self
-
-      - task: UsePythonVersion@0
-        inputs:
-          versionSpec: '${{ parameters.pythonVersion }}'
-        displayName: 'Use Python ${{ parameters.pythonVersion }}'
-
-      - bash: tools/install_ubuntu_docs_dependencies.sh
-        displayName: 'Install docs dependencies'
-
-      - bash: tox run -e docs,lint
-        displayName: 'Lint and docs'
-
-      - bash: rm -rf docs/_build/html/{.doctrees,.buildinfo}
-        displayName: 'Clean up docs detritus'
-
-      - task: ArchiveFiles@2
-        inputs:
-          rootFolderOrFile: 'docs/_build/html'
-          archiveType: tar
-          archiveFile: '$(Build.ArtifactStagingDirectory)/html_docs.tar.gz'
-          verbose: true
-
-      - task: PublishBuildArtifacts@1
-        displayName: 'Upload docs artifact'
-        inputs:
-          pathtoPublish: '$(Build.ArtifactStagingDirectory)'
-          artifactName: 'html_docs'
-          Parallel: true
-          ParallelCount: 8
diff --git a/.github/workflows/lint_docs.yml b/.github/workflows/lint_docs.yml
new file mode 100644
index 000000000000..35e06b965759
--- /dev/null
+++ b/.github/workflows/lint_docs.yml
@@ -0,0 +1,57 @@
+---
+name: Lint and Docs
+on:
+  push:
+    branches: [ main, 'stable/*' ]
+  pull_request:
+    branches: [ main, 'stable/*' ]
+  merge_group:
+
+concurrency:
+  group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}
+  cancel-in-progress: true
+jobs:
+  docs:
+    if: github.repository_owner == 'Qiskit'
+    name: Docs
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: False
+    steps:
+    - uses: actions/checkout@v4
+    - name: Set up Python
+      uses: actions/setup-python@v5
+      with:
+        python-version: '3.9'
+    - name: Install ubuntu docs dependencies
+      run: tools/install_ubuntu_docs_dependencies.sh
+    - name: Run docs
+      run: |
+      tox -e docs
+    - name: Store built documentation artifact
+      uses: actions/upload-artifact@v4
+      with:
+        name: qiskit-docs
+        path: |
+          ./docs/_build/html/*
+          !**/.doctrees
+          !**/.buildinfo
+        if-no-files-found: error
+  lint:
+    if: github.repository_owner == 'Qiskit'
+    name: Lint
+    runs-on: macOS-14
+    strategy:
+      fail-fast: False
+    steps:
+    - uses: actions/checkout@v4
+    - name: Set up Python
+      uses: actions/setup-python@v5
+      with:
+        python-version: '3.9'
+    - name: Install ubuntu docs dependencies
+      run: tools/install_ubuntu_docs_dependencies.sh
+    - name: Run lint
+      run: |
+      tox -e lint
+        
\ No newline at end of file

From b5bd039519ac6bb7705a2a380dbfbea56cf6be63 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <raynelfss@hotmail.com>
Date: Fri, 22 Nov 2024 09:50:57 -0500
Subject: [PATCH 02/25] Fix: Wrong usage of map in `lint_docs` workflow

---
 .github/workflows/lint_docs.yml | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/lint_docs.yml b/.github/workflows/lint_docs.yml
index 35e06b965759..413b4ffc6e34 100644
--- a/.github/workflows/lint_docs.yml
+++ b/.github/workflows/lint_docs.yml
@@ -26,8 +26,7 @@ jobs:
     - name: Install ubuntu docs dependencies
       run: tools/install_ubuntu_docs_dependencies.sh
     - name: Run docs
-      run: |
-      tox -e docs
+      run: tox -e docs
     - name: Store built documentation artifact
       uses: actions/upload-artifact@v4
       with:
@@ -52,6 +51,5 @@ jobs:
     - name: Install ubuntu docs dependencies
       run: tools/install_ubuntu_docs_dependencies.sh
     - name: Run lint
-      run: |
-      tox -e lint
+      run: tox -e lint
         
\ No newline at end of file

From bd42c718b8c4535b2beb226d5c1b515731f79e2c Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <raynelfss@hotmail.com>
Date: Fri, 22 Nov 2024 09:53:59 -0500
Subject: [PATCH 03/25] Fix: Use ubuntu-latest for lint

---
 .github/workflows/lint_docs.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/lint_docs.yml b/.github/workflows/lint_docs.yml
index 413b4ffc6e34..633fe7a7e71c 100644
--- a/.github/workflows/lint_docs.yml
+++ b/.github/workflows/lint_docs.yml
@@ -39,7 +39,7 @@ jobs:
   lint:
     if: github.repository_owner == 'Qiskit'
     name: Lint
-    runs-on: macOS-14
+    runs-on: ubuntu-latest
     strategy:
       fail-fast: False
     steps:

From 4f8f941b18e0170ca63b82101084087b6b5f5966 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Mon, 25 Nov 2024 08:45:59 -0500
Subject: [PATCH 04/25] Fix: Add step to delete `doctrees` and `buildinfo` -
 Added `depth: 0` to checkout to avoid reno bugs.

---
 .github/workflows/lint_docs.yml | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/lint_docs.yml b/.github/workflows/lint_docs.yml
index 633fe7a7e71c..941c20bd1c74 100644
--- a/.github/workflows/lint_docs.yml
+++ b/.github/workflows/lint_docs.yml
@@ -8,7 +8,7 @@ on:
   merge_group:
 
 concurrency:
-  group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}
+  group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}-${{ github.workflow }}
   cancel-in-progress: true
 jobs:
   docs:
@@ -16,9 +16,12 @@ jobs:
     name: Docs
     runs-on: ubuntu-latest
     strategy:
-      fail-fast: False
+      fail-fast: true
     steps:
     - uses: actions/checkout@v4
+      with:
+        # We need to fetch the whole history so 'reno' can do its job and we can inspect tags.
+        fetch-depth: 0
     - name: Set up Python
       uses: actions/setup-python@v5
       with:
@@ -27,23 +30,26 @@ jobs:
       run: tools/install_ubuntu_docs_dependencies.sh
     - name: Run docs
       run: tox -e docs
+    - name: Clean up docs detritus
+      run: rm -rf docs/_build/html/{.doctrees,.buildinfo}
     - name: Store built documentation artifact
       uses: actions/upload-artifact@v4
       with:
         name: qiskit-docs
         path: |
           ./docs/_build/html/*
-          !**/.doctrees
-          !**/.buildinfo
         if-no-files-found: error
   lint:
     if: github.repository_owner == 'Qiskit'
     name: Lint
     runs-on: ubuntu-latest
     strategy:
-      fail-fast: False
+      fail-fast: true
     steps:
     - uses: actions/checkout@v4
+      with:
+        # We need to fetch the whole history so 'reno' can do its job and we can inspect tags.
+        fetch-depth: 0
     - name: Set up Python
       uses: actions/setup-python@v5
       with:

From 25c4ca474a6ae0aebf58cda188cc9f8db0756922 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Mon, 25 Nov 2024 13:20:53 -0500
Subject: [PATCH 05/25] Add: First drafts of Linux tests

---
 .github/workflows/tests.yml | 163 ++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 39439f7dd059..a2d4a2fbf6d5 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -5,12 +5,175 @@ on:
     branches: [ main, 'stable/*' ]
   pull_request:
     branches: [ main, 'stable/*' ]
+  workflow_call:
+    inputs:
+      test-rust:
+        description: >
+          Decides whether we perform rust tests
+        type: boolean
+      
+      test-images:
+        description: >
+          Decides whether we perform image tests
+        type: boolean
+      
+      install-optionals:
+        description: >
+          Decides whether we install optyional dependencies
+        type: boolean
+        default: false
+      
+      install-from-dist:
+        description: >
+          Decides whether we perform rust tests
+        type: boolean
+        default: false
+
   merge_group:
 
 concurrency:
   group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}
   cancel-in-progress: true
 jobs:
+  tests-linux:
+    if: github.repository_owner == 'Qiskit'
+    name: ubuntu-latest-tests-Python-${{ matrix.python-version }}
+    runs-on: ubuntu-latest
+    env:
+      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
+      PIP_CACHE_DIR: ${{ github.workspace }}/.pip
+      QISKIT_TEST_CAPTURE_STREAMS: 1
+      HAVE_VISUAL_TESTS_RUN: false
+    strategy:
+      fail-fast: false
+      matrix:
+        python-version: ["3.9", "3.13"]
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install Rust toolchain
+        uses: dtolnay/rust-toolchain@1.70
+        if: matrix.python-version == '3.9'
+      - name: Set up Python ${{ matrix.python-version }}
+        id: python-outputs
+        uses: actions/setup-python@v5
+        with:
+          python-version: ${{ matrix.python-version }}
+      - name: Cache stestr
+        uses: actions/cache@v4
+        with:
+          key: 'stestr | "${{ runner.os }}" | "${{ matrix.python-version }}" | "${{ github.run_id }}"'
+          restore-keys: |
+            stestr | "${{ runner.os }}" | "${{ matrix.python-version }}"
+            stestr | "${{ runner.os }}"
+            stestr
+          path: .stestr
+      - name: Run Rust Tests
+        if: inputs.test-rust == true
+        # We need to avoid linking our crates into full Python extension libraries during Rust-only
+        # testing because Rust/PyO3 can't handle finding a static CPython interpreter.
+        run: cargo test --no-default-features
+        env:
+          # On Linux we link against `libpython` dynamically, but it isn't written into the rpath
+          # of the test executable (I'm not 100% sure why ---Jake).  It's easiest just to forcibly
+          # include the correct place in the `dlopen` search path.
+          LD_LIBRARY_PATH: '${{ steps.python-outputs.outputs.python-path }}/lib:$LD_LIBRARY_PATH'
+      - name: Prepare venv
+        run: |
+          set -e
+          python -m pip install --upgrade pip setuptools wheel virtualenv
+          virtualenv test-job
+      - name: Install Qiskit from sdist
+        if: ${{ inputs.install-from-dist }}
+        run: |
+          set -e
+          # Use stable Rust, rather than MSRV, to spot-check that stable builds properly.
+          rustup override set stable
+          source test-job/bin/activate
+          python -m pip install -U pip
+          python -m pip install -U build
+          python -m build --sdist .
+          python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            dist/qiskit-*.tar.gz
+          # Build and install both qiskit and qiskit-terra so that any optionals
+          # depending on `qiskit` will resolve correctly.
+      - name: Install QIskit directly
+        if: ${{ !inputs.install-from-dist }}
+        run: |
+          set -e
+          source test-job/bin/activate
+          python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            -e .
+          # Build and install both qiskit and qiskit-terra so that any optionals
+          # depending on `qiskit` will resolve correctly.
+      - name: Install Optional packages
+        run: |
+          set -e
+          source test-job/bin/activate
+          python -m pip install -r requirements-optional.txt -c constraints.txt
+          python -m pip check
+        if: ${{ inputs.install-optionals }}
+      - name: Install optional non-Python dependencies
+        run: |
+          set -e
+          sudo apt-get update
+          sudo apt-get install -y graphviz
+        if: ${{ inputs.install-optionals }}
+      - name: Run Python tests
+        run: |
+          set -e
+          source test-job/bin/activate
+          python tools/report_numpy_state.py
+          mkdir -p /tmp/terra-tests
+          cp -r test /tmp/terra-tests/.
+          cp .stestr.conf /tmp/terra-tests/.
+          cp -r .stestr /tmp/terra-tests/. || :
+          pushd /tmp/terra-tests
+          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 4294967295))")
+          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
+          stestr run
+          popd
+        env:
+          QISKIT_PARALLEL: FALSE
+          RUST_BACKTRACE: 1
+      - name: Install Image dependencies
+        run: |
+          set -e
+          virtualenv image_tests
+          image_tests/bin/python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            -r requirements-optional.txt \
+            -e .
+          sudo apt-get update
+          sudo apt-get install -y graphviz pandoc
+          image_tests/bin/pip check
+        if: ${{ inputs.test-images }}
+      - name: Run image tests
+        run: |
+          echo "##vso[task.setvariable variable=HAVE_VISUAL_TESTS_RUN;]true"
+          image_tests/bin/python -m unittest discover -v test/visual
+        if: ${{ inputs.test-images }}
+        env:
+          # Needed to suppress a warning in jupyter-core 5.x by eagerly migrating to
+          # a new internal interface that will be the default in jupyter-core 6.x.
+          # This variable should become redundant on release of jupyter-core 6.
+          JUPYTER_PLATFORM_DIRS: 1
+      - name: Store image tests diff
+        uses: actions/upload-artifact@v4
+        if: ${{ inputs.test-images && failure()}}
+        with:
+          name: image-test-failure-img-diffs
+          path: |
+            ./test/visual/mpl/graph/graph_results
+          if-no-files-found: error  
+        
   tests:
     if: github.repository_owner == 'Qiskit'
     name: macOS-arm64-tests-Python-${{ matrix.python-version }}

From 547d872163dbf1fd2a97d702997ff35ef0ffa1f8 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Tue, 26 Nov 2024 12:31:23 -0500
Subject: [PATCH 06/25] Add: First draft of Windows tests

---
 .github/workflows/tests.yml | 86 ++++++++++++++++++++++++++++++++++---
 1 file changed, 79 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index a2d4a2fbf6d5..bd01c949518a 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -99,7 +99,7 @@ jobs:
             dist/qiskit-*.tar.gz
           # Build and install both qiskit and qiskit-terra so that any optionals
           # depending on `qiskit` will resolve correctly.
-      - name: Install QIskit directly
+      - name: Install Qiskit directly
         if: ${{ !inputs.install-from-dist }}
         run: |
           set -e
@@ -181,14 +181,12 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        # Normally we test min and max version but we can't run python
-        # 3.9 on arm64 until actions/setup-python#808 is resolved
-        python-version: ["3.10", "3.13"]
+        python-version: ["3.9", "3.13"]
     steps:
       - uses: actions/checkout@v4
       - name: Install Rust toolchain
         uses: dtolnay/rust-toolchain@1.70
-        if: matrix.python-version == '3.10'
+        if: matrix.python-version == '3.9'
       - name: Set up Python ${{ matrix.python-version }}
         uses: actions/setup-python@v5
         with:
@@ -199,7 +197,7 @@ jobs:
           python -m pip install -U -r requirements.txt -c constraints.txt
           python -m pip install -U -r requirements-dev.txt -c constraints.txt
           python -m pip install -c constraints.txt -e .
-        if: matrix.python-version == '3.10'
+        if: matrix.python-version == '3.9'
         env:
           QISKIT_NO_CACHE_GATES: 1
       - name: 'Install dependencies'
@@ -212,6 +210,80 @@ jobs:
         run: |
           python -m pip install -r requirements-optional.txt -c constraints.txt
           python tools/report_numpy_state.py
-        if: matrix.python-version == '3.10'
+        if: matrix.python-version == '3.9'
       - name: 'Run tests'
         run: stestr run
+  
+  test-windows:
+    if: github.repository_owner == 'Qiskit'
+    name: windows-latest-tests-Python-${{ matrix.python-version }}
+    runs-on: windows-latest
+    env:
+      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
+      QISKIT_TEST_CAPTURE_STREAMS: 1
+    strategy:
+      fail-fast: false
+      matrix:
+        python-version: ["3.9", "3.13"]
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install Rust toolchain
+        uses: dtolnay/rust-toolchain@1.70
+        if: matrix.python-version == '3.9'
+      - name: Set up Python ${{ matrix.python-version }}
+        id: python-outputs
+        uses: actions/setup-python@v5
+        with:
+          python-version: ${{ matrix.python-version }}
+      - name: Cache stestr
+        uses: actions/cache@v4
+        with:
+          key: 'stestr | "${{ runner.os }}" | "${{ matrix.python-version }}" | "${{ github.run_id }}"'
+          restore-keys: |
+            stestr | "${{ runner.os }}" | "${{ matrix.python-version }}"
+            stestr | "${{ runner.os }}"
+            stestr
+          path: .stestr
+      - name: Install dependencies
+        run: |
+          set -e
+          python -m pip install --upgrade pip setuptools wheel virtualenv
+          virtualenv test-job
+          source test-job/Scripts/activate
+          python -m pip install -U pip setuptools wheel
+          python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            -e .
+          # Build and install both qiskit and qiskit-terra so that any optionals
+          # depending on `qiskit` will resolve correctly.
+          pip check
+      - name: Install Optional packages
+        run: |
+          set -e
+          source test-job/Scripts/activate
+          pip install -c constraints.txt -r requirements-optional.txt
+          pip check
+        if: ${{ inputs.install-optionals }}
+      - name: Run Tests
+        run: |
+          set -e
+          chcp.com 65001
+          source test-job/Scripts/activate
+          python tools/report_numpy_state.py
+          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 1024))")
+          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
+          stestr run
+        env:
+          LANG: 'C.UTF-8'
+          PYTHONIOENCODING: 'utf-8:backslashreplace'
+          QISKIT_PARALLEL: FALSE
+          RUST_BACKTRACE: 1
+      - name: Copy and Publish images
+        uses: actions/upload-artifact@v4
+        if: ${{ failure() }}
+        with:
+          name: copied-images
+          path: '**/*.png'
+          if-no-files-found: error

From 473b6ff75a91093ad7568fb037c68f22cb5abe83 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Tue, 26 Nov 2024 12:39:20 -0500
Subject: [PATCH 07/25] Fix: Use Poweshell formatting for scripts in Windows

---
 .github/workflows/tests.yml | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index bd01c949518a..345085cb47eb 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -246,10 +246,9 @@ jobs:
           path: .stestr
       - name: Install dependencies
         run: |
-          set -e
           python -m pip install --upgrade pip setuptools wheel virtualenv
-          virtualenv test-job
-          source test-job/Scripts/activate
+          python -m virtualenv test-job
+          .\test-job\Scripts\activate
           python -m pip install -U pip setuptools wheel
           python -m pip install -U \
             -c constraints.txt \
@@ -261,8 +260,7 @@ jobs:
           pip check
       - name: Install Optional packages
         run: |
-          set -e
-          source test-job/Scripts/activate
+          .\test-job\Scripts\activate
           pip install -c constraints.txt -r requirements-optional.txt
           pip check
         if: ${{ inputs.install-optionals }}
@@ -270,7 +268,7 @@ jobs:
         run: |
           set -e
           chcp.com 65001
-          source test-job/Scripts/activate
+          .\test-job\Scripts\activate
           python tools/report_numpy_state.py
           export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 1024))")
           echo "PYTHONHASHSEED=$PYTHONHASHSEED"

From 1523cf6287af5315a09b59f1739f864d63232bc8 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Tue, 26 Nov 2024 12:43:14 -0500
Subject: [PATCH 08/25] Fix: Formatting for multiline commands in Powershell

---
 .github/workflows/tests.yml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 345085cb47eb..6a463d5eeef2 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -250,10 +250,10 @@ jobs:
           python -m virtualenv test-job
           .\test-job\Scripts\activate
           python -m pip install -U pip setuptools wheel
-          python -m pip install -U \
-            -c constraints.txt \
-            -r requirements.txt \
-            -r requirements-dev.txt \
+          python -m pip install -U `
+            -c constraints.txt `
+            -r requirements.txt `
+            -r requirements-dev.txt `
             -e .
           # Build and install both qiskit and qiskit-terra so that any optionals
           # depending on `qiskit` will resolve correctly.

From c62b8c91e149f0b7972102b74a3af3d21a25b314 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Tue, 26 Nov 2024 12:49:03 -0500
Subject: [PATCH 09/25] Fix: Remove `set -e` from all windows environments.

---
 .github/workflows/tests.yml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 6a463d5eeef2..afa6c85d79b2 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -266,7 +266,6 @@ jobs:
         if: ${{ inputs.install-optionals }}
       - name: Run Tests
         run: |
-          set -e
           chcp.com 65001
           .\test-job\Scripts\activate
           python tools/report_numpy_state.py

From 5abe5982a9fbf5c4530cb91fa635432cc52f20d1 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Tue, 26 Nov 2024 13:05:23 -0500
Subject: [PATCH 10/25] Fix: Use correct powershell export patterns

---
 .github/workflows/tests.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index afa6c85d79b2..60ebb6b4b69b 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -269,7 +269,7 @@ jobs:
           chcp.com 65001
           .\test-job\Scripts\activate
           python tools/report_numpy_state.py
-          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 1024))")
+          $Env:PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 1024))")
           echo "PYTHONHASHSEED=$PYTHONHASHSEED"
           stestr run
         env:

From 6371ce93ae0041abde2e5f1860a6c793794a751d Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Tue, 26 Nov 2024 15:15:19 -0500
Subject: [PATCH 11/25] Add: First draft of new Mac tests

---
 .github/workflows/tests.yml | 57 +++++++++++++++++++++++++------------
 1 file changed, 39 insertions(+), 18 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 60ebb6b4b69b..353bd63d6de1 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -174,10 +174,14 @@ jobs:
             ./test/visual/mpl/graph/graph_results
           if-no-files-found: error  
         
-  tests:
+  tests-mac:
     if: github.repository_owner == 'Qiskit'
     name: macOS-arm64-tests-Python-${{ matrix.python-version }}
     runs-on: macOS-14
+    env:
+      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
+      PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip
+      QISKIT_TEST_CAPTURE_STREAMS: 1
     strategy:
       fail-fast: false
       matrix:
@@ -194,26 +198,43 @@ jobs:
           architecture: arm64
       - name: 'Install dependencies'
         run: |
-          python -m pip install -U -r requirements.txt -c constraints.txt
-          python -m pip install -U -r requirements-dev.txt -c constraints.txt
-          python -m pip install -c constraints.txt -e .
-        if: matrix.python-version == '3.9'
-        env:
-          QISKIT_NO_CACHE_GATES: 1
-      - name: 'Install dependencies'
-        run: |
-          python -m pip install -U -r requirements.txt -c constraints.txt
-          python -m pip install -U -r requirements-dev.txt -c constraints.txt
-          python -m pip install -c constraints.txt -e .
-        if: matrix.python-version == '3.13'
+          set -e
+          python -m pip install --upgrade pip setuptools wheel virtualenv
+          virtualenv test-job
+          source test-job/bin/activate
+          python -m pip install -U pip setuptools wheel
+          python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            -e .
+            # Build and install both qiskit and qiskit-terra so that any optionals
+            # depending on `qiskit` will resolve correctly.
+          pip check
       - name: 'Install optionals'
         run: |
-          python -m pip install -r requirements-optional.txt -c constraints.txt
-          python tools/report_numpy_state.py
-        if: matrix.python-version == '3.9'
+          set -e
+          source test-job/bin/activate
+          pip install -r requirements-optional.txt -c constraints.txt
+        if: ${{ inputs.install-optionals }}
       - name: 'Run tests'
-        run: stestr run
-  
+        run: |
+          set -e
+          source test-job/bin/activate
+          python tools/report_numpy_state.py
+          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 4294967295))")
+          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
+          stestr run
+        env:
+          QISKIT_PARALLEL: FALSE
+          RUST_BACKTRACE: 1
+      - name: Copy and Publish images
+        uses: actions/upload-artifact@v4
+        if: ${{ failure() }}
+        with:
+          name: copied-images
+          path: '**/*.png'
+          if-no-files-found: error
   test-windows:
     if: github.repository_owner == 'Qiskit'
     name: windows-latest-tests-Python-${{ matrix.python-version }}

From d53cb40f70eefef2220d1e800d9cc9acea625336 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Tue, 26 Nov 2024 15:18:42 -0500
Subject: [PATCH 12/25] Fix: Add cache step

---
 .github/workflows/tests.yml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 353bd63d6de1..63be7bd47168 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -196,6 +196,15 @@ jobs:
         with:
           python-version: ${{ matrix.python-version }}
           architecture: arm64
+      - name: Cache stestr
+        uses: actions/cache@v4
+        with:
+          key: 'stestr | "${{ runner.os }}" | "${{ matrix.python-version }}" | "${{ github.run_id }}"'
+          restore-keys: |
+            stestr | "${{ runner.os }}" | "${{ matrix.python-version }}"
+            stestr | "${{ runner.os }}"
+            stestr
+          path: .stestr
       - name: 'Install dependencies'
         run: |
           set -e

From a81f2649d3545fb870576a334671f210f593831e Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Mon, 2 Dec 2024 13:51:07 -0500
Subject: [PATCH 13/25] Add: CI main workflow.

---
 .github/workflows/ci-config.yml    |  76 +++++++
 .github/workflows/lint_docs.yml    |   4 -
 .github/workflows/test-mac.yml     |  88 ++++++++
 .github/workflows/test-windows.yml |  88 ++++++++
 .github/workflows/tests-linux.yml  | 171 ++++++++++++++++
 .github/workflows/tests.yml        | 316 -----------------------------
 6 files changed, 423 insertions(+), 320 deletions(-)
 create mode 100644 .github/workflows/ci-config.yml
 create mode 100644 .github/workflows/test-mac.yml
 create mode 100644 .github/workflows/test-windows.yml
 create mode 100644 .github/workflows/tests-linux.yml
 delete mode 100644 .github/workflows/tests.yml

diff --git a/.github/workflows/ci-config.yml b/.github/workflows/ci-config.yml
new file mode 100644
index 000000000000..1bde53818945
--- /dev/null
+++ b/.github/workflows/ci-config.yml
@@ -0,0 +1,76 @@
+---
+name: Qiskit CI Workflow (Docs, Lint, and Tests)
+on:
+  push:
+    branches: [main, "stable/*"]
+  pull_request:
+    branches: [main, "stable/*"]
+  merge_group:
+
+concurrency:
+  group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}
+  cancel-in-progress: true
+
+jobs:
+  lint-docs:
+    name: Lint and Docs
+    runs-on: ubuntu-latest
+    steps:
+      - uses: ./.github/workflows/lint_docs.yml
+  preliminary-tests:
+    name: Preliminary Tests
+    runs-on: ubuntu-latest
+    steps:
+      - uses: ./.github/workflows/test-linux.yml
+        with:
+          python-version: "3.9"
+          # A PR is more likely to fail CI because it introduces a logic error
+          # into an existing test than because it adds a new test / optional
+          # dependency that isn't accounted for in the test-skipping logic
+          # (and such a failure would need fewer iterations to fix).  We want
+          # to fail fast in the first CI stage.
+          install-optionals: true
+          test-rust: true
+          test-images: true
+  main-tests-ubuntu:
+    runs-on: ubuntu-latest
+    name: Main Tests (ubuntu-latest)
+    needs: [lint-docs, preliminary-tests]
+    strategy:
+      matrix:
+        python_version: ["3.13"]
+    steps:
+      - uses: ./.github/workflows/test-linux.yml
+        with:
+          python-version: ${{ matrix.python_version }}
+          test-rust: false
+          test-images: false
+          install-from-sdist: true
+          install-optionals: false
+
+  main-tests-mac:
+    runs-on: macos-14
+    name: Main Tests (ubuntu-latest)
+    needs: [lint-docs, preliminary-tests]
+    strategy:
+      matrix:
+        python_version: ["3.9", "3.13"]
+    steps:
+      - uses: ./.github/workflows/test-macos.yml
+        with:
+          python-version: ${{ matrix.python_version }}
+          install-optionals: ${{ matrix.python_version == '3.9'}}
+
+  main-tests-windows:
+    runs-on: macos-14
+    name: Main Tests (ubuntu-latest)
+    needs: [lint-docs, preliminary-tests]
+    strategy:
+      matrix:
+        python_version: ["3.9", "3.13"]
+    steps:
+      - uses: ./.github/workflows/test-windows.yml
+        with:
+          python-version: ${{ matrix.python_version }}
+          install-optionals: ${{ matrix.python_version == '3.9'}}
+
diff --git a/.github/workflows/lint_docs.yml b/.github/workflows/lint_docs.yml
index 941c20bd1c74..e4bab1bdd2c3 100644
--- a/.github/workflows/lint_docs.yml
+++ b/.github/workflows/lint_docs.yml
@@ -1,10 +1,6 @@
 ---
 name: Lint and Docs
 on:
-  push:
-    branches: [ main, 'stable/*' ]
-  pull_request:
-    branches: [ main, 'stable/*' ]
   merge_group:
 
 concurrency:
diff --git a/.github/workflows/test-mac.yml b/.github/workflows/test-mac.yml
new file mode 100644
index 000000000000..703f0a0964e1
--- /dev/null
+++ b/.github/workflows/test-mac.yml
@@ -0,0 +1,88 @@
+---
+name: Test Windows
+on:
+  workflow_call:
+    inputs:
+      python-version:
+        description: >
+          Python version to currently test
+        type: string
+        required: true
+
+      install-optionals:
+        description: >
+          Decides whether we install optyional dependencies
+        type: boolean
+        default: false
+
+  merge_group:
+
+jobs:
+  tests-mac:
+    if: github.repository_owner == 'Qiskit'
+    name: macOS-arm64-tests-Python-${{ inputs.python-version }}
+    runs-on: macOS-14
+    env:
+      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
+      PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip
+      QISKIT_TEST_CAPTURE_STREAMS: 1
+    strategy:
+      fail-fast: false
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install Rust toolchain
+        uses: dtolnay/rust-toolchain@1.70
+        if: inputs.python-version == '3.9'
+      - name: Set up Python ${{ inputs.python-version }}
+        uses: actions/setup-python@v5
+        with:
+          python-version: ${{ inputs.python-version }}
+          architecture: arm64
+      - name: Cache stestr
+        uses: actions/cache@v4
+        with:
+          key: 'stestr | "${{ runner.os }}" | "${{ inputs.python-version }}" | "${{ github.run_id }}"'
+          restore-keys: |
+            stestr | "${{ runner.os }}" | "${{ inputs.python-version }}"
+            stestr | "${{ runner.os }}"
+            stestr
+          path: .stestr
+      - name: "Install dependencies"
+        run: |
+          set -e
+          python -m pip install --upgrade pip setuptools wheel virtualenv
+          virtualenv test-job
+          source test-job/bin/activate
+          python -m pip install -U pip setuptools wheel
+          python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            -e .
+            # Build and install both qiskit and qiskit-terra so that any optionals
+            # depending on `qiskit` will resolve correctly.
+          pip check
+      - name: "Install optionals"
+        run: |
+          set -e
+          source test-job/bin/activate
+          pip install -r requirements-optional.txt -c constraints.txt
+        if: ${{ inputs.install-optionals }}
+      - name: "Run tests"
+        run: |
+          set -e
+          source test-job/bin/activate
+          python tools/report_numpy_state.py
+          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 4294967295))")
+          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
+          stestr run
+        env:
+          QISKIT_PARALLEL: FALSE
+          RUST_BACKTRACE: 1
+      - name: Copy and Publish images
+        uses: actions/upload-artifact@v4
+        if: ${{ failure() }}
+        with:
+          name: copied-images
+          path: "**/*.png"
+          if-no-files-found: error
diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml
new file mode 100644
index 000000000000..48d1a33f06a7
--- /dev/null
+++ b/.github/workflows/test-windows.yml
@@ -0,0 +1,88 @@
+---
+name: Test Windows
+on:
+  workflow_call:
+    inputs:
+      python-version:
+        description: >
+          Python version to currently test
+        type: string
+        required: true
+
+      install-optionals:
+        description: >
+          Decides whether we install optyional dependencies
+        type: boolean
+        default: false
+
+  merge_group:
+
+jobs:
+  test-windows:
+    if: github.repository_owner == 'Qiskit'
+    name: windows-latest-tests-Python-${{ inputs.python-version }}
+    runs-on: windows-latest
+    env:
+      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
+      QISKIT_TEST_CAPTURE_STREAMS: 1
+    strategy:
+      fail-fast: false
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install Rust toolchain
+        uses: dtolnay/rust-toolchain@1.70
+        if: inputs.python-version == '3.9'
+      - name: Set up Python ${{ inputs.python-version }}
+        id: python-outputs
+        uses: actions/setup-python@v5
+        with:
+          python-version: ${{ inputs.python-version }}
+      - name: Cache stestr
+        uses: actions/cache@v4
+        with:
+          key: 'stestr | "${{ runner.os }}" | "${{ inputs.python-version }}" | "${{ github.run_id }}"'
+          restore-keys: |
+            stestr | "${{ runner.os }}" | "${{ inputs.python-version }}"
+            stestr | "${{ runner.os }}"
+            stestr
+          path: .stestr
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip setuptools wheel virtualenv
+          python -m virtualenv test-job
+          .\test-job\Scripts\activate
+          python -m pip install -U pip setuptools wheel
+          python -m pip install -U `
+            -c constraints.txt `
+            -r requirements.txt `
+            -r requirements-dev.txt `
+            -e .
+          # Build and install both qiskit and qiskit-terra so that any optionals
+          # depending on `qiskit` will resolve correctly.
+          pip check
+      - name: Install Optional packages
+        run: |
+          .\test-job\Scripts\activate
+          pip install -c constraints.txt -r requirements-optional.txt
+          pip check
+        if: ${{ inputs.install-optionals }}
+      - name: Run Tests
+        run: |
+          chcp.com 65001
+          .\test-job\Scripts\activate
+          python tools/report_numpy_state.py
+          $Env:PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 1024))")
+          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
+          stestr run
+        env:
+          LANG: "C.UTF-8"
+          PYTHONIOENCODING: "utf-8:backslashreplace"
+          QISKIT_PARALLEL: FALSE
+          RUST_BACKTRACE: 1
+      - name: Copy and Publish images
+        uses: actions/upload-artifact@v4
+        if: ${{ failure() }}
+        with:
+          name: copied-images
+          path: "**/*.png"
+          if-no-files-found: error
diff --git a/.github/workflows/tests-linux.yml b/.github/workflows/tests-linux.yml
new file mode 100644
index 000000000000..23c3ff3976b4
--- /dev/null
+++ b/.github/workflows/tests-linux.yml
@@ -0,0 +1,171 @@
+---
+name: Test Linux
+on:
+  workflow_call:
+    inputs:
+      python-version:
+        description: >
+          Python version to currently test
+        type: string
+        required: true
+      test-rust:
+        description: >
+          Decides whether we perform rust tests
+        type: boolean
+        required: true
+      test-images:
+        description: >
+          Decides whether we perform image tests
+        type: boolean
+        required: true
+      install-optionals:
+        description: >
+          Decides whether we install optyional dependencies
+        type: boolean
+        default: false
+
+      install-from-sdist:
+        description: >
+          Decides whether we perform rust tests
+        type: boolean
+        default: false
+
+  merge_group:
+
+jobs:
+  tests-linux:
+    if: github.repository_owner == 'Qiskit'
+    name: ubuntu-latest-tests-Python-${{ inputs.python-version }}
+    runs-on: ubuntu-latest
+    env:
+      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
+      PIP_CACHE_DIR: ${{ github.workspace }}/.pip
+      QISKIT_TEST_CAPTURE_STREAMS: 1
+      HAVE_VISUAL_TESTS_RUN: false
+    strategy:
+      fail-fast: false
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install Rust toolchain
+        uses: dtolnay/rust-toolchain@1.70
+        if: inputs.python-version == '3.9'
+      - name: Set up Python ${{ inputs.python-version }}
+        id: python-outputs
+        uses: actions/setup-python@v5
+        with:
+          python-version: ${{ inputs.python-version }}
+      - name: Cache stestr
+        uses: actions/cache@v4
+        with:
+          key: 'stestr | "${{ runner.os }}" | "${{ inputs.python-version }}" | "${{ github.run_id }}"'
+          restore-keys: |
+            stestr | "${{ runner.os }}" | "${{ inputs.python-version }}"
+            stestr | "${{ runner.os }}"
+            stestr
+          path: .stestr
+      - name: Run Rust Tests
+        if: inputs.test-rust == true
+        # We need to avoid linking our crates into full Python extension libraries during Rust-only
+        # testing because Rust/PyO3 can't handle finding a static CPython interpreter.
+        run: cargo test --no-default-features
+        env:
+          # On Linux we link against `libpython` dynamically, but it isn't written into the rpath
+          # of the test executable (I'm not 100% sure why ---Jake).  It's easiest just to forcibly
+          # include the correct place in the `dlopen` search path.
+          LD_LIBRARY_PATH: "${{ steps.python-outputs.outputs.python-path }}/lib:$LD_LIBRARY_PATH"
+      - name: Prepare venv
+        run: |
+          set -e
+          python -m pip install --upgrade pip setuptools wheel virtualenv
+          virtualenv test-job
+      - name: Install Qiskit from sdist
+        if: ${{ inputs.install-from-sdist }}
+        run: |
+          set -e
+          # Use stable Rust, rather than MSRV, to spot-check that stable builds properly.
+          rustup override set stable
+          source test-job/bin/activate
+          python -m pip install -U pip
+          python -m pip install -U build
+          python -m build --sdist .
+          python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            dist/qiskit-*.tar.gz
+          # Build and install both qiskit and qiskit-terra so that any optionals
+          # depending on `qiskit` will resolve correctly.
+      - name: Install Qiskit directly
+        if: ${{ !inputs.install-from-sdist }}
+        run: |
+          set -e
+          source test-job/bin/activate
+          python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            -e .
+          # Build and install both qiskit and qiskit-terra so that any optionals
+          # depending on `qiskit` will resolve correctly.
+      - name: Install Optional packages
+        run: |
+          set -e
+          source test-job/bin/activate
+          python -m pip install -r requirements-optional.txt -c constraints.txt
+          python -m pip check
+        if: ${{ inputs.install-optionals }}
+      - name: Install optional non-Python dependencies
+        run: |
+          set -e
+          sudo apt-get update
+          sudo apt-get install -y graphviz
+        if: ${{ inputs.install-optionals }}
+      - name: Run Python tests
+        run: |
+          set -e
+          source test-job/bin/activate
+          python tools/report_numpy_state.py
+          mkdir -p /tmp/terra-tests
+          cp -r test /tmp/terra-tests/.
+          cp .stestr.conf /tmp/terra-tests/.
+          cp -r .stestr /tmp/terra-tests/. || :
+          pushd /tmp/terra-tests
+          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 4294967295))")
+          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
+          stestr run
+          popd
+        env:
+          QISKIT_PARALLEL: FALSE
+          RUST_BACKTRACE: 1
+      - name: Install Image dependencies
+        run: |
+          set -e
+          virtualenv image_tests
+          image_tests/bin/python -m pip install -U \
+            -c constraints.txt \
+            -r requirements.txt \
+            -r requirements-dev.txt \
+            -r requirements-optional.txt \
+            -e .
+          sudo apt-get update
+          sudo apt-get install -y graphviz pandoc
+          image_tests/bin/pip check
+        if: ${{ inputs.test-images }}
+      - name: Run image tests
+        run: |
+          echo "##vso[task.setvariable variable=HAVE_VISUAL_TESTS_RUN;]true"
+          image_tests/bin/python -m unittest discover -v test/visual
+        if: ${{ inputs.test-images }}
+        env:
+          # Needed to suppress a warning in jupyter-core 5.x by eagerly migrating to
+          # a new internal interface that will be the default in jupyter-core 6.x.
+          # This variable should become redundant on release of jupyter-core 6.
+          JUPYTER_PLATFORM_DIRS: 1
+      - name: Store image tests diff
+        uses: actions/upload-artifact@v4
+        if: ${{ inputs.test-images && failure()}}
+        with:
+          name: image-test-failure-img-diffs
+          path: |
+            ./test/visual/mpl/graph/graph_results
+          if-no-files-found: error
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
deleted file mode 100644
index 63be7bd47168..000000000000
--- a/.github/workflows/tests.yml
+++ /dev/null
@@ -1,316 +0,0 @@
----
-name: Tests
-on:
-  push:
-    branches: [ main, 'stable/*' ]
-  pull_request:
-    branches: [ main, 'stable/*' ]
-  workflow_call:
-    inputs:
-      test-rust:
-        description: >
-          Decides whether we perform rust tests
-        type: boolean
-      
-      test-images:
-        description: >
-          Decides whether we perform image tests
-        type: boolean
-      
-      install-optionals:
-        description: >
-          Decides whether we install optyional dependencies
-        type: boolean
-        default: false
-      
-      install-from-dist:
-        description: >
-          Decides whether we perform rust tests
-        type: boolean
-        default: false
-
-  merge_group:
-
-concurrency:
-  group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}
-  cancel-in-progress: true
-jobs:
-  tests-linux:
-    if: github.repository_owner == 'Qiskit'
-    name: ubuntu-latest-tests-Python-${{ matrix.python-version }}
-    runs-on: ubuntu-latest
-    env:
-      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
-      PIP_CACHE_DIR: ${{ github.workspace }}/.pip
-      QISKIT_TEST_CAPTURE_STREAMS: 1
-      HAVE_VISUAL_TESTS_RUN: false
-    strategy:
-      fail-fast: false
-      matrix:
-        python-version: ["3.9", "3.13"]
-    steps:
-      - uses: actions/checkout@v4
-      - name: Install Rust toolchain
-        uses: dtolnay/rust-toolchain@1.70
-        if: matrix.python-version == '3.9'
-      - name: Set up Python ${{ matrix.python-version }}
-        id: python-outputs
-        uses: actions/setup-python@v5
-        with:
-          python-version: ${{ matrix.python-version }}
-      - name: Cache stestr
-        uses: actions/cache@v4
-        with:
-          key: 'stestr | "${{ runner.os }}" | "${{ matrix.python-version }}" | "${{ github.run_id }}"'
-          restore-keys: |
-            stestr | "${{ runner.os }}" | "${{ matrix.python-version }}"
-            stestr | "${{ runner.os }}"
-            stestr
-          path: .stestr
-      - name: Run Rust Tests
-        if: inputs.test-rust == true
-        # We need to avoid linking our crates into full Python extension libraries during Rust-only
-        # testing because Rust/PyO3 can't handle finding a static CPython interpreter.
-        run: cargo test --no-default-features
-        env:
-          # On Linux we link against `libpython` dynamically, but it isn't written into the rpath
-          # of the test executable (I'm not 100% sure why ---Jake).  It's easiest just to forcibly
-          # include the correct place in the `dlopen` search path.
-          LD_LIBRARY_PATH: '${{ steps.python-outputs.outputs.python-path }}/lib:$LD_LIBRARY_PATH'
-      - name: Prepare venv
-        run: |
-          set -e
-          python -m pip install --upgrade pip setuptools wheel virtualenv
-          virtualenv test-job
-      - name: Install Qiskit from sdist
-        if: ${{ inputs.install-from-dist }}
-        run: |
-          set -e
-          # Use stable Rust, rather than MSRV, to spot-check that stable builds properly.
-          rustup override set stable
-          source test-job/bin/activate
-          python -m pip install -U pip
-          python -m pip install -U build
-          python -m build --sdist .
-          python -m pip install -U \
-            -c constraints.txt \
-            -r requirements.txt \
-            -r requirements-dev.txt \
-            dist/qiskit-*.tar.gz
-          # Build and install both qiskit and qiskit-terra so that any optionals
-          # depending on `qiskit` will resolve correctly.
-      - name: Install Qiskit directly
-        if: ${{ !inputs.install-from-dist }}
-        run: |
-          set -e
-          source test-job/bin/activate
-          python -m pip install -U \
-            -c constraints.txt \
-            -r requirements.txt \
-            -r requirements-dev.txt \
-            -e .
-          # Build and install both qiskit and qiskit-terra so that any optionals
-          # depending on `qiskit` will resolve correctly.
-      - name: Install Optional packages
-        run: |
-          set -e
-          source test-job/bin/activate
-          python -m pip install -r requirements-optional.txt -c constraints.txt
-          python -m pip check
-        if: ${{ inputs.install-optionals }}
-      - name: Install optional non-Python dependencies
-        run: |
-          set -e
-          sudo apt-get update
-          sudo apt-get install -y graphviz
-        if: ${{ inputs.install-optionals }}
-      - name: Run Python tests
-        run: |
-          set -e
-          source test-job/bin/activate
-          python tools/report_numpy_state.py
-          mkdir -p /tmp/terra-tests
-          cp -r test /tmp/terra-tests/.
-          cp .stestr.conf /tmp/terra-tests/.
-          cp -r .stestr /tmp/terra-tests/. || :
-          pushd /tmp/terra-tests
-          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 4294967295))")
-          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
-          stestr run
-          popd
-        env:
-          QISKIT_PARALLEL: FALSE
-          RUST_BACKTRACE: 1
-      - name: Install Image dependencies
-        run: |
-          set -e
-          virtualenv image_tests
-          image_tests/bin/python -m pip install -U \
-            -c constraints.txt \
-            -r requirements.txt \
-            -r requirements-dev.txt \
-            -r requirements-optional.txt \
-            -e .
-          sudo apt-get update
-          sudo apt-get install -y graphviz pandoc
-          image_tests/bin/pip check
-        if: ${{ inputs.test-images }}
-      - name: Run image tests
-        run: |
-          echo "##vso[task.setvariable variable=HAVE_VISUAL_TESTS_RUN;]true"
-          image_tests/bin/python -m unittest discover -v test/visual
-        if: ${{ inputs.test-images }}
-        env:
-          # Needed to suppress a warning in jupyter-core 5.x by eagerly migrating to
-          # a new internal interface that will be the default in jupyter-core 6.x.
-          # This variable should become redundant on release of jupyter-core 6.
-          JUPYTER_PLATFORM_DIRS: 1
-      - name: Store image tests diff
-        uses: actions/upload-artifact@v4
-        if: ${{ inputs.test-images && failure()}}
-        with:
-          name: image-test-failure-img-diffs
-          path: |
-            ./test/visual/mpl/graph/graph_results
-          if-no-files-found: error  
-        
-  tests-mac:
-    if: github.repository_owner == 'Qiskit'
-    name: macOS-arm64-tests-Python-${{ matrix.python-version }}
-    runs-on: macOS-14
-    env:
-      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
-      PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip
-      QISKIT_TEST_CAPTURE_STREAMS: 1
-    strategy:
-      fail-fast: false
-      matrix:
-        python-version: ["3.9", "3.13"]
-    steps:
-      - uses: actions/checkout@v4
-      - name: Install Rust toolchain
-        uses: dtolnay/rust-toolchain@1.70
-        if: matrix.python-version == '3.9'
-      - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v5
-        with:
-          python-version: ${{ matrix.python-version }}
-          architecture: arm64
-      - name: Cache stestr
-        uses: actions/cache@v4
-        with:
-          key: 'stestr | "${{ runner.os }}" | "${{ matrix.python-version }}" | "${{ github.run_id }}"'
-          restore-keys: |
-            stestr | "${{ runner.os }}" | "${{ matrix.python-version }}"
-            stestr | "${{ runner.os }}"
-            stestr
-          path: .stestr
-      - name: 'Install dependencies'
-        run: |
-          set -e
-          python -m pip install --upgrade pip setuptools wheel virtualenv
-          virtualenv test-job
-          source test-job/bin/activate
-          python -m pip install -U pip setuptools wheel
-          python -m pip install -U \
-            -c constraints.txt \
-            -r requirements.txt \
-            -r requirements-dev.txt \
-            -e .
-            # Build and install both qiskit and qiskit-terra so that any optionals
-            # depending on `qiskit` will resolve correctly.
-          pip check
-      - name: 'Install optionals'
-        run: |
-          set -e
-          source test-job/bin/activate
-          pip install -r requirements-optional.txt -c constraints.txt
-        if: ${{ inputs.install-optionals }}
-      - name: 'Run tests'
-        run: |
-          set -e
-          source test-job/bin/activate
-          python tools/report_numpy_state.py
-          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 4294967295))")
-          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
-          stestr run
-        env:
-          QISKIT_PARALLEL: FALSE
-          RUST_BACKTRACE: 1
-      - name: Copy and Publish images
-        uses: actions/upload-artifact@v4
-        if: ${{ failure() }}
-        with:
-          name: copied-images
-          path: '**/*.png'
-          if-no-files-found: error
-  test-windows:
-    if: github.repository_owner == 'Qiskit'
-    name: windows-latest-tests-Python-${{ matrix.python-version }}
-    runs-on: windows-latest
-    env:
-      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
-      QISKIT_TEST_CAPTURE_STREAMS: 1
-    strategy:
-      fail-fast: false
-      matrix:
-        python-version: ["3.9", "3.13"]
-    steps:
-      - uses: actions/checkout@v4
-      - name: Install Rust toolchain
-        uses: dtolnay/rust-toolchain@1.70
-        if: matrix.python-version == '3.9'
-      - name: Set up Python ${{ matrix.python-version }}
-        id: python-outputs
-        uses: actions/setup-python@v5
-        with:
-          python-version: ${{ matrix.python-version }}
-      - name: Cache stestr
-        uses: actions/cache@v4
-        with:
-          key: 'stestr | "${{ runner.os }}" | "${{ matrix.python-version }}" | "${{ github.run_id }}"'
-          restore-keys: |
-            stestr | "${{ runner.os }}" | "${{ matrix.python-version }}"
-            stestr | "${{ runner.os }}"
-            stestr
-          path: .stestr
-      - name: Install dependencies
-        run: |
-          python -m pip install --upgrade pip setuptools wheel virtualenv
-          python -m virtualenv test-job
-          .\test-job\Scripts\activate
-          python -m pip install -U pip setuptools wheel
-          python -m pip install -U `
-            -c constraints.txt `
-            -r requirements.txt `
-            -r requirements-dev.txt `
-            -e .
-          # Build and install both qiskit and qiskit-terra so that any optionals
-          # depending on `qiskit` will resolve correctly.
-          pip check
-      - name: Install Optional packages
-        run: |
-          .\test-job\Scripts\activate
-          pip install -c constraints.txt -r requirements-optional.txt
-          pip check
-        if: ${{ inputs.install-optionals }}
-      - name: Run Tests
-        run: |
-          chcp.com 65001
-          .\test-job\Scripts\activate
-          python tools/report_numpy_state.py
-          $Env:PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 1024))")
-          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
-          stestr run
-        env:
-          LANG: 'C.UTF-8'
-          PYTHONIOENCODING: 'utf-8:backslashreplace'
-          QISKIT_PARALLEL: FALSE
-          RUST_BACKTRACE: 1
-      - name: Copy and Publish images
-        uses: actions/upload-artifact@v4
-        if: ${{ failure() }}
-        with:
-          name: copied-images
-          path: '**/*.png'
-          if-no-files-found: error

From a674d88cdae18682ed2b47768022881ebef0283f Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Mon, 2 Dec 2024 14:01:11 -0500
Subject: [PATCH 14/25] Fix: wrong usage of workflow calls. - Rename
 `tests-linux.yml` to  `test-linux.yml`.

---
 .github/workflows/ci-config.yml               | 67 ++++++++-----------
 .github/workflows/lint_docs.yml               |  3 +-
 .../{tests-linux.yml => test-linux.yml}       |  0
 3 files changed, 30 insertions(+), 40 deletions(-)
 rename .github/workflows/{tests-linux.yml => test-linux.yml} (100%)

diff --git a/.github/workflows/ci-config.yml b/.github/workflows/ci-config.yml
index 1bde53818945..23ffd85a4ab5 100644
--- a/.github/workflows/ci-config.yml
+++ b/.github/workflows/ci-config.yml
@@ -13,64 +13,53 @@ concurrency:
 
 jobs:
   lint-docs:
-    name: Lint and Docs
-    runs-on: ubuntu-latest
-    steps:
-      - uses: ./.github/workflows/lint_docs.yml
+    name: Docs and Lint
+    uses: ./.github/workflows/lint_docs.yml
   preliminary-tests:
     name: Preliminary Tests
-    runs-on: ubuntu-latest
-    steps:
-      - uses: ./.github/workflows/test-linux.yml
-        with:
-          python-version: "3.9"
-          # A PR is more likely to fail CI because it introduces a logic error
-          # into an existing test than because it adds a new test / optional
-          # dependency that isn't accounted for in the test-skipping logic
-          # (and such a failure would need fewer iterations to fix).  We want
-          # to fail fast in the first CI stage.
-          install-optionals: true
-          test-rust: true
-          test-images: true
+    uses: ./.github/workflows/test-linux.yml
+    with:
+      python-version: "3.9"
+      # A PR is more likely to fail CI because it introduces a logic error
+      # into an existing test than because it adds a new test / optional
+      # dependency that isn't accounted for in the test-skipping logic
+      # (and such a failure would need fewer iterations to fix).  We want
+      # to fail fast in the first CI stage.
+      install-optionals: true
+      test-rust: true
+      test-images: true
   main-tests-ubuntu:
-    runs-on: ubuntu-latest
     name: Main Tests (ubuntu-latest)
     needs: [lint-docs, preliminary-tests]
     strategy:
       matrix:
         python_version: ["3.13"]
-    steps:
-      - uses: ./.github/workflows/test-linux.yml
-        with:
-          python-version: ${{ matrix.python_version }}
-          test-rust: false
-          test-images: false
-          install-from-sdist: true
-          install-optionals: false
+    uses: ./.github/workflows/test-linux.yml
+    with:
+      python-version: ${{ matrix.python_version }}
+      test-rust: false
+      test-images: false
+      install-from-sdist: true
+      install-optionals: false
 
   main-tests-mac:
-    runs-on: macos-14
     name: Main Tests (ubuntu-latest)
     needs: [lint-docs, preliminary-tests]
     strategy:
       matrix:
         python_version: ["3.9", "3.13"]
-    steps:
-      - uses: ./.github/workflows/test-macos.yml
-        with:
-          python-version: ${{ matrix.python_version }}
-          install-optionals: ${{ matrix.python_version == '3.9'}}
+    uses: ./.github/workflows/test-mac.yml
+    with:
+      python-version: ${{ matrix.python_version }}
+      install-optionals: ${{ matrix.python_version == '3.9'}}
 
   main-tests-windows:
-    runs-on: macos-14
     name: Main Tests (ubuntu-latest)
     needs: [lint-docs, preliminary-tests]
     strategy:
       matrix:
         python_version: ["3.9", "3.13"]
-    steps:
-      - uses: ./.github/workflows/test-windows.yml
-        with:
-          python-version: ${{ matrix.python_version }}
-          install-optionals: ${{ matrix.python_version == '3.9'}}
-
+    uses: ./.github/workflows/test-windows.yml
+    with:
+      python-version: ${{ matrix.python_version }}
+      install-optionals: ${{ matrix.python_version == '3.9'}}
diff --git a/.github/workflows/lint_docs.yml b/.github/workflows/lint_docs.yml
index e4bab1bdd2c3..2636a24b0ea4 100644
--- a/.github/workflows/lint_docs.yml
+++ b/.github/workflows/lint_docs.yml
@@ -1,7 +1,8 @@
 ---
 name: Lint and Docs
 on:
-  merge_group:
+  workflow_call:
+    
 
 concurrency:
   group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}-${{ github.workflow }}
diff --git a/.github/workflows/tests-linux.yml b/.github/workflows/test-linux.yml
similarity index 100%
rename from .github/workflows/tests-linux.yml
rename to .github/workflows/test-linux.yml

From 053e84521ec6a56e94aa73333d6ca683ef58ea05 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Mon, 2 Dec 2024 14:02:29 -0500
Subject: [PATCH 15/25] Fix: Rename tests to their respective os

---
 .github/workflows/ci-config.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci-config.yml b/.github/workflows/ci-config.yml
index 23ffd85a4ab5..f5a6e5fc3767 100644
--- a/.github/workflows/ci-config.yml
+++ b/.github/workflows/ci-config.yml
@@ -43,7 +43,7 @@ jobs:
       install-optionals: false
 
   main-tests-mac:
-    name: Main Tests (ubuntu-latest)
+    name: Main Tests (macos)
     needs: [lint-docs, preliminary-tests]
     strategy:
       matrix:
@@ -54,7 +54,7 @@ jobs:
       install-optionals: ${{ matrix.python_version == '3.9'}}
 
   main-tests-windows:
-    name: Main Tests (ubuntu-latest)
+    name: Main Tests (windows-latest)
     needs: [lint-docs, preliminary-tests]
     strategy:
       matrix:

From ddb945bd9a08ee61f472bb568f9b826727b215a5 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Mon, 2 Dec 2024 14:17:45 -0500
Subject: [PATCH 16/25] Fix: Add correct library path for rust tests

---
 .github/workflows/test-linux.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index 23c3ff3976b4..de30f91b79df 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -72,7 +72,7 @@ jobs:
           # On Linux we link against `libpython` dynamically, but it isn't written into the rpath
           # of the test executable (I'm not 100% sure why ---Jake).  It's easiest just to forcibly
           # include the correct place in the `dlopen` search path.
-          LD_LIBRARY_PATH: "${{ steps.python-outputs.outputs.python-path }}/lib:$LD_LIBRARY_PATH"
+          LD_LIBRARY_PATH: "${{ steps.python-outputs.outputs.python-path }}/lib:${{env.LD_LIBRARY_PATH}}"
       - name: Prepare venv
         run: |
           set -e

From f2840f7c9071fce290f9ec47acb549eb99eb1e2b Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <raynelfss@hotmail.com>
Date: Tue, 3 Dec 2024 14:23:18 -0500
Subject: [PATCH 17/25] Add: Nightly, Merge-queue, and Push workflows - Add
 comments - Rename `Qiskit CI workflow` to `Pull Request`

---
 .github/workflows/ci-config.yml      | 23 +++++++++++---
 .github/workflows/nightly.yml        | 31 +++++++++++++++++++
 .github/workflows/on-merge-queue.yml | 45 ++++++++++++++++++++++++++++
 .github/workflows/on-nightly.yml     | 36 ++++++++++++++++++++++
 .github/workflows/on-push.yml        | 26 ++++++++++++++++
 5 files changed, 157 insertions(+), 4 deletions(-)
 create mode 100644 .github/workflows/nightly.yml
 create mode 100644 .github/workflows/on-merge-queue.yml
 create mode 100644 .github/workflows/on-nightly.yml
 create mode 100644 .github/workflows/on-push.yml

diff --git a/.github/workflows/ci-config.yml b/.github/workflows/ci-config.yml
index f5a6e5fc3767..723cb622c64d 100644
--- a/.github/workflows/ci-config.yml
+++ b/.github/workflows/ci-config.yml
@@ -1,8 +1,9 @@
 ---
-name: Qiskit CI Workflow (Docs, Lint, and Tests)
+# Full PR suite.  PRs need to pass this pipeline in order to be moved to the
+# merge queue, where they'll use the next rule as the branch-protection rule
+# for the final merge to the base branch.
+name: Pull Requests
 on:
-  push:
-    branches: [main, "stable/*"]
   pull_request:
     branches: [main, "stable/*"]
   merge_group:
@@ -10,14 +11,20 @@ on:
 concurrency:
   group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}
   cancel-in-progress: true
-
 jobs:
+  # The preliminary stage should be small in both total runtime (including
+  # provisioning) and resources required.  About half of PR commits result in
+  # a CI failure, and over 90% of these are in linting, documention or a test
+  # failure that would affect _any_ OS or Python version.  The goal in the
+  # first stage is to catch the vast majority of failures with minimal cost.
   lint-docs:
+    if: github.repository_owner == 'Qiskit'
     name: Docs and Lint
     uses: ./.github/workflows/lint_docs.yml
   preliminary-tests:
     name: Preliminary Tests
     uses: ./.github/workflows/test-linux.yml
+    if: github.repository_owner == 'Qiskit'
     with:
       python-version: "3.9"
       # A PR is more likely to fail CI because it introduces a logic error
@@ -28,7 +35,13 @@ jobs:
       install-optionals: true
       test-rust: true
       test-images: true
+
+  # The rest of the PR pipeline is to test the oldest and newest supported
+  # versions of Python. It's very rare for a failure to be specific to an
+  # intermediate version of Python, so we just catch those in the cron-job
+  # pipeline to reduce the amount of resources used.
   main-tests-ubuntu:
+    if: github.repository_owner == 'Qiskit'
     name: Main Tests (ubuntu-latest)
     needs: [lint-docs, preliminary-tests]
     strategy:
@@ -43,6 +56,7 @@ jobs:
       install-optionals: false
 
   main-tests-mac:
+    if: github.repository_owner == 'Qiskit'
     name: Main Tests (macos)
     needs: [lint-docs, preliminary-tests]
     strategy:
@@ -54,6 +68,7 @@ jobs:
       install-optionals: ${{ matrix.python_version == '3.9'}}
 
   main-tests-windows:
+    if: github.repository_owner == 'Qiskit'
     name: Main Tests (windows-latest)
     needs: [lint-docs, preliminary-tests]
     strategy:
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
new file mode 100644
index 000000000000..b7592e6d5233
--- /dev/null
+++ b/.github/workflows/nightly.yml
@@ -0,0 +1,31 @@
+---
+# A schedule only runs on branches that match include rules from _both_ `main`
+# and the branch itself.  On `main`, we blanket include all branches that might
+# want to be enabled, then particular branches can override it to exclude
+# themselves by removing themselves from the trigger list.  For example, old
+# stable branches can remove `stable/*` from their copy of this file once they
+# reach their end-of-life.
+name: Nightly Main tests
+on:
+  schedule:
+    - cron: "20 6 * * *"
+  workflow_dispatch:
+
+jobs:
+  nightly-tests:
+    # Nightly cron job.
+    #
+    # For this to run on a branch, the `schedules` trigger  up at the top of this
+    # file needs to match on _both_ `main` and the branch itself.
+    if: ${{ github.repository_owner == 'Qiskit'}}
+    uses: ./.github/workflows/on-nightly.yml
+  nightly-failure:
+    name: Create comment on failed test run
+    if: ${{ github.repository_owner == 'Qiskit' && failure() }}
+    uses: peter-evans/create-or-update-comment@v4
+    with:
+      issue-number: 7864
+      body: |
+        Nightly matrix test run failed at commit ${{ github.sha }}.
+
+        _Logs_: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}.
diff --git a/.github/workflows/on-merge-queue.yml b/.github/workflows/on-merge-queue.yml
new file mode 100644
index 000000000000..1544bf50f1e9
--- /dev/null
+++ b/.github/workflows/on-merge-queue.yml
@@ -0,0 +1,45 @@
+---
+# Merge queue.  A PR that reaches here has already passed the more rigorous PR
+# suite, so is very likely to pass.  The main reasons for failures here are
+# flaky VMs timing out (which we can't do much about), or a merge conflict
+# with another PR that is also in the merge queue.
+#
+# There's no reason to have multiple stages in this case, because we're
+# expecting it to pass.  Having more than one stage frustrates parallel
+# throughput in low-contention cases, and guarantees a longer critical path.
+name: Merge queue
+on:
+  merge_group:
+    branches: [main, "stable/*"]
+concurrency:
+  group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}-${{ github.workflow }}
+  cancel-in-progress: true
+
+jobs:
+  docs_lint:
+    if: github.repository_owner == 'Qiskit'
+    name: Docs and Lint
+    uses: ./.github/workflows/lint_docs.yml
+  test-linux:
+    if: github.repository_owner == 'Qiskit'
+    uses: ./.github/workflows/test-linux.yml
+    strategy:
+      matrix:
+        python-version: ["3.9", "3.13"]
+    with:
+      python-version: ${{ matrix.python-version }}
+      install-optionals: ${{ matrix.python-version == '3.9' }}
+      test-rust: ${{ matrix.python-version == '3.9' }}
+      test-images: ${{ matrix.python-version == '3.9' }}
+  test-mac:
+    if: github.repository_owner == 'Qiskit'
+    uses: ./.github/workflows/test-mac.yml
+    with:
+      python-version: "3.13"
+      install-optionals: false
+  test-windows:
+    if: github.repository_owner == 'Qiskit'
+    uses: ./.github/workflows/test-windows.yml
+    with:
+      python-version: "3.13"
+      install-optionals: false
diff --git a/.github/workflows/on-nightly.yml b/.github/workflows/on-nightly.yml
new file mode 100644
index 000000000000..a7f7166e80aa
--- /dev/null
+++ b/.github/workflows/on-nightly.yml
@@ -0,0 +1,36 @@
+---
+name: Nightly complete matrix tests
+on:
+  workflow_call:
+
+concurrency:
+  group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}
+  cancel-in-progress: true
+
+jobs:
+  nightly-linux:
+    uses: ./.github/workflows/test-linux
+    strategy:
+      matrix:
+        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+    with:
+      python-version: ${{ matrix.python-version }}
+      test-images: false
+      test-rust: false
+      install-optionals: true
+  nightly-mac:
+    uses: ./.github/workflows/test-mac
+    strategy:
+      matrix:
+        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+    with:
+      python-version: ${{ matrix.python-version }}
+      install-optionals: true
+  nightly-windows:
+    uses: ./.github/workflows/test-windows
+    strategy:
+      matrix:
+        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+    with:
+      python-version: ${{ matrix.python-version }}
+      install-optionals: true
diff --git a/.github/workflows/on-push.yml b/.github/workflows/on-push.yml
new file mode 100644
index 000000000000..5e08d1cf5a68
--- /dev/null
+++ b/.github/workflows/on-push.yml
@@ -0,0 +1,26 @@
+---
+# Push to main or the stable branches.  The triggering branches also need to
+# be in the triggers at the top of this file.
+name: Push
+on:
+  push:
+    branches: [main, "stable/*"]
+
+jobs:
+  tests-mac:
+    if: github.repository_owner == 'Qiskit'
+    uses: ./.github/workflows/test-mac
+    strategy:
+      matrix:
+        python-version: ["3.9", "3.13"]
+    with:
+      python-version: ${{ matrix.python-version }}
+      install-optionals: false
+  test-linux:
+    if: github.repository_owner == 'Qiskit'
+    uses: ./.github/workflows/test-mac
+    with:
+      python-version: "3.9"
+      test-rust: true
+      test-images: true
+      install-optionals: false

From 514afd9370ecd08304ea22fc7bd9d7381facea70 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <raynelfss@hotmail.com>
Date: Tue, 3 Dec 2024 14:24:06 -0500
Subject: [PATCH 18/25] Refactor: ci-workflow -> on-pull-request

---
 .github/workflows/{ci-config.yml => on-pull-request.yml} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename .github/workflows/{ci-config.yml => on-pull-request.yml} (100%)

diff --git a/.github/workflows/ci-config.yml b/.github/workflows/on-pull-request.yml
similarity index 100%
rename from .github/workflows/ci-config.yml
rename to .github/workflows/on-pull-request.yml

From 8a318dd456c71ae792cf7ffdc62c5be4cc11513f Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <raynelfss@hotmail.com>
Date: Tue, 3 Dec 2024 14:30:41 -0500
Subject: [PATCH 19/25] Remove: All azure workflow files

---
 .azure/test-linux.yml   | 225 ------------------------------------
 .azure/test-macos.yml   | 101 ----------------
 .azure/test-windows.yml | 108 -----------------
 azure-pipelines.yml     | 249 ----------------------------------------
 4 files changed, 683 deletions(-)
 delete mode 100644 .azure/test-linux.yml
 delete mode 100644 .azure/test-macos.yml
 delete mode 100644 .azure/test-windows.yml
 delete mode 100644 azure-pipelines.yml

diff --git a/.azure/test-linux.yml b/.azure/test-linux.yml
deleted file mode 100644
index a641ae215efd..000000000000
--- a/.azure/test-linux.yml
+++ /dev/null
@@ -1,225 +0,0 @@
-parameters:
-  - name: "pythonVersion"
-    type: string
-    displayName: "Version of Python to test"
-
-  - name: "testRust"
-    type: boolean
-
-  - name: "testImages"
-    type: boolean
-
-  - name: "installOptionals"
-    type: boolean
-    default: false
-
-  - name: "installFromSdist"
-    type: boolean
-    default: false
-
-jobs:
-  - job: "Linux_Tests_Python${{ replace(parameters.pythonVersion, '.', '') }}"
-    displayName: "Test Linux Rust & Python ${{ parameters.pythonVersion }}"
-    pool: {vmImage: 'ubuntu-latest'}
-
-    variables:
-      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
-      PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip
-      QISKIT_TEST_CAPTURE_STREAMS: 1
-      HAVE_VISUAL_TESTS_RUN: false
-
-    steps:
-      - task: UsePythonVersion@0
-        inputs:
-          versionSpec: '${{ parameters.pythonVersion }}'
-        name: 'usePython'
-        displayName: 'Use Python ${{ parameters.pythonVersion }}'
-
-      - task: Cache@2
-        inputs:
-          key: 'stestr | "$(Agent.OS)" | "${{ parameters.pythonVersion }}" | "$(Build.BuildNumber)"'
-          restoreKeys: |
-            stestr | "$(Agent.OS)" | "${{ parameters.pythonVersion }}"
-            stestr | "$(Agent.OS)"
-            stestr
-          path: .stestr
-        displayName: "Cache stestr"
-
-      - ${{ if eq(parameters.testRust, true) }}:
-        # We need to avoid linking our crates into full Python extension libraries during Rust-only
-        # testing because Rust/PyO3 can't handle finding a static CPython interpreter.
-        - bash: cargo test --no-default-features
-          env:
-            # On Linux we link against `libpython` dynamically, but it isn't written into the rpath
-            # of the test executable (I'm not 100% sure why ---Jake).  It's easiest just to forcibly
-            # include the correct place in the `dlopen` search path.
-            LD_LIBRARY_PATH: '$(usePython.pythonLocation)/lib:$LD_LIBRARY_PATH'
-          displayName: "Run Rust tests"
-
-      - bash: |
-          set -e
-          python -m pip install --upgrade pip setuptools wheel virtualenv
-          virtualenv test-job
-        displayName: "Prepare venv"
-
-      - ${{ if eq(parameters.installFromSdist, true) }}:
-        - bash: |
-            set -e
-            # Use stable Rust, rather than MSRV, to spot-check that stable builds properly.
-            rustup override set stable
-            source test-job/bin/activate
-            python -m pip install -U pip
-            python -m pip install -U build
-            python -m build --sdist .
-            python -m pip install -U \
-              -c constraints.txt \
-              -r requirements.txt \
-              -r requirements-dev.txt \
-              dist/qiskit-*.tar.gz
-            # Build and install both qiskit and qiskit-terra so that any optionals
-            # depending on `qiskit` will resolve correctly.
-          displayName: "Install Terra from sdist"
-
-      - ${{ if eq(parameters.installFromSdist, false) }}:
-        - bash: |
-            set -e
-            source test-job/bin/activate
-            python -m pip install -U \
-              -c constraints.txt \
-              -r requirements.txt \
-              -r requirements-dev.txt \
-              -e .
-            # Build and install both qiskit and qiskit-terra so that any optionals
-            # depending on `qiskit` will resolve correctly.
-          displayName: "Install Terra directly"
-
-      - ${{ if eq(parameters.installOptionals, true) }}:
-        - bash: |
-            set -e
-            source test-job/bin/activate
-            python -m pip install -r requirements-optional.txt -c constraints.txt
-            python -m pip check
-          displayName: "Install optional packages"
-
-        - bash: |
-            set -e
-            sudo apt-get update
-            sudo apt-get install -y graphviz
-          displayName: 'Install optional non-Python dependencies'
-
-      - bash: |
-          set -e
-          source test-job/bin/activate
-          python tools/report_numpy_state.py
-          mkdir -p /tmp/terra-tests
-          cp -r test /tmp/terra-tests/.
-          cp .stestr.conf /tmp/terra-tests/.
-          cp -r .stestr /tmp/terra-tests/. || :
-          pushd /tmp/terra-tests
-          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 4294967295))")
-          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
-          stestr run
-          popd
-        env:
-          QISKIT_PARALLEL: FALSE
-          RUST_BACKTRACE: 1
-        displayName: 'Run Python tests'
-
-      - bash: |
-          set -e
-          source test-job/bin/activate
-          cp tools/subunit_to_junit.py /tmp/terra-tests/.
-          python -m pip install -U junitxml
-          pushd /tmp/terra-tests
-          mkdir -p junit
-          stestr last --subunit | ./subunit_to_junit.py -o junit/test-results.xml
-          pushd .stestr
-          ls | grep -P "^\d" | xargs -d "\n" rm -f
-          popd
-          popd
-          cp -r /tmp/terra-tests/junit .
-          cp -r /tmp/terra-tests/.stestr .
-        displayName: 'Generate results'
-        condition: succeededOrFailed()
-
-      - task: PublishTestResults@2
-        condition: succeededOrFailed()
-        inputs:
-          testResultsFiles: '**/test-*.xml'
-          testRunTitle: 'Test results for Linux Python ${{ parameters.pythonVersion }}'
-
-      - task: CopyFiles@2
-        inputs:
-          contents: '**/*.png'
-          targetFolder: $(Build.ArtifactStagingDirectory)
-        displayName: 'Copy images on test failure'
-        condition: failed()
-
-      - task: PublishBuildArtifacts@1
-        inputs:
-          pathtoPublish: '$(Build.ArtifactStagingDirectory)'
-          artifactName: 'drop_linux'
-        displayName: 'Publish images on test failure'
-        condition: failed()
-
-      - ${{ if eq(parameters.testImages, true) }}:
-        - bash: |
-            set -e
-            virtualenv image_tests
-            image_tests/bin/python -m pip install -U \
-              -c constraints.txt \
-              -r requirements.txt \
-              -r requirements-dev.txt \
-              -r requirements-optional.txt \
-              -e .
-            sudo apt-get update
-            sudo apt-get install -y graphviz pandoc
-            image_tests/bin/pip check
-          displayName: 'Install dependencies'
-
-        - bash: |
-            echo "##vso[task.setvariable variable=HAVE_VISUAL_TESTS_RUN;]true"
-            image_tests/bin/python -m unittest discover -v test/visual
-          displayName: 'Run image test'
-          env:
-            # Needed to suppress a warning in jupyter-core 5.x by eagerly migrating to
-            # a new internal interface that will be the default in jupyter-core 6.x.
-            # This variable should become redundant on release of jupyter-core 6.
-            JUPYTER_PLATFORM_DIRS: 1
-
-        - task: ArchiveFiles@2
-          displayName: Archive visual test failure diffs
-          inputs:
-            rootFolderOrFile: 'test/visual/mpl/visual_test_failures'
-            includeRootFolder: false
-            archiveType: tar
-            archiveFile: '$(Build.ArtifactStagingDirectory)/visual_test_failures.tar.gz'
-            verbose: true
-          condition: and(failed(), eq(variables.HAVE_VISUAL_TESTS_RUN, 'true'))
-
-        - task: ArchiveFiles@2
-          displayName: Archive circuit results
-          inputs:
-            rootFolderOrFile: 'test/visual/mpl/circuit/circuit_results'
-            archiveType: tar
-            archiveFile: '$(Build.ArtifactStagingDirectory)/circuit_results.tar.gz'
-            verbose: true
-          condition: and(failed(), eq(variables.HAVE_VISUAL_TESTS_RUN, 'true'))
-
-        - task: ArchiveFiles@2
-          displayName: Archive graph results
-          inputs:
-            rootFolderOrFile: 'test/visual/mpl/graph/graph_results'
-            archiveType: tar
-            archiveFile: '$(Build.ArtifactStagingDirectory)/graph_results.tar.gz'
-            verbose: true
-          condition: and(failed(), eq(variables.HAVE_VISUAL_TESTS_RUN, 'true'))
-
-        - task: PublishBuildArtifacts@1
-          displayName: 'Publish image test failure diffs'
-          inputs:
-            pathtoPublish: '$(Build.ArtifactStagingDirectory)'
-            artifactName: 'image_test_failure_img_diffs'
-            Parallel: true
-            ParallelCount: 8
-          condition: and(failed(), eq(variables.HAVE_VISUAL_TESTS_RUN, 'true'))
diff --git a/.azure/test-macos.yml b/.azure/test-macos.yml
deleted file mode 100644
index 9e9620e8ecbb..000000000000
--- a/.azure/test-macos.yml
+++ /dev/null
@@ -1,101 +0,0 @@
-parameters:
-  - name: "pythonVersion"
-    type: string
-    displayName: "Version of Python to test"
-
-  - name: "installOptionals"
-    type: boolean
-    default: false
-
-jobs:
-  - job: "MacOS_Tests_Python${{ replace(parameters.pythonVersion, '.', '') }}"
-    displayName: "Test macOS Python ${{ parameters.pythonVersion }}"
-    pool: {vmImage: 'macOS-13'}
-
-    variables:
-      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
-      PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip
-      QISKIT_TEST_CAPTURE_STREAMS: 1
-
-    steps:
-      - task: UsePythonVersion@0
-        inputs:
-          versionSpec: '${{ parameters.pythonVersion }}'
-        displayName: 'Use Python ${{ parameters.pythonVersion }}'
-
-      - task: Cache@2
-        inputs:
-          key: 'stestr | "$(Agent.OS)" | "${{ parameters.pythonVersion }}" | "$(Build.BuildNumber)"'
-          restoreKeys: |
-            stestr | "$(Agent.OS)" | "${{ parameters.pythonVersion }}"
-            stestr | "$(Agent.OS)"
-            stestr
-          path: .stestr
-        displayName: "Cache stestr"
-
-      - bash: |
-          set -e
-          python -m pip install --upgrade pip setuptools wheel virtualenv
-          virtualenv test-job
-          source test-job/bin/activate
-          python -m pip install -U pip setuptools wheel
-          python -m pip install -U \
-            -c constraints.txt \
-            -r requirements.txt \
-            -r requirements-dev.txt \
-            -e .
-            # Build and install both qiskit and qiskit-terra so that any optionals
-            # depending on `qiskit` will resolve correctly.
-          pip check
-        displayName: 'Install dependencies'
-
-      - ${{ if eq(parameters.installOptionals, true) }}:
-        - bash: |
-            set -e
-            source test-job/bin/activate
-            pip install -r requirements-optional.txt -c constraints.txt
-          displayName: "Install optional packages"
-
-      - bash: |
-          set -e
-          source test-job/bin/activate
-          python tools/report_numpy_state.py
-          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 4294967295))")
-          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
-          stestr run
-        env:
-          QISKIT_PARALLEL: FALSE
-          RUST_BACKTRACE: 1
-        displayName: "Run tests"
-
-      - bash: |
-          set -e
-          source test-job/bin/activate
-          python -m pip install -U junitxml
-          mkdir -p junit
-          stestr last --subunit | tools/subunit_to_junit.py -o junit/test-results.xml
-          pushd .stestr
-          ls | grep -e '^[[:digit:]]' | xargs -n1 rm -f
-          popd
-        displayName: "Generate results"
-        condition: succeededOrFailed()
-
-      - task: PublishTestResults@2
-        condition: succeededOrFailed()
-        inputs:
-          testResultsFiles: '**/test-*.xml'
-          testRunTitle: 'Test results for macOS Python ${{ parameters.pythonVersion }}'
-
-      - task: CopyFiles@2
-        inputs:
-          contents: '**/*.png'
-          targetFolder: $(Build.ArtifactStagingDirectory)
-        displayName: 'Copy images on test failure'
-        condition: failed()
-
-      - task: PublishBuildArtifacts@1
-        inputs:
-          pathtoPublish: '$(Build.ArtifactStagingDirectory)'
-          artifactName: 'drop_macos'
-        displayName: 'Publish images on test failure'
-        condition: failed()
diff --git a/.azure/test-windows.yml b/.azure/test-windows.yml
deleted file mode 100644
index 8d86456bd72f..000000000000
--- a/.azure/test-windows.yml
+++ /dev/null
@@ -1,108 +0,0 @@
-parameters:
-  - name: "pythonVersion"
-    type: string
-    displayName: "Versions of Python to test"
-
-  - name: "installOptionals"
-    type: boolean
-    default: false
-
-jobs:
-  - job: "Windows_Tests_Python${{ replace(parameters.pythonVersion, '.', '') }}"
-    displayName: "Test Windows Python ${{ parameters.pythonVersion }}"
-    pool: {vmImage: 'windows-latest'}
-
-    variables:
-      QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
-      QISKIT_TEST_CAPTURE_STREAMS: 1
-
-    steps:
-      - task: UsePythonVersion@0
-        inputs:
-          versionSpec: '${{ parameters.pythonVersion }}'
-        displayName: 'Use Python ${{ parameters.pythonVersion }}'
-
-      - task: Cache@2
-        inputs:
-          key: 'stestr | "$(Agent.OS)" | "${{ parameters.pythonVersion }}" | "$(Build.BuildNumber)"'
-          restoreKeys: |
-            stestr | "$(Agent.OS)" | "${{ parameters.pythonVersion }}"
-            stestr | "$(Agent.OS)"
-            stestr
-          path: .stestr
-        displayName: Cache stestr
-
-      - bash: |
-          set -e
-          python -m pip install --upgrade pip setuptools wheel virtualenv
-          virtualenv test-job
-          source test-job/Scripts/activate
-          python -m pip install -U pip setuptools wheel
-          python -m pip install -U \
-            -c constraints.txt \
-            -r requirements.txt \
-            -r requirements-dev.txt \
-            -e .
-          # Build and install both qiskit and qiskit-terra so that any optionals
-          # depending on `qiskit` will resolve correctly.
-          pip check
-        displayName: 'Install dependencies'
-
-      - ${{ if eq(parameters.installOptionals, true) }}:
-        - bash: |
-            set -e
-            source test-job/Scripts/activate
-            pip install -c constraints.txt -r requirements-optional.txt
-            pip check
-          displayName: "Install optional packages"
-
-      - bash: |
-          set -e
-          chcp.com 65001
-          source test-job/Scripts/activate
-          python tools/report_numpy_state.py
-          export PYTHONHASHSEED=$(python -S -c "import random; print(random.randint(1, 1024))")
-          echo "PYTHONHASHSEED=$PYTHONHASHSEED"
-          stestr run
-        env:
-          LANG: 'C.UTF-8'
-          PYTHONIOENCODING: 'utf-8:backslashreplace'
-          QISKIT_PARALLEL: FALSE
-          RUST_BACKTRACE: 1
-        displayName: 'Run tests'
-
-      - bash: |
-          set -e
-          chcp.com 65001
-          source test-job/Scripts/activate
-          python -m pip install -U junitxml
-          mkdir -p junit
-          stestr last --subunit | python tools/subunit_to_junit.py -o junit/test-results.xml
-          pushd .stestr
-          ls | grep -P "^\d" | xargs -d "\n" rm -f
-          popd
-        condition: succeededOrFailed()
-        env:
-          LANG: 'C.UTF-8'
-          PYTHONIOENCODING: 'utf-8:backslashreplace'
-        displayName: 'Generate results'
-
-      - task: PublishTestResults@2
-        condition: succeededOrFailed()
-        inputs:
-          testResultsFiles: '**/test-*.xml'
-          testRunTitle: 'Test results for Windows Python ${{ parameters.pythonVersion }}'
-
-      - task: CopyFiles@2
-        condition: failed()
-        displayName: 'Copy images'
-        inputs:
-          contents: '**/*.png'
-          targetFolder: $(Build.ArtifactStagingDirectory)
-
-      - task: PublishBuildArtifacts@1
-        condition: failed()
-        displayName: 'Publish images'
-        inputs:
-          pathtoPublish: '$(Build.ArtifactStagingDirectory)'
-          artifactName: 'drop_windows'
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
deleted file mode 100644
index 94ed7d1fad7f..000000000000
--- a/azure-pipelines.yml
+++ /dev/null
@@ -1,249 +0,0 @@
-# Trigger types.  This needs to include all the triggers for the different
-# pipelines we might want to run.
-#
-# Each of these individually triggers the pipeline compilation step, but it's
-# the templating expressions in the `stages` list that actually set what runs.
-trigger:
-  branches:
-    include:
-      - 'main'
-      - 'stable/*'
-      - 'gh-readonly-queue/*'
-
-pr:
-  autoCancel: true
-  branches:
-    include:
-      - '*'
-
-# A schedule only runs on branches that match include rules from _both_ `main`
-# and the branch itself.  On `main`, we blanket include all branches that might
-# want to be enabled, then particular branches can override it to exclude
-# themselves by removing themselves from the trigger list.  For example, old
-# stable branches can remove `stable/*` from their copy of this file once they
-# reach their end-of-life.
-schedules:
-  - cron: "20 6 * * *"
-    displayName: "Complete matrix test"
-    branches:
-      include: [ "main", "stable/*" ]
-    always: false  # Only run if the code changed since the last cron sync.
-
-
-# Configuration.  In theory a manual trigger on the Azure website or embedding
-# this pipeline as a template can override these, but we're not interested in
-# that.  We just want to give names to things to make it easier to read.
-parameters:
-  - name: "supportedPythonVersions"
-    displayName: "All supported versions of Python"
-    type: object
-    default: ["3.9", "3.10", "3.11", "3.12", "3.13"]
-
-  - name: "minimumPythonVersion"
-    displayName: "Minimum supported version of Python"
-    type: string
-    default: "3.9"
-
-  - name: "maximumPythonVersion"
-    displayName: "Maximum supported version of Python"
-    type: string
-    default: "3.13"
-
-  # These two versions of Python can be chosen somewhat arbitrarily, but we get
-  # slightly better coverage per PR if they're neither the maximum nor minimum
-  # supported versions.
-
-  - name: "branchPushPythonVersion"
-    displayName: "Version of Python to run simple tests on pushes to protected branches"
-    type: string
-    default: "3.9"
-
-  # Sync with 'python-version' in '.github/workflows/docs_deploy.yml'.
-  - name: "documentationPythonVersion"
-    displayName: "Version of Python to use to build Sphinx documentation"
-    type: string
-    default: "3.9"
-
-# Conditional compilation logic.  This is all the logic for "what to run"; each
-# stage in turn delegates to various templates in ".azure" that provide the
-# information on "how to run" them.
-#
-# The conditional conditions use the template-expression syntax `${{ }}` so only
-# the relevant stages even appear in the job list.  The documentation on the
-# expression syntax is here:
-#
-#   https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops
-#
-# Not all variables are available at template-expansion time - this happens
-# before any machine is provisioned, so mostly you can access things from
-# GitHub, but nothing about the actual machine.  This is the list of variables
-# (look in the "available in templates" column):
-#
-#   https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml
-#
-# The main differentiator is `variables['Build.Reason']`, which contains the
-# trigger type:
-#   - cron (`Schedule`)
-#   - push to a git reference like a branch or tag (`IndividualCI`)
-#   - push to a pull request (`PullRequest`)
-# For `IndividualCI` (push/merge to a branch/tag on Qiskit/qiskit-terra), you
-# need to examine `variables['Build.SourceBranch']` to determine whether it's a
-# branch or a tag, and if a branch, then whether it's in the merge queue or a
-# push to a "real" branch.
-stages:
-  # Nightly cron job.
-  #
-  # For this to run on a branch, the `schedules` trigger  up at the top of this
-  # file needs to match on _both_ `main` and the branch itself.
-  - ${{ if eq(variables['Build.Reason'], 'Schedule') }}:
-    - stage: "Nightly"
-      displayName: "Nightly complete matrix tests"
-      jobs:
-        - ${{ each version in parameters.supportedPythonVersions }}:
-          - template: ".azure/test-linux.yml"
-            parameters:
-              pythonVersion: ${{ version }}
-              testImages: false
-              testRust: false
-              installOptionals: true
-
-          - template: ".azure/test-macos.yml"
-            parameters:
-              pythonVersion: ${{ version }}
-              installOptionals: true
-
-          - template: ".azure/test-windows.yml"
-            parameters:
-              pythonVersion: ${{ version }}
-              installOptionals: true
-
-    - stage: "Nightly_Failure"
-      displayName: "Comment on nightly failure"
-      dependsOn: "Nightly"
-      condition: failed()
-      pool: {vmImage: 'ubuntu-latest'}
-      jobs:
-        - job: "Comment"
-          steps:
-            - task: GitHubComment@0
-              inputs:
-                gitHubConnection: Qiskit
-                repositoryName: ${{ variables['Build.Repository.Name'] }}
-                id: 7864
-                comment: Nightly test job failed at commit $(Build.SourceVersion).  View the logs at $(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId).
-
-  # Full PR suite.  PRs need to pass this pipeline in order to be moved to the
-  # merge queue, where they'll use the next rule as the branch-protection rule
-  # for the final merge to the base branch.
-  - ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
-    # The preliminary stage should be small in both total runtime (including
-    # provisioning) and resources required.  About half of PR commits result in
-    # a CI failure, and over 90% of these are in linting, documention or a test
-    # failure that would affect _any_ OS or Python version.  The goal in the
-    # first stage is to catch the vast majority of failures with minimal cost.
-    - stage: "Lint_Docs_Prelim_Tests"
-      displayName: "Preliminary tests"
-      jobs:
-        - template: ".azure/lint_docs-linux.yml"
-          parameters:
-            pythonVersion: ${{ parameters.minimumPythonVersion }}
-
-        - template: ".azure/test-linux.yml"
-          parameters:
-            pythonVersion: ${{ parameters.minimumPythonVersion }}
-            # A PR is more likely to fail CI because it introduces a logic error
-            # into an existing test than because it adds a new test / optional
-            # dependency that isn't accounted for in the test-skipping logic
-            # (and such a failure would need fewer iterations to fix).  We want
-            # to fail fast in the first CI stage.
-            installOptionals: true
-            testRust: true
-            testImages: true
-
-    # The rest of the PR pipeline is to test the oldest and newest supported
-    # versions of Python. It's very rare for a failure to be specific to an
-    # intermediate version of Python, so we just catch those in the cron-job
-    # pipeline to reduce the amount of resources used.
-    - stage: "Tests"
-      displayName: "Main tests"
-      dependsOn: "Lint_Docs_Prelim_Tests"
-      jobs:
-        - template: ".azure/test-linux.yml"
-          parameters:
-            pythonVersion: ${{ parameters.maximumPythonVersion }}
-            testRust: false
-            testImages: false
-            installFromSdist: true
-            installOptionals: false
-
-        - template: ".azure/test-macos.yml"
-          parameters:
-            pythonVersion: ${{ parameters.minimumPythonVersion }}
-            installOptionals: true
-
-        - template: ".azure/test-macos.yml"
-          parameters:
-            pythonVersion: ${{ parameters.maximumPythonVersion }}
-            installOptionals: false
-
-        - template: ".azure/test-windows.yml"
-          parameters:
-            pythonVersion: ${{ parameters.minimumPythonVersion }}
-            installOptionals: true
-
-        - template: ".azure/test-windows.yml"
-          parameters:
-            pythonVersion: ${{ parameters.maximumPythonVersion }}
-            installOptionals: false
-
-  # Merge queue.  A PR that reaches here has already passed the more rigorous PR
-  # suite, so is very likely to pass.  The main reasons for failures here are
-  # flaky VMs timing out (which we can't do much about), or a merge conflict
-  # with another PR that is also in the merge queue.
-  #
-  # There's no reason to have multiple stages in this case, because we're
-  # expecting it to pass.  Having more than one stage frustrates parallel
-  # throughput in low-contention cases, and guarantees a longer critical path.
-  - ${{ if and(eq(variables['Build.Reason'], 'IndividualCI'), contains(variables['Build.SourceBranch'], 'gh-readonly-queue')) }}:
-    - stage: "Merge_Queue"
-      displayName: "Merge queue"
-      jobs:
-        - template: ".azure/lint_docs-linux.yml"
-          parameters:
-            pythonVersion: ${{ parameters.minimumPythonVersion }}
-
-        - template: ".azure/test-linux.yml"
-          parameters:
-            pythonVersion: ${{ parameters.minimumPythonVersion }}
-            installOptionals: true
-            testRust: true
-            testImages: true
-
-        - template: ".azure/test-linux.yml"
-          parameters:
-            pythonVersion: ${{ parameters.maximumPythonVersion }}
-            installOptionals: false
-            testRust: false
-            testImages: false
-
-        - template: ".azure/test-macos.yml"
-          parameters:
-            pythonVersion: ${{ parameters.maximumPythonVersion }}
-            installOptionals: false
-
-        - template: ".azure/test-windows.yml"
-          parameters:
-            pythonVersion: ${{ parameters.maximumPythonVersion }}
-            installOptionals: false
-
-  # Push to main or the stable branches.  The triggering branches also need to
-  # be in the triggers at the top of this file.
-  - ${{ if and(eq(variables['Build.Reason'], 'IndividualCI'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/stable/'))) }}:
-    - stage: "Push"
-      jobs:
-        - template: ".azure/test-linux.yml"
-          parameters:
-            pythonVersion: ${{ parameters.branchPushPythonVersion }}
-            testRust: true
-            testImages: true
-            installOptionals: false

From 3c9e7535ff19d2b4b9f6bc1f6e17598eb0c069f3 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <raynelfss@hotmail.com>
Date: Tue, 3 Dec 2024 14:36:35 -0500
Subject: [PATCH 20/25] Fix: Use runner for issue comment - Add missing `.yml`
 extension in reusable workflow references.

---
 .github/workflows/nightly.yml    | 14 ++++++++------
 .github/workflows/on-nightly.yml |  6 +++---
 .github/workflows/on-push.yml    |  4 ++--
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index b7592e6d5233..84df18714f37 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -22,10 +22,12 @@ jobs:
   nightly-failure:
     name: Create comment on failed test run
     if: ${{ github.repository_owner == 'Qiskit' && failure() }}
-    uses: peter-evans/create-or-update-comment@v4
-    with:
-      issue-number: 7864
-      body: |
-        Nightly matrix test run failed at commit ${{ github.sha }}.
+    runs-on: ubuntu-latest
+    steps:
+      - uses: peter-evans/create-or-update-comment@v4
+        with:
+          issue-number: 7864
+          body: |
+            Nightly matrix test run failed at commit ${{ github.sha }}.
 
-        _Logs_: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}.
+            _Logs_: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}.
diff --git a/.github/workflows/on-nightly.yml b/.github/workflows/on-nightly.yml
index a7f7166e80aa..4fdfd8105d5f 100644
--- a/.github/workflows/on-nightly.yml
+++ b/.github/workflows/on-nightly.yml
@@ -9,7 +9,7 @@ concurrency:
 
 jobs:
   nightly-linux:
-    uses: ./.github/workflows/test-linux
+    uses: ./.github/workflows/test-linux.yml
     strategy:
       matrix:
         python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
@@ -19,7 +19,7 @@ jobs:
       test-rust: false
       install-optionals: true
   nightly-mac:
-    uses: ./.github/workflows/test-mac
+    uses: ./.github/workflows/test-mac.yml
     strategy:
       matrix:
         python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
@@ -27,7 +27,7 @@ jobs:
       python-version: ${{ matrix.python-version }}
       install-optionals: true
   nightly-windows:
-    uses: ./.github/workflows/test-windows
+    uses: ./.github/workflows/test-windows.yml
     strategy:
       matrix:
         python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
diff --git a/.github/workflows/on-push.yml b/.github/workflows/on-push.yml
index 5e08d1cf5a68..0d107a40b35e 100644
--- a/.github/workflows/on-push.yml
+++ b/.github/workflows/on-push.yml
@@ -9,7 +9,7 @@ on:
 jobs:
   tests-mac:
     if: github.repository_owner == 'Qiskit'
-    uses: ./.github/workflows/test-mac
+    uses: ./.github/workflows/test-mac.yml
     strategy:
       matrix:
         python-version: ["3.9", "3.13"]
@@ -18,7 +18,7 @@ jobs:
       install-optionals: false
   test-linux:
     if: github.repository_owner == 'Qiskit'
-    uses: ./.github/workflows/test-mac
+    uses: ./.github/workflows/test-linux.yml
     with:
       python-version: "3.9"
       test-rust: true

From 9cbf7fca164661554cd553bfb2242d8bd3ec674b Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <raynelfss@hotmail.com>
Date: Tue, 10 Dec 2024 14:31:56 -0500
Subject: [PATCH 21/25] Fix: Wrong name in MacOS tests

---
 .github/workflows/test-mac.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test-mac.yml b/.github/workflows/test-mac.yml
index 703f0a0964e1..f6f694af35e4 100644
--- a/.github/workflows/test-mac.yml
+++ b/.github/workflows/test-mac.yml
@@ -1,5 +1,5 @@
 ---
-name: Test Windows
+name: Test MacOS
 on:
   workflow_call:
     inputs:

From e345893c156440998d82b638c57ca21e4950c5d3 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Sat, 25 Jan 2025 13:24:43 -0500
Subject: [PATCH 22/25] Test: Remove main repository requirement - For testing
 purposes.

---
 .github/workflows/lint_docs.yml       |  2 +-
 .github/workflows/nightly.yml         |  5 +++--
 .github/workflows/on-merge-queue.yml  |  8 ++++----
 .github/workflows/on-pull-request.yml | 10 +++++-----
 .github/workflows/on-push.yml         |  4 ++--
 .github/workflows/test-linux.yml      |  2 +-
 .github/workflows/test-mac.yml        |  2 +-
 .github/workflows/test-windows.yml    |  2 +-
 8 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/.github/workflows/lint_docs.yml b/.github/workflows/lint_docs.yml
index 2636a24b0ea4..28ed57988ca4 100644
--- a/.github/workflows/lint_docs.yml
+++ b/.github/workflows/lint_docs.yml
@@ -9,7 +9,7 @@ concurrency:
   cancel-in-progress: true
 jobs:
   docs:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: Docs
     runs-on: ubuntu-latest
     strategy:
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 84df18714f37..2166bd04151b 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -17,11 +17,12 @@ jobs:
     #
     # For this to run on a branch, the `schedules` trigger  up at the top of this
     # file needs to match on _both_ `main` and the branch itself.
-    if: ${{ github.repository_owner == 'Qiskit'}}
+    # if: ${{ github.repository_owner == 'Qiskit'}}
     uses: ./.github/workflows/on-nightly.yml
   nightly-failure:
     name: Create comment on failed test run
-    if: ${{ github.repository_owner == 'Qiskit' && failure() }}
+    # if: ${{ github.repository_owner == 'Qiskit' && failure() }}
+    if: ${{ failure() }}
     runs-on: ubuntu-latest
     steps:
       - uses: peter-evans/create-or-update-comment@v4
diff --git a/.github/workflows/on-merge-queue.yml b/.github/workflows/on-merge-queue.yml
index 1544bf50f1e9..488a865903e4 100644
--- a/.github/workflows/on-merge-queue.yml
+++ b/.github/workflows/on-merge-queue.yml
@@ -17,11 +17,11 @@ concurrency:
 
 jobs:
   docs_lint:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: Docs and Lint
     uses: ./.github/workflows/lint_docs.yml
   test-linux:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     uses: ./.github/workflows/test-linux.yml
     strategy:
       matrix:
@@ -32,13 +32,13 @@ jobs:
       test-rust: ${{ matrix.python-version == '3.9' }}
       test-images: ${{ matrix.python-version == '3.9' }}
   test-mac:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     uses: ./.github/workflows/test-mac.yml
     with:
       python-version: "3.13"
       install-optionals: false
   test-windows:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     uses: ./.github/workflows/test-windows.yml
     with:
       python-version: "3.13"
diff --git a/.github/workflows/on-pull-request.yml b/.github/workflows/on-pull-request.yml
index 723cb622c64d..b75df7d704fa 100644
--- a/.github/workflows/on-pull-request.yml
+++ b/.github/workflows/on-pull-request.yml
@@ -18,13 +18,13 @@ jobs:
   # failure that would affect _any_ OS or Python version.  The goal in the
   # first stage is to catch the vast majority of failures with minimal cost.
   lint-docs:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: Docs and Lint
     uses: ./.github/workflows/lint_docs.yml
   preliminary-tests:
     name: Preliminary Tests
     uses: ./.github/workflows/test-linux.yml
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     with:
       python-version: "3.9"
       # A PR is more likely to fail CI because it introduces a logic error
@@ -41,7 +41,7 @@ jobs:
   # intermediate version of Python, so we just catch those in the cron-job
   # pipeline to reduce the amount of resources used.
   main-tests-ubuntu:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: Main Tests (ubuntu-latest)
     needs: [lint-docs, preliminary-tests]
     strategy:
@@ -56,7 +56,7 @@ jobs:
       install-optionals: false
 
   main-tests-mac:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: Main Tests (macos)
     needs: [lint-docs, preliminary-tests]
     strategy:
@@ -68,7 +68,7 @@ jobs:
       install-optionals: ${{ matrix.python_version == '3.9'}}
 
   main-tests-windows:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: Main Tests (windows-latest)
     needs: [lint-docs, preliminary-tests]
     strategy:
diff --git a/.github/workflows/on-push.yml b/.github/workflows/on-push.yml
index 0d107a40b35e..219cd118a685 100644
--- a/.github/workflows/on-push.yml
+++ b/.github/workflows/on-push.yml
@@ -8,7 +8,7 @@ on:
 
 jobs:
   tests-mac:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     uses: ./.github/workflows/test-mac.yml
     strategy:
       matrix:
@@ -17,7 +17,7 @@ jobs:
       python-version: ${{ matrix.python-version }}
       install-optionals: false
   test-linux:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     uses: ./.github/workflows/test-linux.yml
     with:
       python-version: "3.9"
diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index de30f91b79df..823cc1e1d134 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -34,7 +34,7 @@ on:
 
 jobs:
   tests-linux:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: ubuntu-latest-tests-Python-${{ inputs.python-version }}
     runs-on: ubuntu-latest
     env:
diff --git a/.github/workflows/test-mac.yml b/.github/workflows/test-mac.yml
index f6f694af35e4..408ee004e228 100644
--- a/.github/workflows/test-mac.yml
+++ b/.github/workflows/test-mac.yml
@@ -19,7 +19,7 @@ on:
 
 jobs:
   tests-mac:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: macOS-arm64-tests-Python-${{ inputs.python-version }}
     runs-on: macOS-14
     env:
diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml
index 48d1a33f06a7..6f31924c7f4e 100644
--- a/.github/workflows/test-windows.yml
+++ b/.github/workflows/test-windows.yml
@@ -19,7 +19,7 @@ on:
 
 jobs:
   test-windows:
-    if: github.repository_owner == 'Qiskit'
+    # if: github.repository_owner == 'Qiskit'
     name: windows-latest-tests-Python-${{ inputs.python-version }}
     runs-on: windows-latest
     env:

From c17272147ab5de55f512e7b8875e37d45de083f4 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Wed, 26 Mar 2025 12:49:18 -0400
Subject: [PATCH 23/25] Fix: Adapt to latest changes - Format documents

---
 .github/workflows/lint_docs.yml    | 70 +++++++++++++++---------------
 .github/workflows/test-linux.yml   | 21 ++++-----
 .github/workflows/test-mac.yml     |  1 +
 .github/workflows/test-windows.yml |  1 +
 4 files changed, 48 insertions(+), 45 deletions(-)

diff --git a/.github/workflows/lint_docs.yml b/.github/workflows/lint_docs.yml
index 28ed57988ca4..6f906ed7b910 100644
--- a/.github/workflows/lint_docs.yml
+++ b/.github/workflows/lint_docs.yml
@@ -2,7 +2,6 @@
 name: Lint and Docs
 on:
   workflow_call:
-    
 
 concurrency:
   group: ${{ github.repository }}-${{ github.ref }}-${{ github.head_ref }}-${{ github.workflow }}
@@ -15,27 +14,29 @@ jobs:
     strategy:
       fail-fast: true
     steps:
-    - uses: actions/checkout@v4
-      with:
-        # We need to fetch the whole history so 'reno' can do its job and we can inspect tags.
-        fetch-depth: 0
-    - name: Set up Python
-      uses: actions/setup-python@v5
-      with:
-        python-version: '3.9'
-    - name: Install ubuntu docs dependencies
-      run: tools/install_ubuntu_docs_dependencies.sh
-    - name: Run docs
-      run: tox -e docs
-    - name: Clean up docs detritus
-      run: rm -rf docs/_build/html/{.doctrees,.buildinfo}
-    - name: Store built documentation artifact
-      uses: actions/upload-artifact@v4
-      with:
-        name: qiskit-docs
-        path: |
-          ./docs/_build/html/*
-        if-no-files-found: error
+      - uses: actions/checkout@v4
+        with:
+          # We need to fetch the whole history so 'reno' can do its job and we can inspect tags.
+          fetch-depth: 0
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: "3.9"
+      - name: Install ubuntu docs dependencies
+        run: tools/install_ubuntu_docs_dependencies.sh
+      - name: Run docs
+        run: |
+          make cformat
+          tox -e docs
+      - name: Clean up docs detritus
+        run: rm -rf docs/_build/html/{.doctrees,.buildinfo}
+      - name: Store built documentation artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: qiskit-docs
+          path: |
+            ./docs/_build/html/*
+          if-no-files-found: error
   lint:
     if: github.repository_owner == 'Qiskit'
     name: Lint
@@ -43,16 +44,15 @@ jobs:
     strategy:
       fail-fast: true
     steps:
-    - uses: actions/checkout@v4
-      with:
-        # We need to fetch the whole history so 'reno' can do its job and we can inspect tags.
-        fetch-depth: 0
-    - name: Set up Python
-      uses: actions/setup-python@v5
-      with:
-        python-version: '3.9'
-    - name: Install ubuntu docs dependencies
-      run: tools/install_ubuntu_docs_dependencies.sh
-    - name: Run lint
-      run: tox -e lint
-        
\ No newline at end of file
+      - uses: actions/checkout@v4
+        with:
+          # We need to fetch the whole history so 'reno' can do its job and we can inspect tags.
+          fetch-depth: 0
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: "3.9"
+      - name: Install ubuntu docs dependencies
+        run: tools/install_ubuntu_docs_dependencies.sh
+      - name: Run lint
+        run: tox -e lint
diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index 823cc1e1d134..d25fc5e2538a 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -44,6 +44,8 @@ jobs:
       HAVE_VISUAL_TESTS_RUN: false
     strategy:
       fail-fast: false
+      matrix:
+        os: ["ubuntu-latest", "ubuntu-24.04-arm"]
     steps:
       - uses: actions/checkout@v4
       - name: Install Rust toolchain
@@ -63,16 +65,6 @@ jobs:
             stestr | "${{ runner.os }}"
             stestr
           path: .stestr
-      - name: Run Rust Tests
-        if: inputs.test-rust == true
-        # We need to avoid linking our crates into full Python extension libraries during Rust-only
-        # testing because Rust/PyO3 can't handle finding a static CPython interpreter.
-        run: cargo test --no-default-features
-        env:
-          # On Linux we link against `libpython` dynamically, but it isn't written into the rpath
-          # of the test executable (I'm not 100% sure why ---Jake).  It's easiest just to forcibly
-          # include the correct place in the `dlopen` search path.
-          LD_LIBRARY_PATH: "${{ steps.python-outputs.outputs.python-path }}/lib:${{env.LD_LIBRARY_PATH}}"
       - name: Prepare venv
         run: |
           set -e
@@ -120,6 +112,14 @@ jobs:
           sudo apt-get update
           sudo apt-get install -y graphviz
         if: ${{ inputs.install-optionals }}
+      - name: Run Rust Tests
+        if: inputs.test-rust == true
+        # Note that we use the virtual env with Qiskit installed to run the Rust
+        # tests since some of them still depend on Qiskit's Python API via PyO3.
+        run: |
+          source test-job/bin/activate
+          python tools/report_numpy_state.py
+          python tools/run_cargo_test.py
       - name: Run Python tests
         run: |
           set -e
@@ -136,6 +136,7 @@ jobs:
           popd
         env:
           QISKIT_PARALLEL: FALSE
+          QISKIT_IGNORE_USER_SETTINGS: TRUE
           RUST_BACKTRACE: 1
       - name: Install Image dependencies
         run: |
diff --git a/.github/workflows/test-mac.yml b/.github/workflows/test-mac.yml
index 408ee004e228..9c1157bf2e22 100644
--- a/.github/workflows/test-mac.yml
+++ b/.github/workflows/test-mac.yml
@@ -78,6 +78,7 @@ jobs:
           stestr run
         env:
           QISKIT_PARALLEL: FALSE
+          QISKIT_IGNORE_USER_SETTINGS: TRUE
           RUST_BACKTRACE: 1
       - name: Copy and Publish images
         uses: actions/upload-artifact@v4
diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml
index 6f31924c7f4e..8fa52ea666eb 100644
--- a/.github/workflows/test-windows.yml
+++ b/.github/workflows/test-windows.yml
@@ -78,6 +78,7 @@ jobs:
           LANG: "C.UTF-8"
           PYTHONIOENCODING: "utf-8:backslashreplace"
           QISKIT_PARALLEL: FALSE
+          QISKIT_IGNORE_USER_SETTINGS: TRUE
           RUST_BACKTRACE: 1
       - name: Copy and Publish images
         uses: actions/upload-artifact@v4

From f0b5941cafecfcd5797a56c3b8e99bbf09040e34 Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Wed, 26 Mar 2025 12:51:06 -0400
Subject: [PATCH 24/25] Fix: Use matrix.os in test-linux

---
 .github/workflows/test-linux.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index d25fc5e2538a..51be47058e94 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -36,7 +36,7 @@ jobs:
   tests-linux:
     # if: github.repository_owner == 'Qiskit'
     name: ubuntu-latest-tests-Python-${{ inputs.python-version }}
-    runs-on: ubuntu-latest
+    runs-on: ${{ matrix.os }}
     env:
       QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y
       PIP_CACHE_DIR: ${{ github.workspace }}/.pip

From 70516915fbda3d53a17214c84ef397929bda7bef Mon Sep 17 00:00:00 2001
From: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
Date: Wed, 26 Mar 2025 12:55:32 -0400
Subject: [PATCH 25/25] Fix: Naming in test-linux

---
 .github/workflows/test-linux.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index 51be47058e94..5e814a8adde7 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -35,7 +35,7 @@ on:
 jobs:
   tests-linux:
     # if: github.repository_owner == 'Qiskit'
-    name: ubuntu-latest-tests-Python-${{ inputs.python-version }}
+    name: ${{ matrix.os }}-tests-Python-${{ inputs.python-version }}
     runs-on: ${{ matrix.os }}
     env:
       QISKIT_SUPPRESS_PACKAGING_WARNINGS: Y