diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 3777927445..0000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,66 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/2.0/configuration-reference -version: 2.1 -parameters: - GHA_Actor: - type: string - default: "" - GHA_Action: - type: string - default: "" - GHA_Event: - type: string - default: "" - GHA_Meta: - type: string - default: "" - -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/2.0/configuration-reference/#jobs -jobs: - linux-arm-wheels: - working_directory: ~/linux-wheels - machine: - image: ubuntu-2204:current - docker_layer_caching: true - - resource_class: arm.medium - - environment: - # these environment variables will be passed to the docker container - - CIBW_ARCHS: aarch64 - - CIBW_MANYLINUX_AARCH64_IMAGE: manylinux2014_base_aarch64 - - CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: manylinux2014_base_aarch64 - - steps: - - checkout - - run: - name: Build the aarch64 base image (and cache it) - working_directory: buildconfig/manylinux-build/docker_base - command: docker build -t manylinux2014_base_aarch64 -f Dockerfile-aarch64 . - - - run: - name: Build the Linux wheels. - command: | - pip3 install --user cibuildwheel==2.22.0 - PATH="$HOME/.local/bin:$PATH" cibuildwheel --output-dir wheelhouse - - - store_artifacts: - path: wheelhouse/ - -# Invoke jobs via workflows -# See: https://circleci.com/docs/2.0/configuration-reference/#workflows -workflows: - build-arm: - when: - equal: [ "", << pipeline.parameters.GHA_Actor >> ] - jobs: - - linux-arm-wheels - - # run a separate, identical release job only if triggered - build-arm-release: - when: - not: - equal: [ "", << pipeline.parameters.GHA_Actor >> ] - jobs: - - linux-arm-wheels diff --git a/.gitattributes b/.gitattributes index b6e8cb8199..8e51994dff 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,8 +1,6 @@ # define files/directories that won't be exported in an sdist # Keep in sync with MANIFEST.in -.circleci/ export-ignore .github/ export-ignore -buildconfig/ci/ export-ignore buildconfig/macdependencies/ export-ignore buildconfig/manylinux-build/ export-ignore diff --git a/.github/workflows/build-manylinux.yml b/.github/workflows/build-manylinux.yml index b24aabda05..a51fa681b7 100644 --- a/.github/workflows/build-manylinux.yml +++ b/.github/workflows/build-manylinux.yml @@ -38,7 +38,7 @@ concurrency: jobs: build: name: ${{ matrix.arch }} - runs-on: ubuntu-24.04 + runs-on: ${{ matrix.arch == 'aarch64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} permissions: contents: read packages: write @@ -46,7 +46,7 @@ jobs: strategy: fail-fast: false # if a particular matrix build fails, don't skip the rest matrix: - arch: [x86_64, i686] + arch: [x86_64, i686, aarch64] env: CIBW_ARCHS: ${{ matrix.arch }} @@ -90,6 +90,8 @@ jobs: CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ghcr.io/${{ github.repository }}_x86_64:${{ steps.meta.outputs.version }} CIBW_MANYLINUX_I686_IMAGE: ghcr.io/${{ github.repository }}_i686:${{ steps.meta.outputs.version }} CIBW_MANYLINUX_PYPY_I686_IMAGE: ghcr.io/${{ github.repository }}_i686:${{ steps.meta.outputs.version }} + CIBW_MANYLINUX_AARCH64_IMAGE: ghcr.io/${{ github.repository }}_aarch64:${{ steps.meta.outputs.version }} + CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ghcr.io/${{ github.repository }}_aarch64:${{ steps.meta.outputs.version }} uses: pypa/cibuildwheel@v2.22.0 diff --git a/.github/workflows/release-gh-draft.yml b/.github/workflows/release-gh-draft.yml index 0f5acc8f22..935f6f6745 100644 --- a/.github/workflows/release-gh-draft.yml +++ b/.github/workflows/release-gh-draft.yml @@ -5,18 +5,6 @@ on: branches: 'release/**' jobs: - manylinux-aarch64: - runs-on: ubuntu-latest - outputs: - pipeline_id: ${{ steps.circleci.outputs.id }} - - steps: - - name: Trigger CircleCI builds on release - id: circleci - uses: CircleCI-Public/trigger-circleci-pipeline-action@v1.2.0 - env: - CCI_TOKEN: ${{ secrets.CCI_TOKEN }} - manylinux: uses: ./.github/workflows/build-manylinux.yml @@ -46,14 +34,6 @@ jobs: path: pygame-wheels merge-multiple: true - - name: Download manylinux-aarch64 artifacts from CircleCI - continue-on-error: true # incase things don't work here, can manually handle it - run: > - python3 buildconfig/ci/circleci/pull_circleci_artifacts.py - ${{ secrets.CCI_TOKEN }} - ${{ needs.manylinux-aarch64.outputs.pipeline_id }} - pygame-wheels - # Strips 'release/' from the ref_name, this helps us access the version # name as 'steps.ver.outputs.VER' - name: Get version diff --git a/buildconfig/MANIFEST.in b/buildconfig/MANIFEST.in index b46eb7e695..9f9eab0c71 100644 --- a/buildconfig/MANIFEST.in +++ b/buildconfig/MANIFEST.in @@ -5,7 +5,6 @@ recursive-include src_c * recursive-include examples * recursive-include test * -recursive-exclude buildconfig/ci * recursive-exclude buildconfig/manylinux-build * recursive-exclude buildconfig/macdependencies * recursive-exclude buildconfig/stubs/.mypy_cache * diff --git a/buildconfig/ci/circleci/pull_circleci_artifacts.py b/buildconfig/ci/circleci/pull_circleci_artifacts.py deleted file mode 100644 index 43494ae66a..0000000000 --- a/buildconfig/ci/circleci/pull_circleci_artifacts.py +++ /dev/null @@ -1,138 +0,0 @@ -""" -A script to automate downloading CircleCI artifacts. - -Usage: python3 pull_circleci_artifacts.py - TOKEN: - CircleCI "personal access token" of a github (preferably machine) user. - This is secret! - - PIPELINE_ID: - A unique string id that represents the CircleCI pipeline, whose artifacts this - script pulls. - This pipeline must have exactly one workflow and that workflow must have exactly - one job. This script waits for the pipeline to finish, and pulls artifacts from - this job. If the pipeline isn't successful on finish, this script exits with an - error. - - SAVE_DIR: - The downloaded artifacts are saved to this directory - -CircleCI API docs: https://circleci.com/docs/api/v2/index.html (useful for understanding -this code) -""" - -# yup, all these are stdlib modules incase you are wondering -import concurrent.futures -import http.client -import json -import sys -import time -from pathlib import Path -from urllib import request - -_, token, pipeline_id, save_dir = sys.argv - -headers = {"Circle-Token": token} -save_dir = Path(save_dir) - -print( - f"Starting for {pipeline_id = } (and {save_dir = }), now establishing connection..." -) - -cci_api = http.client.HTTPSConnection("circleci.com") - - -def paginate_get_items_and_next(url, next_page=""): - """ - Helper to get "items" and "next_page_token" from CircleCI API, used to handle - pagination. - """ - - # page-token is used for pagination. Initially, it is unspecified. - url_query = f"{url}?page-token={next_page}" if next_page else url - cci_api.request("GET", f"/api/v2/{url_query}", headers=headers) - response = cci_api.getresponse() - if response.status != 200: - raise RuntimeError( - f"Request to '{url}' not successful: {response.status} ({response.reason})" - ) - - response_dict = json.loads(response.read()) - if "message" in response_dict: - raise RuntimeError( - f"Request to '{url}' failed with message - {response_dict['message']}" - ) - - return response_dict["items"], response_dict["next_page_token"] - - -def paginate_get_single_item(url): - """ - Helper to get exactly one item from CircleCI paginated APIs - """ - items, _ = paginate_get_items_and_next(url) - if len(items) != 1: - raise RuntimeError(f"Expected one item, got {len(items)}") - - return items[0] - - -def paginate_get_all_items(url): - """ - Helper to get all "items" from CircleCI paginated APIs - """ - prev_page_tag = "" - while True: - items, prev_page_tag = paginate_get_items_and_next(url, prev_page_tag) - if not items: - # all artifacts are probably downloaded at this point - break - - yield from items - if not prev_page_tag: - # done with pagination, exit - break - - -def download_artifact(artifact): - """ - Helper to download an artifact given an "artifact dict". This can be concurrently - called in multiple threads to speed up downloads. - """ - path = Path(artifact["path"]) - save_path = save_dir / path.name - print(f"Downloading {path.name}") - request.urlretrieve(artifact["url"], save_path) - print(f"Done with saving {path.name}") - - -cnt = 1 -while True: - print(f"\nAttempt {cnt}") - workflow = paginate_get_single_item(f"/pipeline/{pipeline_id}/workflow") - if workflow["status"] != "running": - if workflow["status"] != "success": - # workflow failed - raise RuntimeError(f"The workflow has status '{workflow['status']}'") - - # successfully finished workflow at this point - job = paginate_get_single_item(f"/workflow/{workflow['id']}/job") - - # shouldn't really happen, but test anyways - if job["status"] != "success": - raise RuntimeError(f"The job has status '{workflow['status']}'") - - print(f"Downloading artifacts (they will all be saved in {str(save_dir)})") - with concurrent.futures.ThreadPoolExecutor() as pool: - pool.map( - download_artifact, - paginate_get_all_items( - f"/project/{job['project_slug']}/{job['job_number']}/artifacts" - ), - ) - - break - - cnt += 1 - print("Job is still running (now sleeping for 30s before retrying)") - time.sleep(30)