Skip to content

Commit 2f05f71

Browse files
authored
Merge pull request #5 from per1234/local-report-support
Support using sketches reports from local path
2 parents 66f2d53 + d4ae92e commit 2f05f71

File tree

5 files changed

+268
-44
lines changed

5 files changed

+268
-44
lines changed

README.md

+75-3
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,31 @@ This action comments on the pull request with a report on the resulting change i
88

99
## Inputs
1010

11-
### `size-deltas-reports-artifact-name`
11+
### `sketches-reports-source`
1212

13-
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.
13+
**Default**: "size-deltas-reports"
1414

15-
**Default**: `"size-deltas-reports"`
15+
The action can be used in two ways:
16+
17+
#### Run from a [scheduled workflow](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#onschedule)
18+
19+
Recommended for public repositories.
20+
21+
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).
22+
23+
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.
24+
25+
#### Run from the same workflow as the [`arduino/compile-sketches`](https://github.com/arduino/compile-sketches) action
26+
27+
Recommended for private repositories.
28+
29+
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.
30+
31+
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.
32+
33+
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.
34+
35+
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.
1636

1737
### `github-token`
1838

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

2343
## Example usage
2444

45+
### Scheduled workflow
46+
2547
```yaml
2648
on:
2749
schedule:
@@ -49,3 +71,53 @@ jobs:
4971
name: size-deltas-reports
5072
path: size-deltas-reports
5173
```
74+
75+
### Workflow triggered by `pull_request` event
76+
77+
```yaml
78+
on: [push, pull_request]
79+
env:
80+
# It's convenient to set variables for values used multiple times in the workflow
81+
SKETCHES_REPORTS_PATH: sketches-reports
82+
SKETCHES_REPORTS_ARTIFACT_NAME: sketches-reports
83+
jobs:
84+
compile:
85+
runs-on: ubuntu-latest
86+
strategy:
87+
matrix:
88+
fqbn:
89+
- "arduino:avr:uno"
90+
- "arduino:samd:mkrzero"
91+
steps:
92+
- uses: actions/checkout@v2
93+
94+
- uses: arduino/compile-sketches@main
95+
with:
96+
fqbn: ${{ matrix.fqbn }}
97+
enable-deltas-report: true
98+
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
99+
100+
# This step is needed to pass the size data to the report job
101+
- name: Upload sketches report to workflow artifact
102+
uses: actions/upload-artifact@v2
103+
with:
104+
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}
105+
path: ${{ env.SKETCHES_REPORTS_PATH }}
106+
107+
# When using a matrix to compile for multiple boards, it's necessary to use a separate job for the deltas report
108+
report:
109+
needs: compile # Wait for the compile job to finish to get the data for the report
110+
if: github.event_name == 'pull_request' # Only run the job when the workflow is triggered by a pull request
111+
runs-on: ubuntu-latest
112+
steps:
113+
# This step is needed to get the size data produced by the compile jobs
114+
- name: Download sketches reports artifact
115+
uses: actions/download-artifact@v2
116+
with:
117+
name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }}
118+
path: ${{ env.SKETCHES_REPORTS_PATH }}
119+
120+
- uses: arduino/report-size-deltas@main
121+
with:
122+
sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }}
123+
```

action.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
name: 'Report Arduino Sketch Size Deltas'
22
description: 'Comments on the pull request with a report on the resulting change in memory usage of Arduino sketches'
33
inputs:
4-
size-deltas-reports-artifact-name:
5-
description: 'Name of the workflow artifact that contains the memory usage data, as specified to the actions/upload-artifact action via its name input'
4+
sketches-reports-source:
5+
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.'
66
default: 'size-deltas-reports'
77
github-token:
88
description: 'GitHub access token used to comment the memory usage comparison results to the PR thread'

reportsizedeltas/reportsizedeltas.py

+44-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import logging
55
import os
6+
import pathlib
67
import re
78
import sys
89
import tempfile
@@ -19,8 +20,13 @@
1920
def main():
2021
set_verbosity(enable_verbosity=False)
2122

23+
if "INPUT_SIZE-DELTAS-REPORTS-ARTIFACT-NAME" in os.environ:
24+
print("::warning::The size-deltas-report-artifact-name input is deprecated. Use the equivalent input: "
25+
"sketches-reports-source instead.")
26+
os.environ["INPUT_SKETCHES-REPORTS-SOURCE"] = os.environ["INPUT_SIZE-DELTAS-REPORTS-ARTIFACT-NAME"]
27+
2228
report_size_deltas = ReportSizeDeltas(repository_name=os.environ["GITHUB_REPOSITORY"],
23-
artifact_name=os.environ["INPUT_SIZE-DELTAS-REPORTS-ARTIFACT-NAME"],
29+
sketches_reports_source=os.environ["INPUT_SKETCHES-REPORTS-SOURCE"],
2430
token=os.environ["INPUT_GITHUB-TOKEN"])
2531

2632
report_size_deltas.report_size_deltas()
@@ -73,12 +79,35 @@ class ReportKeys:
7379
sketches = "sketches"
7480
compilation_success = "compilation_success"
7581

