From 6ffb86d8c17e3cacde616b1dff90b2af268d83a5 Mon Sep 17 00:00:00 2001 From: per1234 Date: Sat, 24 Oct 2020 22:11:56 -0700 Subject: [PATCH 1/3] Convert to composite run steps action When the action was created, the only option for non-JavaScript actions was to use a Docker container. However, GitHub recently added a new action type: the "composite run steps action": https://docs.github.com/en/free-pro-team@latest/actions/creating-actions/creating-a-composite-run-steps-action The Docker container approach has the significant advantage of providing a controlled environment for the action to run in, which will not pollute the general environment of the runner for later workflow steps. However it also has a couple disadvantages: - Docker container actions can only execute on runners with a Linux operating system. - The workspace is mounted to a folder in the container named `/github/workspace`. The problem with the first is it prevents testing for other operating systems. Arduino boards platforms have different toolchains and even build properties according to operating system of the machine they are running on. Only testing on a Linux system may result in missing issues that affect the majority of users. Although more still needs to be done to make the action cross-platform, converting to a composite run steps action is the first step toward that goal. The problem with the second is that, in order to be valid, an Arduino sketch folder must match the filename of the primary sketch file. For a sketch in the root of the repository, a sketch author might achieve this to some limited extent by naming the repository to match the primary sketch file name. However, the container volume is not named according to the repository name, so sketches in the root of the repository are not currently supported by the action (except in the unlikely event the sketch happens to be named "workspace"). Even though structuring sketch repositories in this manner is not best practices due to GitHub's popular "Download ZIP" appending the Git ref to the end of the folder name, the purpose of this action is to compile sketches, not legislate repository policy, so it is reasonable to support this use case. The workspace folder in the GitHub Actions runner is named according to the repository name, meaning that converting to a composite run steps action permits use with sketches in the root of the repository. --- Dockerfile | 10 ---------- action-setup.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ action.yml | 29 +++++++++++++++++++++++++++-- 3 files changed, 71 insertions(+), 12 deletions(-) delete mode 100644 Dockerfile create mode 100755 action-setup.sh diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4516451..0000000 --- a/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM python:3.8.6 - -# Copies your code file from your action repository to the filesystem path `/` of the container -COPY compilesketches /compilesketches - -# Install python dependencies -RUN pip install -r /compilesketches/requirements.txt - -# Code file to execute when the docker container starts up -ENTRYPOINT ["python", "/compilesketches/compilesketches.py"] diff --git a/action-setup.sh b/action-setup.sh new file mode 100755 index 0000000..8579073 --- /dev/null +++ b/action-setup.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# Set up the Python environment for the action's script to run in + +readonly PYTHON_PACKAGE_VERSION='3.8' + +# https://stackoverflow.com/a/29835459 +readonly SCRIPT_PATH="$( + CDPATH='' \ + cd -- "$( + dirname -- "$0" + )" && ( + pwd -P + ) +)" + +readonly PYTHON_COMMAND="python${PYTHON_PACKAGE_VERSION}" +readonly PYTHON_VENV_PATH="${SCRIPT_PATH}/compilesketches/.venv" +readonly PYTHON_VENV_ACTIVATE_SCRIPT_PATH="${PYTHON_VENV_PATH}/bin/activate" + +# Install Python +sudo apt-get install --yes software-properties-common > /dev/null +sudo add-apt-repository --yes ppa:deadsnakes/ppa > /dev/null +sudo apt-get update --yes > /dev/null +sudo apt-get install --yes python${PYTHON_PACKAGE_VERSION} > /dev/null +echo "Using Python version: $("$PYTHON_COMMAND" --version)" + +sudo apt-get install --yes python3-setuptools > /dev/null +sudo apt-get install --yes python${PYTHON_PACKAGE_VERSION}-venv > /dev/null + +# Create Python virtual environment +"$PYTHON_COMMAND" -m venv "$PYTHON_VENV_PATH" + +# Activate Python virtual environment +. "$PYTHON_VENV_ACTIVATE_SCRIPT_PATH" + +# Install Python dependencies +"$PYTHON_COMMAND" -m pip install --upgrade pip > /dev/null +"$PYTHON_COMMAND" -m pip install --quiet --requirement "${SCRIPT_PATH}/compilesketches/requirements.txt" + +# Set outputs for use in GitHub Actions workflow steps +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-output-parameter +echo "::set-output name=python-command::$PYTHON_COMMAND" +echo "::set-output name=python-venv-activate-script-path::$PYTHON_VENV_ACTIVATE_SCRIPT_PATH" diff --git a/action.yml b/action.yml index d096604..7bbb4c7 100644 --- a/action.yml +++ b/action.yml @@ -43,5 +43,30 @@ inputs: required: true runs: - using: 'docker' - image: 'Dockerfile' + using: composite + steps: + - name: Run the set up script + id: setup + shell: bash + run: | + # Group action setup log output + echo "::group::Action set up" + "${{ github.action_path }}/action-setup.sh" + echo "::endgroup::" + + - name: Run script + shell: bash + env: + INPUT_CLI-VERSION: ${{ inputs.cli-version }} + INPUT_FQBN: ${{ inputs.fqbn }} + INPUT_LIBRARIES: ${{ inputs.libraries }} + INPUT_PLATFORMS: ${{ inputs.platforms }} + INPUT_SKETCH-PATHS: ${{ inputs.sketch-paths }} + INPUT_VERBOSE: ${{ inputs.verbose }} + INPUT_GITHUB-TOKEN: ${{ inputs.github-token }} + INPUT_ENABLE-DELTAS-REPORT: ${{ inputs.enable-deltas-report }} + INPUT_ENABLE-WARNINGS-REPORT: ${{ inputs.enable-warnings-report }} + INPUT_SKETCHES-REPORT-PATH: ${{ inputs.sketches-report-path }} + run: | + source "${{ steps.setup.outputs.python-venv-activate-script-path }}" + "${{ steps.setup.outputs.python-command }}" "${{ github.action_path }}/compilesketches/compilesketches.py" From af17618aa24b87d3bc8e3991f2d5c114855b6830 Mon Sep 17 00:00:00 2001 From: per1234 Date: Sun, 25 Oct 2020 01:55:41 -0700 Subject: [PATCH 2/3] Add CI workflow to lint shell scripts Although currently very simple, the action setup script is essential to the proper funtioning of the action, so worthy of some CI. --- .github/workflows/lint-shell.yml | 24 ++++++++++++++++++++++++ action-setup.sh | 1 + 2 files changed, 25 insertions(+) create mode 100644 .github/workflows/lint-shell.yml diff --git a/.github/workflows/lint-shell.yml b/.github/workflows/lint-shell.yml new file mode 100644 index 0000000..d0a6c28 --- /dev/null +++ b/.github/workflows/lint-shell.yml @@ -0,0 +1,24 @@ +name: Lint shell scripts + +on: + push: + paths: + - '.github/workflows/lint-shell.yml' + - '**.sh' + pull_request: + paths: + - '.github/workflows/lint-shell.yml' + - '**.sh' + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + # Recursively lint all shell scripts in the repository + # See: https://github.com/azohra/shell-linter/blob/latest/README.md + - name: ShellCheck + uses: azohra/shell-linter@latest diff --git a/action-setup.sh b/action-setup.sh index 8579073..4022b68 100755 --- a/action-setup.sh +++ b/action-setup.sh @@ -32,6 +32,7 @@ sudo apt-get install --yes python${PYTHON_PACKAGE_VERSION}-venv > /dev/null "$PYTHON_COMMAND" -m venv "$PYTHON_VENV_PATH" # Activate Python virtual environment +# shellcheck source=/dev/null . "$PYTHON_VENV_ACTIVATE_SCRIPT_PATH" # Install Python dependencies From 99a1a9239e72b7f04ac3ab008ecdc61e6766c23b Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 26 Oct 2020 03:19:16 -0700 Subject: [PATCH 3/3] Mirror the approach used when running the action in the test workflow The test workflow will be most effective if it emulates the environment the action will run in. --- .github/workflows/test-python.yml | 50 +++++++++++++++++++++++-------- compilesketches/tests/.coveragerc | 3 ++ 2 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 compilesketches/tests/.coveragerc diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index a265814..22895e0 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -4,15 +4,16 @@ on: pull_request: paths: - '.github/workflows/test-python.yml' + - 'action-setup.sh' - 'compilesketches/**' push: paths: - '.github/workflows/test-python.yml' + - 'action-setup.sh' - 'compilesketches/**' - # The actions/setup-python action will periodically break the workflow by dropping the Python version we have pinned - # Better to catch that before it causes confusion for a contributor + # Catch issues resulting from new patch releases of Python in the APT repository schedule: # run every Tuesday at 3 AM UTC - cron: "0 3 * * 2" @@ -32,29 +33,52 @@ jobs: env: PYTHON_PROJECT_PATH: ${GITHUB_WORKSPACE}/compilesketches PYTHON_PROJECT_TESTS_PATH: ${GITHUB_WORKSPACE}/compilesketches/tests + COVERAGE_DATA_FILENAME: coverage.xml steps: - name: Checkout uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v1 - with: - python-version: '3.8.6' + - name: Run the set up script + id: setup + run: | + "${{ github.workspace }}/action-setup.sh" - - name: Install dependencies + - name: Install test dependencies run: | - python -m pip install --upgrade pip - pip install --requirement "${{ env.PYTHON_PROJECT_TESTS_PATH }}/requirements.txt" + source "${{ steps.setup.outputs.python-venv-activate-script-path }}" + "${{ steps.setup.outputs.python-command }}" \ + -m \ + pip install \ + --requirement "${{ env.PYTHON_PROJECT_TESTS_PATH }}/requirements.txt" - - name: Run Python unit tests and report code coverage + - name: Run Python unit tests and record code coverage data run: | + source "${{ steps.setup.outputs.python-venv-activate-script-path }}" export PYTHONPATH="${{ env.PYTHON_PROJECT_PATH }}" - coverage run --source="${{ env.PYTHON_PROJECT_PATH }}" --module pytest "${{ env.PYTHON_PROJECT_TESTS_PATH }}" - # Display code coverage report in workflow run log - coverage report + "${{ steps.setup.outputs.python-command }}" \ + -m \ + coverage run \ + --rcfile="${{ env.PYTHON_PROJECT_TESTS_PATH }}/.coveragerc" \ + --source="${{ env.PYTHON_PROJECT_PATH }}" \ + --module \ + pytest "${{ env.PYTHON_PROJECT_TESTS_PATH }}" + # Generate coverage data file for consumption by `codecov/codecov-action`. + # Otherwise that action generates the file using the system Python environment, which doesn't work. + "${{ steps.setup.outputs.python-command }}" \ + -m \ + coverage xml \ + -o "${{ github.workspace }}/${{ env.COVERAGE_DATA_FILENAME }}" + + - name: Display code coverage report + run: | + source "${{ steps.setup.outputs.python-venv-activate-script-path }}" + "${{ steps.setup.outputs.python-command }}" \ + -m \ + coverage report - name: Upload coverage report to Codecov uses: codecov/codecov-action@v1 with: + file: ${{ env.COVERAGE_DATA_FILENAME }} fail_ci_if_error: true diff --git a/compilesketches/tests/.coveragerc b/compilesketches/tests/.coveragerc new file mode 100644 index 0000000..9ca48dd --- /dev/null +++ b/compilesketches/tests/.coveragerc @@ -0,0 +1,3 @@ +[run] +omit = + */.venv/*