refactor!(action): detect when in private branches

This removes the need to use the private-repo-workaround input.
This commit is contained in:
Jalil David Salamé Messina 2024-12-19 21:56:16 +01:00
parent bff5365c60
commit 39f58ee538
Signed by: jalil
GPG key ID: F016B9E770737A0B
5 changed files with 125 additions and 69 deletions

View file

@ -1,12 +1,12 @@
# Nix Flake outputs size
Use `nix path-info` to query the size of flake outputs and produce a markdown report.
Use `nix path-info` to query the size of flake outputs and produce a report.
You can post this report as a comment to the PR associated with the current branch and/or export the report as a markdown artifact.
This repost can be posted to a PR (as formatted markdown) and/or uploaded as a workflow artifact.
Requires `nix`, `jq`, `curl`, `sed` and `coreutils` to be in path.
Requires `nix`, `jq`, `curl`, `sed`, `gunzip`, `tar` and `coreutils` to be in the runner's path.
## Usage
## Example
```yaml
- name: Generate size report
@ -15,6 +15,11 @@ Requires `nix`, `jq`, `curl`, `sed` and `coreutils` to be in path.
comment-on-pr: 'true'
generate-artifact: 'false'
artifact-name: 'size-report.md'
# If you want to enable comparisons set this to true
do-comparison: 'false'
job-name: '' # required if do-comparison is true
# This is the branch that will be compared against
base-branch: ${{ github.base_ref }} # or default branch if missing
```
For more details see the [action.yaml](./action.yml) file.

View file

