From 384b8710c339ea0826a16c36dd69482db9aba5c1 Mon Sep 17 00:00:00 2001 From: Adrian Moennich Date: Sat, 23 Mar 2024 21:04:43 +0100 Subject: [PATCH] ci: Build wheels for plugins --- .github/utils/generate_matrix.py | 34 ++++++++++ .github/utils/get_core_repo.py | 8 ++- .github/workflows/build.yml | 109 +++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 .github/utils/generate_matrix.py create mode 100644 .github/workflows/build.yml diff --git a/.github/utils/generate_matrix.py b/.github/utils/generate_matrix.py new file mode 100644 index 00000000..ae01dd59 --- /dev/null +++ b/.github/utils/generate_matrix.py @@ -0,0 +1,34 @@ +# This file is part of the Indico plugins. +# Copyright (C) 2002 - 2024 CERN +# +# The Indico plugins are free software; you can redistribute +# them and/or modify them under the terms of the MIT License; +# see the LICENSE file for more details. + +import json +import os +import sys +from operator import itemgetter +from pathlib import Path + + +def _plugin_has_assets(plugin_dir: Path): + return (plugin_dir / 'webpack.config.js').exists() or (plugin_dir / 'webpack-bundles.json').exists() + + +def main(): + plugin_data = sorted(({'plugin': x.name, 'assets': _plugin_has_assets(x)} for x in Path().iterdir() + if x.name != '_meta' and x.is_dir() and (x / 'setup.cfg').exists()), key=itemgetter('plugin')) + + # TODO remove after initial testing + plugin_data = [x for x in plugin_data if x['plugin'] in {'cloud_captchas', 'storage_s3'}] + print(plugin_data) + + matrix = {'include': plugin_data} + with open(os.environ['GITHUB_OUTPUT'], 'a') as f: + f.write(f'PLUGINS_MATRIX={json.dumps(matrix)}\n') + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/.github/utils/get_core_repo.py b/.github/utils/get_core_repo.py index 9c7bea8b..d9a09002 100644 --- a/.github/utils/get_core_repo.py +++ b/.github/utils/get_core_repo.py @@ -90,9 +90,11 @@ def main(): print(f'Uncommon branch {branch}; defaulting to master') branch = 'master' - with open(os.environ['GITHUB_ENV'], 'a') as f: - f.write(f'{SCOPE}_REPO={full_repo}\n') - f.write(f'{SCOPE}_BRANCH={branch}\n') + for fn in (os.environ['GITHUB_ENV'], os.environ['GITHUB_OUTPUT']): + with open(fn, 'a') as f: + f.write(f'{SCOPE}_REPO={full_repo}\n') + f.write(f'{SCOPE}_BRANCH={branch}\n') + return 0 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..78cf79b9 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,109 @@ +name: Build + +env: + PYTHON_VERSION: '3.12' + TZ: Europe/Zurich + +on: + push: + branches: + - 'master' + - '*.x' + - 'ci-build-plugins' # TODO remove + pull_request: + branches: + - 'master' + - '*.x' + types: + - opened + - reopened + - synchronize + - labeled + +jobs: + list-plugins: + name: Get plugin list 📃 + runs-on: ubuntu-22.04 + if: github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'build-wheel') + outputs: + PLUGINS_MATRIX: ${{ steps.list-plugins.outputs.PLUGINS_MATRIX }} + steps: + - uses: actions/checkout@v4 + - name: Set up Python 🐍 + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + - name: Generate matrix + id: list-plugins + run: python .github/utils/generate_matrix.py + + build: + name: Build package for ${{ matrix.plugin }} 📦 + needs: list-plugins + runs-on: ubuntu-22.04 + if: github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'build-wheel') + strategy: + matrix: ${{ fromJson(needs.list-plugins.outputs.PLUGINS_MATRIX) }} + steps: + - name: Checkout plugins + uses: actions/checkout@v4 + with: + path: plugins + # prefer head commit over merge commit in case of PRs + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || '' }} + + - name: Pick Indico core repo + id: core-repo + env: + GH_TOKEN: ${{ github.token }} + PR_BODY: ${{ github.event_name == 'pull_request' && github.event.pull_request.body }} + PR_BASE_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref }} + run: python plugins/.github/utils/get_core_repo.py indico/indico INDICO + + - name: Checkout core + uses: actions/checkout@v4 + with: + path: indico + repository: indico/indico + ref: ${{ steps.core-repo.outputs.INDICO_BRANCH }} + + - name: Set up Python 🐍 + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: pip + cache-dependency-path: | + indico/requirements*.txt + plugins/**/setup.cfg + + - name: Setup Node + if: matrix.assets + uses: actions/setup-node@v4 + with: + node-version: 18.x + cache: 'npm' + cache-dependency-path: indico/package-lock.json + + - name: Install build deps 🔧 + working-directory: indico + run: | + sudo apt-get install libpq-dev + pip install --user -U pip setuptools wheel + pip install --user -e '.[dev]' + + - name: Install npm deps ☕ + if: matrix.assets + working-directory: indico + run: npm ci + + - name: Build wheel 🏗 + working-directory: indico + run: | + ./bin/maintenance/build-wheel.py plugin ../plugins/${{ matrix.plugin }} --add-version-suffix + + - uses: actions/upload-artifact@v4 + name: Upload build artifacts 📦 + with: + name: plugin-wheels + retention-days: 7 + path: ./indico/dist