diff --git a/.github/actions/install-requirement/action.yml b/.github/actions/install-requirement/action.yml new file mode 100644 index 00000000..3724ca1c --- /dev/null +++ b/.github/actions/install-requirement/action.yml @@ -0,0 +1,51 @@ +name: Install Project Requirements +description: Install requirements from a PEP 517 project + +inputs: + requirements: + description: "Whitespace-delimited list of project requirements to install." + required: true + project-root: + description: "The filesystem path to the root of the project to install from; defaults to github.workspace." + default: ${{ github.workspace }} + extra: + description: "Name of the optional dependencies marker; e.g. dev." + required: false + default: "" + workflow-repo: + # Only needed for PRs in other repos wanting to test new workflow changes before they are merged. + # These inputs should not be specified by another repo on their main branch. + description: "The repo to use to run additional workflows and actions." + default: "beeware/.github" + workflow-repo-ref: + description: "The repo ref to use to run additional workflows and actions." + default: "" + +runs: + using: composite + steps: + - name: Checkout ${{ inputs.workflow-repo }}${{ inputs.workflow-repo-ref && format('@{0}', inputs.workflow-repo-ref) || '' }} + uses: actions/checkout@v4.1.6 + with: + repository: ${{ inputs.workflow-repo }} + ref: ${{ inputs.workflow-repo-ref }} + path: .github-beeware + + - name: Resolve Project Root + id: paths + shell: bash + run: echo "project-root=$( cd "${{ inputs.project-root }}" ; pwd -P )" | tee -a ${GITHUB_OUTPUT} + + - name: Install Dependencies + shell: bash + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools build wheel + + - name: Install Requirements + working-directory: ./.github-beeware/scripts + shell: bash + run: | + python -m install_requirement ${{ inputs.requirements }} \ + --extra "${{ inputs.extra }}" \ + --project-root "$(printf -- "%q" "${{ steps.paths.outputs.project-root }}")" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0f361ded..d1884950 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -184,6 +184,74 @@ jobs: repo: toga build-subdir: android + test-install-requirements: + name: Install Requirements + needs: pre-commit + runs-on: ${{ matrix.runner-os }} + strategy: + fail-fast: false + matrix: + runner-os: [ macos-latest, windows-latest, ubuntu-latest ] + steps: + - name: Checkout beeware/briefcase + uses: actions/checkout@v4.1.6 + with: + repository: beeware/briefcase + + - name: Checkout beeware/briefcase to path + uses: actions/checkout@v4.1.6 + with: + repository: beeware/briefcase + path: repos/briefcase + + - name: Checkout beeware/.github + uses: actions/checkout@v4.1.6 + with: + repository: beeware/.github + path: repos/.github-beeware + + - name: Set up Python + uses: actions/setup-python@v5.1.0 + with: + python-version: "3.x" + + - name: Test Install Requirements with Path + uses: ./repos/.github-beeware/.github/actions/install-requirement + with: + requirements: "pre-commit tox" + extra: "dev" + project-root: "repos/briefcase" + + - name: Test Install Requirements with Extra + uses: ./repos/.github-beeware/.github/actions/install-requirement + with: + requirements: "coverage" + extra: "dev" + + - name: Test Install Requirements + uses: ./repos/.github-beeware/.github/actions/install-requirement + with: + requirements: "cookiecutter" + + - name: Verify Requirements Installed + run: | + if ! python -m pip list | grep tox; then + echo '::error::Failed to install tox' + exit 1 + fi + if ! python -m pip list | grep pre-commit; then + echo '::error::Failed to install pre-commit' + exit 1 + fi + if ! python -m pip list | grep coverage; then + echo '::error::Failed to install coverage' + exit 1 + fi + if ! python -m pip list | grep cookiecutter; then + echo '::error::Failed to install cookiecutter' + exit 1 + fi + test-verify-projects-briefcase: name: Verify Project needs: [ pre-commit, test-package-python ] diff --git a/scripts/__pycache__/install_requirement.cpython-312.pyc b/scripts/__pycache__/install_requirement.cpython-312.pyc new file mode 100644 index 00000000..f7db9741 Binary files /dev/null and b/scripts/__pycache__/install_requirement.cpython-312.pyc differ diff --git a/scripts/install_requirement.py b/scripts/install_requirement.py index 0c604a2f..4fedde99 100644 --- a/scripts/install_requirement.py +++ b/scripts/install_requirement.py @@ -7,10 +7,7 @@ # Install one or more PEP 517 project defined requirements # # positional arguments: -# requirements List of project requirements to install. Any project -# requirements that start with any of these values will -# be installed. For instance, including 'pytest' in this -# list would install both pytest and pytest-xdist. +# requirements Whitespace-delimited list of project requirements to install. # # options: # -h, --help show this help message and exit @@ -141,10 +138,11 @@ def gather_requirements( def install_requirements(requirements: list[Requirement]): """Install requirements from PyPI.""" + installed_reqs = [] for requirement in requirements: extras = f"[{','.join(requirement.extras)}]" if requirement.extras else "" requirement_str = f"{requirement.name}{extras}{requirement.specifier}" - print(f"Installing {requirement_str}...") + print(f"Installing {requirement_str}...", flush=True) subprocess.run( [ sys.executable, @@ -156,6 +154,9 @@ def install_requirements(requirements: list[Requirement]): ], check=True, ) + installed_reqs.append(requirement_str) + + print(f"\nSuccessfully installed:\n {f'{chr(10)} '.join(installed_reqs)}") def main():