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 # 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 ```yaml
- name: Generate size report - name: Generate size report
@ -15,6 +15,11 @@ Requires `nix`, `jq`, `curl`, `sed` and `coreutils` to be in path.
comment-on-pr: 'true' comment-on-pr: 'true'
generate-artifact: 'false' generate-artifact: 'false'
artifact-name: 'size-report.md' 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. For more details see the [action.yaml](./action.yml) file.

View file

@ -5,7 +5,7 @@ description: |
report. report.
You can post this report as a comment to the PR associated with the current 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 Requires `nix`, `jq`, `curl`, `sed`, `gunzip`, `tar` and `coreutils` to be in
the runner's path. the runner's path.
@ -19,75 +19,95 @@ description: |
comment-on-pr: 'true' comment-on-pr: 'true'
generate-artifact: 'false' generate-artifact: 'false'
artifact-name: 'size-report.md' artifact-name: 'size-report.md'
base-branch: ${{ github.base_ref }} # set to e.g. main if not triggered by a pull_request # If you want to enable comparisons set this to true
job-name: '' # set to the name of this job if you want to enable comparisons 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: inputs:
comment-on-pr: 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' default: 'true'
# Generate workflow artifact
generate-artifact: generate-artifact:
description: Export the generated markdown document as an artifact. description: Export the generated markdown document as a workflow artifact.
default: 'false' default: 'false'
artifact-name: artifact-name:
description: The name of the generated artifact. description: The name of the generated artifact.
default: report.json default: report.json
base-branch: # Comparison Report (comment only)
do-comparison:
description: | description: |
The name of the base branch, defaults to github.base_ref which is only When commenting on the PR compare the results with those in the base branch.
available in pull_request triggered workflows, for other workflows
specify it manually.
It will try to download the generated artifact from this branch so make This is a no-op when `comment-on-pr: false`.
sure `generate-artifacte: true` when the workflow is running on that
branch. It requires `job-name` to be set.
default: ${{ github.base_ref }} default: 'false'
job-name: job-name:
description: | description: |
The name of the job running this action. If not set, no comparisons can The name of the job running this action. If not set, no comparisons can
be made. be made.
default: '' default: ''
private-repo-workaround: base-branch:
description: | description: |
Forgejo doesn't support downloading artifacts through the API [see The name of the base branch, defaults to `github.base_ref` if present
codeberg.org/forgejo/forgejo#6315](https://codeberg.org/forgejo/forgejo/issues/6315). (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. It will try to download the generated artifact from this branch so make
sure `generate-artifacte: true` when the workflow is running on that
This is very innefficient T-T and slow. branch.
default: 'false' default: ${{ github.base_ref }}
outputs: outputs:
runs: runs:
using: 'composite' using: 'composite'
steps: steps:
- name: Create report - 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: | 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 "$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 - name: Upload Artifact
uses: https://code.forgejo.org/forgejo/upload-artifact@v4 uses: https://code.forgejo.org/forgejo/upload-artifact@v4
if: inputs.generate-artifact == 'true' if: inputs.generate-artifact == 'true'
with: with:
path: report.json path: report.json
name: ${{ inputs.artifact-name }} 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 # Protect against running before a PR is made or if it is triggered on the main branch
if [ -z "$pr_number" ]; then if [ -z "$pr_number" ]; then
log "No PR created for this commit" warn "No PR created for this commit"
exit 0 exit 0
fi fi

View file

@ -1,6 +1,23 @@
#!/bin/sh
. "${GITHUB_ACTION_PATH}/utils.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() { base_report_url() {
curl -X 'GET' \ curl -X 'GET' \
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/tasks" \ "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/tasks" \
@ -8,9 +25,10 @@ base_report_url() {
-H 'accept: application/json' | -H 'accept: application/json' |
jq --raw-output \ jq --raw-output \
--arg name "$JOB_NAME" \ --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' '[.workflow_runs[] | select(.name == $name and .head_branch == $head_branch)] | first | .url'
} }
# USAGE: has_report <REPORT_URL> # USAGE: has_report <REPORT_URL>
has_report() { has_report() {
http_code=$(curl -X 'GET' -o /dev/null --silent -Iw '%{http_code}' \ http_code=$(curl -X 'GET' -o /dev/null --silent -Iw '%{http_code}' \
@ -19,23 +37,11 @@ has_report() {
test "$http_code" = '200' test "$http_code" = '200'
} }
# If we have a previous report compare against it # If a base branch is not provided, use the default branch
if [ "$PRIVATE_REPO" = 'true' ]; then base_branch=${BASE_BRANCH-$(default_branch)}
log "In a private repo, downloading $HEAD_BRANCH to build the old report"
old=$(mktemp -d) if [ "$(in_private_repo)" != 'true' ] && [ "$JOB_NAME" ]; then
group 'Downloaded files' url=$(base_report_url "$base_branch")
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)
log "Found previous run at: $url" log "Found previous run at: $url"
report_url="$url/artifacts/$ARTIFACT_NAME" report_url="$url/artifacts/$ARTIFACT_NAME"
@ -46,11 +52,28 @@ elif [ "$JOB_NAME" ] && [ "$HEAD_BRANCH" ]; then
"$report_url" \ "$report_url" \
-H "Authorization: token $GITHUB_TOKEN" | -H "Authorization: token $GITHUB_TOKEN" |
gunzip >old-report.json 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 exit 0
else
log "Failed to find previous report, expected at: $report_url"
fi fi
error "Failed to find previous report, expected at: $report_url"
fi 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 echo "$@" >&2
} }
warn() {
log "\e[0;33m[ERROR]:" "$@" "\e[0m"
}
error() {
log "\e[0;31m[WARN]:" "$@" "\e[0m"
}
group() { group() {
log "::group::$1" log "::group::$1"
} }