76-
def __init__(self, repository_name, artifact_name, token):
82+
def __init__(self, repository_name, sketches_reports_source, token):
7783
self.repository_name = repository_name
78-
self.artifact_name = artifact_name
84+
self.sketches_reports_source = sketches_reports_source
7985
self.token = token
8086

8187
def report_size_deltas(self):
88+
"""Comment a report of memory usage change to pull request(s)."""
89+
if os.environ["GITHUB_EVENT_NAME"] == "pull_request":
90+
# The sketches reports will be in a local folder location specified by the user
91+
self.report_size_deltas_from_local_reports()
92+
else:
93+
# The script is being run from a workflow triggered by something other than a PR
94+
# Scan the repository's pull requests and comment memory usage change reports where appropriate.
95+
self.report_size_deltas_from_workflow_artifacts()
96+
97+
def report_size_deltas_from_local_reports(self):
98+
"""Comment a report of memory usage change to the pull request."""
99+
sketches_reports_folder = pathlib.Path(os.environ["GITHUB_WORKSPACE"], self.sketches_reports_source)
100+
sketches_reports = self.get_sketches_reports(artifact_folder_object=sketches_reports_folder)
101+
102+
if sketches_reports:
103+
report = self.generate_report(sketches_reports=sketches_reports)
104+
105+
with open(file=os.environ["GITHUB_EVENT_PATH"]) as github_event_file:
106+
pr_number = json.load(github_event_file)["pull_request"]["number"]
107+
108+
self.comment_report(pr_number=pr_number, report_markdown=report)
109+
110+
def report_size_deltas_from_workflow_artifacts(self):
82111
"""Scan the repository's pull requests and comment memory usage change reports where appropriate."""
83112
# Get the repository's pull requests
84113
logger.debug("Getting PRs for " + self.repository_name)
@@ -106,9 +135,10 @@ def report_size_deltas(self):
106135
print("::debug::Report already exists")
107136
continue
108137

109-
artifact_download_url = self.get_artifact_download_url_for_sha(pr_user_login=pr_data["user"]["login"],
110-
pr_head_ref=pr_data["head"]["ref"],
111-
pr_head_sha=pr_head_sha)
138+
artifact_download_url = self.get_artifact_download_url_for_sha(
139+
pr_user_login=pr_data["user"]["login"],
140+
pr_head_ref=pr_data["head"]["ref"],
141+
pr_head_sha=pr_head_sha)
112142
if artifact_download_url is None:
113143
# Go on to the next PR
114144
print("::debug::No sketches report artifact found")
@@ -209,7 +239,7 @@ def get_artifact_download_url_for_run(self, run_id):
209239

210240
for artifact_data in artifacts_data["artifacts"]:
211241
# The artifact is identified by a specific name
212-
if artifact_data["name"] == self.artifact_name:
242+
if artifact_data["name"] == self.sketches_reports_source:
213243
return artifact_data["archive_download_url"]
214244

215245
page_number += 1
@@ -228,12 +258,13 @@ def get_artifact(self, artifact_download_url):
228258
artifact_folder_object = tempfile.TemporaryDirectory(prefix="reportsizedeltas-")
229259
try:
230260
# Download artifact
231-
with open(file=artifact_folder_object.name + "/" + self.artifact_name + ".zip", mode="wb") as out_file:
261+
with open(file=artifact_folder_object.name + "/" + self.sketches_reports_source + ".zip",
262+
mode="wb") as out_file:
232263
with self.raw_http_request(url=artifact_download_url) as fp:
233264
out_file.write(fp.read())
234265

235266
# Unzip artifact
236-
artifact_zip_file = artifact_folder_object.name + "/" + self.artifact_name + ".zip"
267+
artifact_zip_file = artifact_folder_object.name + "/" + self.sketches_reports_source + ".zip"
237268
with zipfile.ZipFile(file=artifact_zip_file, mode="r") as zip_ref:
238269
zip_ref.extractall(path=artifact_folder_object.name)
239270
os.remove(artifact_zip_file)
@@ -251,10 +282,12 @@ def get_sketches_reports(self, artifact_folder_object):
251282
artifact_folder_object -- object containing the data about the temporary folder that stores the markdown files
252283
"""
253284
with artifact_folder_object as artifact_folder:
285+
# artifact_folder will be a string when running in non-local report mode
286+
artifact_folder = pathlib.Path(artifact_folder)
254287
sketches_reports = []
255-
for report_filename in sorted(os.listdir(path=artifact_folder)):
288+
for report_filename in sorted(artifact_folder.iterdir()):
256289
# Combine sketches reports into an array
257-
with open(file=artifact_folder + "/" + report_filename) as report_file:
290+
with open(file=report_filename.joinpath(report_filename)) as report_file:
258291
report_data = json.load(report_file)
259292
if (
260293
(self.ReportKeys.boards not in report_data)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"pull_request": {
3+
"head": {
4+
"sha": "pull_request-head-sha"
5+
},
6+
"number": 42
7+
}
8+
}

0 commit comments

Comments
 (0)