@ -5,7 +5,7 @@ description: |
report.
You can post this report as a comment to the PR associated with the current
branch and/or export the report as a markdown artifact.
branch and/or export the report as a JSON artifact.
Requires `nix`, `jq`, `curl`, `sed`, `gunzip`, `tar` and `coreutils` to be in
the runner's path.
@ -19,75 +19,95 @@ description: |
comment-on-pr: 'true'
generate-artifact: 'false'
artifact-name: 'size-report.md'
base-branch: ${{ github.base_ref }} # set to e.g. main if not triggered by a pull_request
job-name: '' # set to the name of this job if you want to enable comparisons
# If you want to enable comparisons set this to true
do-comparison: 'false'
job-name: '' # required if do-comparison is true
# This is the branch that will be compared against
base-branch: ${{ github.base_ref }} # or default branch if missing
```
inputs:
comment-on-pr:
description: Comment the report on the PR associated with the current branch.
description: |
Comment the report on the PR associated with the current branch.
This is a no-op in case no PR is associated with the current branch.
default: 'true'
# Generate workflow artifact
generate-artifact:
description: Export the generated markdown document as an artifact.
description: Export the generated markdown document as a workflow artifact.
default: 'false'
artifact-name:
description: The name of the generated artifact.
default: report.json
base-branch:
# Comparison Report (comment only)
do-comparison:
description: |
The name of the base branch, defaults to github.base_ref which is only
available in pull_request triggered workflows, for other workflows
specify it manually.
When commenting on the PR compare the results with those in the base branch.
It will try to download the generated artifact from this branch so make
sure `generate-artifacte: true` when the workflow is running on that
branch.
default: ${{ github.base_ref }}
This is a no-op when `comment-on-pr: false`.
It requires `job-name` to be set.
default: 'false'
job-name:
description: |
The name of the job running this action. If not set, no comparisons can
be made.
default: ''
private-repo-workaround:
base-branch:
description: |
Forgejo doesn't support downloading artifacts through the API [see
codeberg.org/forgejo/forgejo#6315](https://codeberg.org/forgejo/forgejo/issues/6315).
The name of the base branch, defaults to `github.base_ref` if present
(when triggered by a `pull_request`). Otherwise defaults to the repo's
default branch. Set in case you want to override this behaviour.
As a workaround, checkout the base branch and regenerate the report.
This is very innefficient T-T and slow.
default: 'false'
It will try to download the generated artifact from this branch so make
sure `generate-artifacte: true` when the workflow is running on that
branch.
default: ${{ github.base_ref }}
outputs:
runs:
using: 'composite'
steps:
- name: Create report
if: inputs.comment-on-pr == 'true' || inputs.generate-artifact == 'true'
env:
COMMENT: ${{ inputs.comment-on-pr == }}
ARTIFACT_NAME: ${{ inputs.artifact-name }}
DO_COMPARISON: ${{ inputs.do-comparison }}
BASE_BRANCH: ${{ inputs.base-branch }}
JOB_NAME: ${{ inputs.job-name }}
run: |
. "$GITHUB_ACTION_PATH/utils.sh"
# Input validation
if [ "$DO_COMPARISON" = 'true' ] && [ -z "$JOB_NAME" ]; then
error 'job-name should be set if you want to generate a comparison report'
exit 1
fi
# Create Size Report
"$GITHUB_ACTION_PATH/create-report.sh" > report.json
# Nothing else to do
if [ "$COMMENT" != 'true' ]; then exit 0; fi
# Try to do a comparison report
if [ "$DO_COMPARISON" = 'true' ]; then
if "$GITHUB_ACTION_PATH/retrieve-old-report.sh" && [ -f old-report.json ]; then
log "Reporting on sizes and comparing to sizes in $HEAD_BRANCH"
"$GITHUB_ACTION_PATH/comment_on_pr.sh" report.json old-report.json
exit 0
else
error 'Failed to do comparison, fallback to posting the report without them'
fi
fi
# Just report values
log 'Reporting on sizes'
"$GITHUB_ACTION_PATH/comment_on_pr.sh" report.json
- name: Upload Artifact
uses: https://code.forgejo.org/forgejo/upload-artifact@v4
if: inputs.generate-artifact == 'true'
with:
path: report.json
name: ${{ inputs.artifact-name }}
- name: Comment Report
if: inputs.comment-on-pr == 'true'
env:
ARTIFACT_NAME: ${{ inputs.artifact-name }}
HEAD_BRANCH: ${{ inputs.base-branch }}
JOB_NAME: ${{ inputs.job-name }}
PRIVATE_REPO: ${{ inputs.private-repo-workaround }}
run: |
. "${GITHUB_ACTION_PATH}/utils.sh"
if "$GITHUB_ACTION_PATH/retrieve-old-report.sh" && [ -f old-report.json ]; then
log "Reporting on sizes and comparing to sizes in $HEAD_BRANCH"
group 'Old report data'
cat old-report.json
endgroup
"$GITHUB_ACTION_PATH/comment_on_pr.sh" report.json old-report.json
else
log 'Reporting on sizes'
"$GITHUB_ACTION_PATH/comment_on_pr.sh" report.json
fi

View file

@ -116,7 +116,7 @@ pr_number=$(echo "$prs" |
# Protect against running before a PR is made or if it is triggered on the main branch
if [ -z "$pr_number" ]; then
log "No PR created for this commit"
warn "No PR created for this commit"
exit 0
fi

View file

@ -1,6 +1,23 @@
#!/bin/sh
. "${GITHUB_ACTION_PATH}/utils.sh"
# USAGE: base_report_url
repo_info() {
curl -X GET \
-H "Authorization: token $GITHUB_TOKEN" \
-H 'accept: application/json' \
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY"
}
in_private_repo() {
test "$(repo_info | jq --raw-output '.private')" = 'true'
}
default_branch() {
repo_info | jq --raw-output '.default_branch'
}
# USAGE: base_report_url <BASE_BRANCH>
base_report_url() {
curl -X 'GET' \
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/tasks" \
@ -8,9 +25,10 @@ base_report_url() {
-H 'accept: application/json' |
jq --raw-output \
--arg name "$JOB_NAME" \
--arg head_branch "$HEAD_BRANCH" \
--arg head_branch "$1" \
'[.workflow_runs[] | select(.name == $name and .head_branch == $head_branch)] | first | .url'
}
# USAGE: has_report <REPORT_URL>
has_report() {
http_code=$(curl -X 'GET' -o /dev/null --silent -Iw '%{http_code}' \
@ -19,23 +37,11 @@ has_report() {
test "$http_code" = '200'
}
# If we have a previous report compare against it
if [ "$PRIVATE_REPO" = 'true' ]; then
log "In a private repo, downloading $HEAD_BRANCH to build the old report"
# If a base branch is not provided, use the default branch
base_branch=${BASE_BRANCH-$(default_branch)}
old=$(mktemp -d)
group 'Downloaded files'
curl -X 'GET' \
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/archive/$HEAD_BRANCH.tar.gz" \
-H "Authorization: token $GITHUB_TOKEN" |
tar -zvx --strip-components=1 -C "$old"
endgroup
(cd "$old" && "$GITHUB_ACTION_PATH/create-report.sh") >old-report.json
exit 0
elif [ "$JOB_NAME" ] && [ "$HEAD_BRANCH" ]; then
url=$(base_report_url)
if [ "$(in_private_repo)" != 'true' ] && [ "$JOB_NAME" ]; then
url=$(base_report_url "$base_branch")
log "Found previous run at: $url"
report_url="$url/artifacts/$ARTIFACT_NAME"
@ -46,11 +52,28 @@ elif [ "$JOB_NAME" ] && [ "$HEAD_BRANCH" ]; then
"$report_url" \
-H "Authorization: token $GITHUB_TOKEN" |
gunzip >old-report.json
log "Reporting on sizes and comparing to sizes in $HEAD_BRANCH"
log "Reporting on sizes and comparing to sizes in $base_branch"
exit 0
else
log "Failed to find previous report, expected at: $report_url"
fi
error "Failed to find previous report, expected at: $report_url"
fi
exit 1
warn "Couldn't retrieve old report:"
warn ' This usuially happens when running on private repos'
warn ' or when job-name is not set.'
warn
warn ' See the README for more details'
error "Falling back to slow method (checkout $base_branch and generate the report)"
old=$(mktemp -d)
group "Download files from $base_branch"
curl -X 'GET' \
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/archive/$base_branch.tar.gz" \
-H "Authorization: token $GITHUB_TOKEN" |
tar -zvx --strip-components=1 -C "$old"
endgroup
(cd "$old" && "$GITHUB_ACTION_PATH/create-report.sh") >old-report.json
exit 0

View file

@ -2,6 +2,14 @@ log() {
echo "$@" >&2
}
warn() {
log "\e[0;33m[ERROR]:" "$@" "\e[0m"
}
error() {
log "\e[0;31m[WARN]:" "$@" "\e[0m"
}
group() {
log "::group::$1"
}