Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support using sketches reports from local path #5

Merged
merged 5 commits into from
Sep 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 75 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,31 @@ This action comments on the pull request with a report on the resulting change i

## Inputs

### `size-deltas-reports-artifact-name`
### `sketches-reports-source`

Name of the [workflow artifact](https://docs.github.com/en/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts) that contains the memory usage data, as specified to the [`actions/upload-artifact`](https://github.com/actions/upload-artifact) action via its `name` input.
**Default**: "size-deltas-reports"

**Default**: `"size-deltas-reports"`
The action can be used in two ways:

#### Run from a [scheduled workflow](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#onschedule)

Recommended for public repositories.

The use of a scheduled workflow is necessary in order for the action to have the [write permissions required to comment on pull requests submitted from forks](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token).

In this usage, the `sketches-reports-source` defines the name of the workflow artifact that contains the memory usage data, as specified to the [`actions/upload-artifact`](https://github.com/actions/upload-artifact) action via its `name` input.

#### Run from the same workflow as the [`arduino/compile-sketches`](https://github.com/arduino/compile-sketches) action

Recommended for private repositories.

If configured to trigger on a short interval, the scheduled workflow method can use a lot of GitHub Actions minutes, quickly using up the limited allotment provided by GitHub for private repositories (public repositories get unlimited free minutes). For this reason, it may be preferable to only run the action as needed.

In order to get reports for pull requests from forks, the ["Send write tokens to workflows from fork pull requests" setting](https://docs.github.com/en/github/administering-a-repository/disabling-or-limiting-github-actions-for-a-repository#enabling-workflows-for-private-repository-forks) must be enabled.

If the "Send write tokens to workflows from fork pull requests" setting is not enabled but the ["Run workflows from fork pull requests" setting](https://docs.github.com/en/github/administering-a-repository/disabling-or-limiting-github-actions-for-a-repository#enabling-workflows-for-private-repository-forks) is enabled, the workflow should be configured to only run the action when the pull request is not from a fork (`if: github.event.pull_request.head.repo.full_name == github.repository`). This will prevent workflow job failures that would otherwise be caused when the report creation failed due to not having the necessary write permissions.

In this usage, the `sketches-reports-source` defines the path to the folder containing the memory usage data, as specified to the [`actions/download-artifact`](https://github.com/actions/download-artifact) action via its `path` input.

### `github-token`

Expand All @@ -22,6 +42,8 @@ Name of the [workflow artifact](https://docs.github.com/en/actions/configuring-a

## Example usage

### Scheduled workflow

```yaml
on:
schedule:
Expand Down Expand Up @@ -49,3 +71,53 @@ jobs:
name: size-deltas-reports
path: size-deltas-reports
```

### Workflow triggered by `pull_request` event

```yaml
on: [push, pull_request]
env:
# It's convenient to set variables for values used multiple times in the workflow
SKETCHES_REPORTS_PATH: sketches-reports
SKETCHES_REPORTS_ARTIFACT_NAME: sketches-reports
jobs:
compile:
runs-on: ubuntu-latest
strategy:
matrix:
fqbn:
- "arduino:avr:uno"
- "arduino:samd:mkrzero"
steps:
- uses: actions/checkout@v2

- uses: arduino/compile-sketches@main
with:
fqbn: ${{ matrix.fqbn }}
enable-deltas-report: true
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}

# This step is needed to pass the size data to the report job
- name: Upload sketches report to workflow artifact
uses: actions/upload-artifact@v2
with:
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}
path: ${{ env.SKETCHES_REPORTS_PATH }}

# When using a matrix to compile for multiple boards, it's necessary to use a separate job for the deltas report
report:
needs: compile # Wait for the compile job to finish to get the data for the report
if: github.event_name == 'pull_request' # Only run the job when the workflow is triggered by a pull request
runs-on: ubuntu-latest
steps:
# This step is needed to get the size data produced by the compile jobs
- name: Download sketches reports artifact
uses: actions/download-artifact@v2
with:
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}
path: ${{ env.SKETCHES_REPORTS_PATH }}

- uses: arduino/report-size-deltas@main
with:
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
```
4 changes: 2 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: 'Report Arduino Sketch Size Deltas'
description: 'Comments on the pull request with a report on the resulting change in memory usage of Arduino sketches'
inputs:
size-deltas-reports-artifact-name:
description: 'Name of the workflow artifact that contains the memory usage data, as specified to the actions/upload-artifact action via its name input'
sketches-reports-source:
description: 'When run from scheduled workflow, name of the workflow artifact that contains sketches reports. When run from a pull request triggered workflow, path to the folder containing sketches reports.'
default: 'size-deltas-reports'
github-token:
description: 'GitHub access token used to comment the memory usage comparison results to the PR thread'
Expand Down
55 changes: 44 additions & 11 deletions reportsizedeltas/reportsizedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json
import logging
import os
import pathlib
import re
import sys
import tempfile
Expand All @@ -19,8 +20,13 @@
def main():
set_verbosity(enable_verbosity=False)

if "INPUT_SIZE-DELTAS-REPORTS-ARTIFACT-NAME" in os.environ:
print("::warning::The size-deltas-report-artifact-name input is deprecated. Use the equivalent input: "
"sketches-reports-source instead.")
os.environ["INPUT_SKETCHES-REPORTS-SOURCE"] = os.environ["INPUT_SIZE-DELTAS-REPORTS-ARTIFACT-NAME"]

report_size_deltas = ReportSizeDeltas(repository_name=os.environ["GITHUB_REPOSITORY"],
artifact_name=os.environ["INPUT_SIZE-DELTAS-REPORTS-ARTIFACT-NAME"],
sketches_reports_source=os.environ["INPUT_SKETCHES-REPORTS-SOURCE"],
token=os.environ["INPUT_GITHUB-TOKEN"])

report_size_deltas.report_size_deltas()
Expand Down Expand Up @@ -73,12 +79,35 @@ class ReportKeys:
sketches = "sketches"
compilation_success = "compilation_success"

def __init__(self, repository_name, artifact_name, token):
def __init__(self, repository_name, sketches_reports_source, token):
self.repository_name = repository_name
self.artifact_name = artifact_name
self.sketches_reports_source = sketches_reports_source
self.token = token

def report_size_deltas(self):
"""Comment a report of memory usage change to pull request(s)."""
if os.environ["GITHUB_EVENT_NAME"] == "pull_request":
# The sketches reports will be in a local folder location specified by the user
self.report_size_deltas_from_local_reports()
else:
# The script is being run from a workflow triggered by something other than a PR
# Scan the repository's pull requests and comment memory usage change reports where appropriate.
self.report_size_deltas_from_workflow_artifacts()

def report_size_deltas_from_local_reports(self):
"""Comment a report of memory usage change to the pull request."""
sketches_reports_folder = pathlib.Path(os.environ["GITHUB_WORKSPACE"], self.sketches_reports_source)
sketches_reports = self.get_sketches_reports(artifact_folder_object=sketches_reports_folder)

if sketches_reports:
report = self.generate_report(sketches_reports=sketches_reports)

with open(file=os.environ["GITHUB_EVENT_PATH"]) as github_event_file:
pr_number = json.load(github_event_file)["pull_request"]["number"]

self.comment_report(pr_number=pr_number, report_markdown=report)

def report_size_deltas_from_workflow_artifacts(self):
"""Scan the repository's pull requests and comment memory usage change reports where appropriate."""
# Get the repository's pull requests
logger.debug("Getting PRs for " + self.repository_name)
Expand Down Expand Up @@ -106,9 +135,10 @@ def report_size_deltas(self):
print("::debug::Report already exists")
continue

artifact_download_url = self.get_artifact_download_url_for_sha(pr_user_login=pr_data["user"]["login"],
pr_head_ref=pr_data["head"]["ref"],
pr_head_sha=pr_head_sha)
artifact_download_url = self.get_artifact_download_url_for_sha(
pr_user_login=pr_data["user"]["login"],
pr_head_ref=pr_data["head"]["ref"],
pr_head_sha=pr_head_sha)
if artifact_download_url is None:
# Go on to the next PR
print("::debug::No sketches report artifact found")
Expand Down Expand Up @@ -209,7 +239,7 @@ def get_artifact_download_url_for_run(self, run_id):

for artifact_data in artifacts_data["artifacts"]:
# The artifact is identified by a specific name
if artifact_data["name"] == self.artifact_name:
if artifact_data["name"] == self.sketches_reports_source:
return artifact_data["archive_download_url"]

page_number += 1
Expand All @@ -228,12 +258,13 @@ def get_artifact(self, artifact_download_url):
artifact_folder_object = tempfile.TemporaryDirectory(prefix="reportsizedeltas-")
try:
# Download artifact
with open(file=artifact_folder_object.name + "/" + self.artifact_name + ".zip", mode="wb") as out_file:
with open(file=artifact_folder_object.name + "/" + self.sketches_reports_source + ".zip",
mode="wb") as out_file:
with self.raw_http_request(url=artifact_download_url) as fp:
out_file.write(fp.read())

# Unzip artifact
artifact_zip_file = artifact_folder_object.name + "/" + self.artifact_name + ".zip"
artifact_zip_file = artifact_folder_object.name + "/" + self.sketches_reports_source + ".zip"
with zipfile.ZipFile(file=artifact_zip_file, mode="r") as zip_ref:
zip_ref.extractall(path=artifact_folder_object.name)
os.remove(artifact_zip_file)
Expand All @@ -251,10 +282,12 @@ def get_sketches_reports(self, artifact_folder_object):
artifact_folder_object -- object containing the data about the temporary folder that stores the markdown files
"""
with artifact_folder_object as artifact_folder:
# artifact_folder will be a string when running in non-local report mode
artifact_folder = pathlib.Path(artifact_folder)
sketches_reports = []
for report_filename in sorted(os.listdir(path=artifact_folder)):
for report_filename in sorted(artifact_folder.iterdir()):
# Combine sketches reports into an array
with open(file=artifact_folder + "/" + report_filename) as report_file:
with open(file=report_filename.joinpath(report_filename)) as report_file:
report_data = json.load(report_file)
if (
(self.ReportKeys.boards not in report_data)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"pull_request": {
"head": {
"sha": "pull_request-head-sha"
},
"number": 42
}
}
Loading