From e54373b6168dbd9ffac0d8dec230548e6e3efda7 Mon Sep 17 00:00:00 2001 From: Chl Date: Tue, 27 Aug 2024 18:49:54 +0200 Subject: [PATCH] Initial commit --- LICENSE | 8 ++++++ README.md | 47 +++++++++++++++++++++++++++++++++++ action.yml | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 action.yml diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..58caeec --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +Zero-Clause BSD +============= + +Copyright (C) 2024 by Chl + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..218cf00 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# `@actions/upload-artifact-with-wget` + +Upload [actions artifacts](https://forgejo.org/docs/next/user/actions/#artifacts) from your workflows runs. + +This is a tryout to make a lighter version of +[actions/upload-artifact](https://github.com/actions/upload-artifact) made for +simple workflows where most of the work could run on a alpine shell and only +the artifact uploading required a full blown NodeJS container. + +## Usage + +This actions won't copy all the features of the original NodeJS version but +please report differences on the main ones. + +### Inputs + +```yaml +- uses: actions/upload-artifact@v4 + with: + # Name of the artifact to upload. + # Optional. Default is 'artifact' + name: + + # A file, directory or wildcard pattern that describes what to upload + # Required. + path: +``` + +### Outputs + +| Name | Description | Example | +| - | - | - | +| `artifact-id` | GitHub ID of an Artifact, can be used by the REST API | `1234` | + +## Examples + +### Upload an Individual File + +```yaml +steps: +- run: mkdir -p path/to/artifact +- run: echo hello > path/to/artifact/world.txt +- uses: actions/upload-artifact@v4 + with: + name: my-artifact + path: path/to/artifact/world.txt +``` diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..3a096af --- /dev/null +++ b/action.yml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: 0BSD +name: "Upload artifact with wget" +author: "Chl " + +description: | + Upload an artifact for a workflow. + + This is a far lighter version of upload-artifact, it only need a shell, zip + and the full version of wget (unfortunately, as of 2024-08-26, the busybox + variant isn't capable of using the PUT method). + +inputs: + name: + description: 'Artifact name' + default: 'artifact' + path: + description: 'A file, directory or wildcard pattern that describes what to upload' + required: true + +outputs: + artifact-id: + description: A unique identifier for the artifact that was just uploaded. Empty if the artifact upload failed. + +runs: + steps: + - name: Upload artifact (using v4) + run: | + # Some optional help for debugging. + set -ex + + # Zip the files + printf "%s\n" "$GITHUB_OUTPUT" + printf "%s\n" ${{ inputs.path }} + return + + # General note: + # instead of using a proper JSON parser like 'jq', we use the readily + # available 'sed' in order to help this code being more easily reusable + # (at the cost of a breaking if the JSON formating happens to + # change...) + + # We extract the 'Actions.Results:22:33' from ACTIONS_RUNTIME_TOKEN + # (note: base64 -d doesn't like when the '==' padding is missing, so 2>/dev/null and relying on the piping to forget about non-zero return code...) + read WORKFLOW_RUN_BACKEND_ID WORKFLOW_JOB_RUN_BACKEND_ID </dev/null | sed 's/.*Actions.Results:\([^:]\+\):\([^:" ]\+\).*/\1 \2/' ) + EOF + + # Get the upload URL + RESPONSE="$( wget -O - \ + --header 'Content-Type:application/json' \ + --header "Authorization: Bearer $GITHUB_TOKEN" \ + --post-data "$( printf '{"version":4, "name":"%s", "workflow_run_backend_id":"%s", "workflow_job_run_backend_id":"%s"}' "$MYFILENAME" "$WORKFLOW_RUN_BACKEND_ID" "$WORKFLOW_JOB_RUN_BACKEND_ID" )" \ + "$GITHUB_SERVER_URL"/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact + )" + # We get a JSON with an signedUploadUrl similar to : + # https://entrepot.xlii.si/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=yWWEI8tIIECp8D7E5TVh4_6G2pZxWaVdQcSYaCsx5s0=&expires=2024-08-26+07%3A20%3A49.886890537+%2B0200+CEST&artifactName=mymodule-1.2.3.zip&taskID=63 + SIGNED_UPLOAD_URL="$( echo "$RESPONSE" | sed -n 's/.*"signedUploadUrl" *: *"\([^"]\+\)".*/\1/p' )" + + # Upload our file + # (note: adding '&comp=block' at the end of the URL) + wget --method PUT --body-file "$MYFILENAME" "$SIGNED_UPLOAD_URL&comp=block" + + # Finalize the artifact + RESPONSE="$( wget -O - \ + --header 'Content-Type:application/json' \ + --header "Authorization: Bearer $GITHUB_TOKEN" \ + --post-data "$( printf '{"hash":"sha256:%s", "name":"%s", "size":"%d", "workflow_run_backend_id":"%s", "workflow_job_run_backend_id":"%s"}' "$( sha256sum $MYFILENAME | sed 's/[[:space:]]\+.*//' )" "$MYFILENAME" "$( stat -c %s $MYFILENAME )" "$WORKFLOW_RUN_BACKEND_ID" "$WORKFLOW_JOB_RUN_BACKEND_ID" )" \ + "$GITHUB_SERVER_URL"/twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact + )" + + # Store the outputs + echo artifact-id="$( echo "$RESPONSE" | sed -n 's/.*"artifactId" *: *"\([^"]\+\)".*/\1/p' )" >> $GITHUB_OUTPUT