From e9525190b634bdea344ee99424119c8005d86326 Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:08:09 +0300 Subject: [PATCH 01/12] Delete .github/dependabot.yml --- .github/dependabot.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index d490a138..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,26 +0,0 @@ -version: 2 -updates: -- package-ecosystem: npm - directory: "/" - schedule: - interval: daily - time: "04:00" - pull-request-branch-name: - separator: "-" - open-pull-requests-limit: 10 - ignore: - - dependency-name: filesize - versions: - - 6.2.6 - - 6.3.0 - - dependency-name: adm-zip - versions: - - 0.5.3 -- package-ecosystem: github-actions - directory: "/" - schedule: - interval: daily - time: "04:00" - pull-request-branch-name: - separator: "-" - open-pull-requests-limit: 10 From 21436516010dabe2978facc2d42cc93c629c9860 Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:08:29 +0300 Subject: [PATCH 02/12] Update test action (download) --- .github/workflows/download.yml | 252 +++++---------------------------- 1 file changed, 37 insertions(+), 215 deletions(-) diff --git a/.github/workflows/download.yml b/.github/workflows/download.yml index 01247428..e2ebb937 100644 --- a/.github/workflows/download.yml +++ b/.github/workflows/download.yml @@ -5,235 +5,57 @@ on: branches: - master pull_request: + workflow_dispatch: jobs: wait: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Wait run: sleep 60 - download-latest: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact - path: artifact - - name: Test - run: cat artifact/sha | grep $GITHUB_SHA - download-search-workflow: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - name: artifact - path: artifact - workflow_search: true - - name: Test - run: cat artifact/sha | grep $GITHUB_SHA - download-branch: - runs-on: ubuntu-latest - needs: wait - if: github.ref == 'refs/heads/master' - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact - path: artifact - branch: master - - name: Test - run: cat artifact/sha | grep $GITHUB_SHA - download-pr: - runs-on: ubuntu-latest - needs: wait - if: github.ref != 'refs/heads/master' - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact - path: artifact - pr: ${{github.event.pull_request.number}} - - name: Test - run: cat artifact/sha | grep $GITHUB_SHA - download-commit: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact - path: artifact - commit: ${{ github.event.workflow_run.head_sha }} - - name: Test - run: cat artifact/sha | grep $GITHUB_SHA - download-multiple: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - - name: Test - run: | - cat artifact/sha | grep $GITHUB_SHA - cat artifact1/sha1 | grep $GITHUB_SHA - cat artifact2/sha2 | grep $GITHUB_SHA - download-regexp: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact. - name_is_regexp: true - - name: Test - run: | - cat artifact1/sha1 | grep $GITHUB_SHA - cat artifact2/sha2 | grep $GITHUB_SHA - ! test -d artifact/artifact - ! test -f artifact.zip - download-empty-conclusion: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact - path: artifact - workflow_conclusion: - - name: Test - run: cat artifact/sha | grep $GITHUB_SHA - download-skip-unpack: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact - path: artifact - skip_unpack: true - - name: Test - run: | - test -d artifact - test -f artifact/artifact.zip - ! test -d artifact/artifact - ! test -f artifact.zip - unzip -l artifact/artifact.zip - download-dry-run-exists: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - id: download - uses: ./ - with: - workflow: upload.yml - name: artifact - path: artifact - dry_run: true - - name: Test - run: test ${{ steps.download.outputs.dry_run }} == true - download-dry-run-not-exists: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - id: download - uses: ./ - with: - workflow: upload.yml - name: not-artifact - path: artifact - dry_run: true - - name: Test - run: test ${{ steps.download.outputs.dry_run }} == false - download-with-check-artifacts: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact - path: artifact - check_artifacts: true - - name: Test - run: cat artifact/sha | grep $GITHUB_SHA - download-with-search-artifacts: - runs-on: ubuntu-latest + + download: + runs-on: ubuntu-24.04 needs: wait + strategy: + matrix: + type: [latest, search-workflow, branch, pr, commit, multiple, regexp, empty-conclusion, skip-unpack, dry-run-exists, dry-run-not-exists, with-check-artifacts, with-search-artifacts, regexp-with-search-artifacts] steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@v4 + - name: Download uses: ./ with: workflow: upload.yml name: artifact path: artifact - search_artifacts: true - - name: Test - run: cat artifact/sha | grep $GITHUB_SHA - download-regexp-with-search-artifacts: - runs-on: ubuntu-latest - needs: wait - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Download - uses: ./ - with: - workflow: upload.yml - name: artifact. - name_is_regexp: true - path: artifact - search_artifacts: true + type: ${{ matrix.type }} + branch: ${{ matrix.type == 'branch' && 'master' || '' }} + pr: ${{ matrix.type == 'pr' && github.event.pull_request.number || '' }} + commit: ${{ matrix.type == 'commit' && github.event.workflow_run.head_sha || '' }} + workflow_conclusion: ${{ matrix.type == 'empty-conclusion' && '' || null }} + skip_unpack: ${{ matrix.type == 'skip-unpack' && 'true' || null }} + dry_run: ${{ matrix.type == 'dry-run-exists' && 'true' || matrix.type == 'dry-run-not-exists' && 'true' || null }} + search_artifacts: ${{ matrix.type == 'with-search-artifacts' || matrix.type == 'regexp-with-search-artifacts' && 'true' || null }} + name_is_regexp: ${{ matrix.type == 'regexp' || matrix.type == 'regexp-with-search-artifacts' && 'true' || null }} + check_artifacts: ${{ matrix.type == 'with-check-artifacts' && 'true' || null }} + - name: Test run: | - cat artifact/artifact1/sha1 | grep $GITHUB_SHA - cat artifact/artifact2/sha2 | grep $GITHUB_SHA - ! test -d artifact/artifact/artifact - ! test -f artifact/artifact.zip + if [[ "${{ matrix.type }}" == "multiple" ]]; then + cat artifact/sha | grep $GITHUB_SHA + cat artifact1/sha1 | grep $GITHUB_SHA + cat artifact2/sha2 | grep $GITHUB_SHA + elif [[ "${{ matrix.type }}" == "regexp" || "${{ matrix.type }}" == "regexp-with-search-artifacts" ]]; then + cat artifact/artifact1/sha1 | grep $GITHUB_SHA + cat artifact/artifact2/sha2 | grep $GITHUB_SHA + ! test -d artifact/artifact/artifact + ! test -f artifact/artifact.zip + elif [[ "${{ matrix.type }}" == "dry-run-exists" ]]; then + test ${{ steps.download.outputs.dry_run }} == true + elif [[ "${{ matrix.type }}" == "dry-run-not-exists" ]]; then + test ${{ steps.download.outputs.dry_run }} == false + else + cat artifact/sha | grep $GITHUB_SHA + fi From 8d5671128bcb4d9c41cc97602f4cd00846f2d424 Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:08:44 +0300 Subject: [PATCH 03/12] Update test action (upload) --- .github/workflows/upload.yml | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/.github/workflows/upload.yml b/.github/workflows/upload.yml index a135acb9..8e600ed7 100644 --- a/.github/workflows/upload.yml +++ b/.github/workflows/upload.yml @@ -5,35 +5,39 @@ on: branches: - master pull_request: + workflow_dispatch: jobs: upload: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 + steps: - name: Dump run: | mkdir artifact echo $GITHUB_SHA > artifact/sha - - name: Upload + + - name: Upload artifact uses: actions/upload-artifact@v4 with: name: artifact path: artifact + upload-multiple: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 + + strategy: + matrix: + artifact: [artifact1, artifact2] + sha: [sha1, sha2] steps: - name: Dump run: | - mkdir artifact1 artifact2 - echo $GITHUB_SHA > artifact1/sha1 - echo $GITHUB_SHA > artifact2/sha2 - - name: Upload first - uses: actions/upload-artifact@v4 - with: - name: artifact1 - path: artifact1 - - name: Upload second + mkdir ${{ matrix.artifact }} + echo $GITHUB_SHA > ${{ matrix.artifact }}/${{ matrix.sha }} + + - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: artifact2 - path: artifact2 + name: ${{ matrix.artifact }} + path: ${{ matrix.artifact }} From d5070f1d816acfe4f1c9f45211391107aa1eac04 Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:09:01 +0300 Subject: [PATCH 04/12] Update license --- LICENSE | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LICENSE b/LICENSE index 1cb6f054..0ed08fa1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -The MIT License (MIT) +MIT License -Copyright (c) 2020 Dawid Dziurla +Copyright (c) 2025 Dawid Dziurla Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 469d35d55d087b2c1321e3fc82fd4648bdca5662 Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:09:17 +0300 Subject: [PATCH 05/12] Update readme --- README.md | 112 ++++++++++++++++++++++++++---------------------------- 1 file changed, 53 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 743caa2a..61e4daf4 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,82 @@ -# Download workflow artifact GitHub Action +# Download Workflow Artifact GitHub Action An action that downloads and extracts uploaded artifacts associated with a given workflow and commit or other criteria. -Let's suppose you have a workflow with a job in it that at the end uploads an artifact using `actions/upload-artifact` action and you want to download this artifact in another workflow that is run after the first one. Official `actions/download-artifact` does not allow this. That's why I decided to create this action. By knowing only the workflow name and commit SHA or other details, you can download the previously uploaded artifact from different workflow associated with that commit or other criteria and use it. +### Problem + +Let's suppose you have a workflow with a job that uploads an artifact using the `actions/upload-artifact` action. If you want to download this artifact in another workflow that runs after the first one, you might run into issues, as the official `actions/download-artifact` action does not support this use case. This action allows you to download artifacts from a different workflow using details like the workflow name, commit SHA, or other criteria. ## Usage -> If `commit` or `pr` or `branch` or `run_id` or `workflow_conclusion` is not specified then the artifact from the most recent successfully completed workflow run will be downloaded. +> **Note**: If `commit`, `pr`, `branch`, `run_id`, or `workflow_conclusion` are not specified, the artifact from the most recent successfully completed workflow run will be downloaded. + +> **Important**: Do not specify `pr`, `commit`, `branch`, `run_id` together, or `workflow_conclusion` and `run_id` together. Pick just one of each or none. -**Do not specify `pr`, `commit`, `branch`, `run_id` together or `workflow_conclusion` and `run_id` together. Pick just one of each or none.** +### Example: ```yaml - name: Download artifact id: download-artifact uses: dawidd6/action-download-artifact@v7 with: - # Optional, GitHub token, a Personal Access Token with `public_repo` scope if needed - # Required, if the artifact is from a different repo - # Required, if the repo is private a Personal Access Token with `repo` scope is needed or GitHub token in a job where the permissions `action` scope set to `read` - github_token: ${{secrets.GITHUB_TOKEN}} - # Optional, workflow file name or ID - # If not specified, will be inferred from run_id (if run_id is specified), or will be the current workflow + # Optional: GitHub token. A Personal Access Token with `public_repo` scope if needed + # Required if the artifact is from a different repo or the repo is private. Use `repo` scope or GitHub token with `read` permissions. + github_token: ${{ secrets.GITHUB_TOKEN }} + + # Optional: Workflow file name or ID. Will be inferred from `run_id` if provided. workflow: workflow_name.yml - # If no workflow is set and workflow_search set to true, then the most recent workflow matching - # all other criteria will be looked up instead of using the current workflow + + # Optional: Set to true if you want to search for the most recent workflow matching the criteria. workflow_search: false - # Optional, the status or conclusion of a completed workflow to search for - # Can be one of a workflow conclusion: - # "failure", "success", "neutral", "cancelled", "skipped", "timed_out", "action_required" - # Or a workflow status: - # "completed", "in_progress", "queued" - # Use the empty string ("") to ignore status or conclusion in the search + + # Optional: Search for a specific workflow conclusion. + # Can be: "failure", "success", "neutral", "cancelled", "skipped", "timed_out", "action_required" + # Or a workflow status: "completed", "in_progress", "queued" workflow_conclusion: success - # Optional, will get head commit SHA - pr: ${{github.event.pull_request.number}} - # Optional, no need to specify if PR is - commit: ${{github.event.pull_request.head.sha}} - # Optional, will use the specified branch. Defaults to all branches + + # Optional: Pull request number. Will use head commit SHA if provided. + pr: ${{ github.event.pull_request.number }} + + # Optional: Commit SHA. Used for identifying the artifact. + commit: ${{ github.event.pull_request.head.sha }} + + # Optional: Branch to consider (defaults to all branches). branch: master - # Optional, defaults to all types + + # Optional: Event type (defaults to "push"). event: push - # Optional, will use specified workflow run - # use ${{ github.event.workflow_run.id }} when your action runs in a workflow_run event - # and wants to download from the triggering workflow run + + # Optional: Workflow run ID. Use `${{ github.event.workflow_run.id }}` in a `workflow_run` event. run_id: 1122334455 - # Optional, run number from the workflow + + # Optional: Run number from the workflow. run_number: 34 - # Optional, uploaded artifact name, - # will download all artifacts if not specified - # and extract them into respective subdirectories - # https://github.com/actions/download-artifact#download-all-artifacts - # is treated as a regular expression if input name_is_regexp is true - # will download only those artifacts with a name that matches this regular expression - # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions + + # Optional: Artifact name. Will download all artifacts if not specified. + # The name is treated as a regular expression if `name_is_regexp` is true. name: artifact_name - # Optional, name is treated as a regular expression if set true + + # Optional: Set to true if the artifact name is a regular expression. name_is_regexp: true - # Optional, a directory where to extract artifact(s), defaults to the current directory + + # Optional: Directory where to extract artifact(s). Defaults to the current directory. path: extract_here - # Optional, defaults to current repo + + # Optional: Repository to search for the artifact. Defaults to the current repo. repo: ${{ github.repository }} - # Optional, check the workflow run to whether it has an artifact - # then will get the last available artifact from the previous workflow - # default false, just try to download from the last one + + # Optional: Check whether the workflow run has an artifact. Default is false. check_artifacts: false - # Optional, search for the last workflow run whose stored an artifact named as in `name` input - # default false + + # Optional: Search for the last workflow run that stored an artifact with the specified name. search_artifacts: false - # Optional, choose to skip unpacking the downloaded artifact(s) - # default false + + # Optional: Choose to skip unpacking the downloaded artifact(s). Default is false. skip_unpack: false - # Optional, choose how to exit the action if no artifact is found - # can be one of: - # "fail", "warn", "ignore" - # default fail + + # Optional: How to exit the action if no artifact is found. Options: "fail", "warn", "ignore". Default is "fail". if_no_artifact_found: fail - # Optional, include forks when searching for artifacts - # default false - allow_forks: true + + # Optional: Include forks when searching for artifacts. Default is false. + allow_forks: false ``` - -## Troubleshooting - -### GLIBC_2.28 not found - -`v3` release of this action switched from `node16` to `node20` as runtime. -Node 20 requires `glibc>=2.28`. If your self-hosted runner has older `glibc`, pin to `v2` release, but note it won't receive any updates. From 1de185126bae7101bbc9499868a8dfcddf8180d2 Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:09:30 +0300 Subject: [PATCH 06/12] Update main action --- action.yml | 69 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/action.yml b/action.yml index e6994360..76f5cafe 100644 --- a/action.yml +++ b/action.yml @@ -1,103 +1,130 @@ name: Download workflow artifact -description: Download and extract an artifact associated with given workflow and commit or other criteria +description: Download and extract an artifact associated with a given workflow and commit or other criteria author: dawidd6 branding: icon: download color: blue + inputs: github_token: description: GitHub token required: false default: ${{ github.token }} + workflow: description: | Workflow name. - If not specified, will be inferred from run_id (if run_id is specified), or will be the current workflow + If not specified, will be inferred from `run_id` (if `run_id` is specified), or will default to the current workflow. required: false + workflow_search: description: | - Most recent workflow matching all other criteria will be looked up instead of using the current workflow + Look up the most recent workflow matching all other criteria instead of using the current workflow. - https://docs.github.com/de/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository + [GitHub Workflow Runs API](https://docs.github.com/rest/actions/workflow-runs#list-workflow-runs-for-a-repository) required: false default: false + workflow_conclusion: description: | - Wanted status or conclusion to search for in recent runs + The status or conclusion to search for in recent runs. - https://docs.github.com/de/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow + [GitHub Workflow Runs API](https://docs.github.com/rest/actions/workflow-runs#list-workflow-runs-for-a-workflow) required: false default: success + repo: - description: Repository name with owner (like actions/checkout) + description: Repository name with owner (e.g., `actions/checkout`) required: false default: ${{ github.repository }} + pr: description: Pull request number required: false + commit: description: Commit hash required: false + branch: description: Branch name required: false + event: description: Event type required: false + run_id: - description: Workflow run id + description: Workflow run ID required: false + run_number: description: Workflow run number required: false + name: - description: Artifact name (download all artifacts if not specified) + description: Artifact name (will download all artifacts if not specified) required: false + name_is_regexp: description: Treat artifact name as a regular expression and download only artifacts with matching names required: false default: false + path: - description: Where to unpack the artifact + description: Directory to unpack the artifact required: false default: "./" + allow_forks: - description: Allow forks + description: Allow forks to be considered in searches required: false default: false + check_artifacts: - description: Check workflow run whether it has an artifact + description: Check if the workflow run has an artifact required: false default: false + search_artifacts: - description: Search workflow runs for artifact with specified name + description: Search workflow runs for an artifact with the specified name required: false default: false + skip_unpack: - description: Choose to skip unpacking the downloaded artifact(s) + description: Skip unpacking the downloaded artifact(s) required: false default: false + dry_run: - description: Check the existence of artifact(s) without downloading + description: Check for the existence of artifact(s) without downloading them required: false + if_no_artifact_found: - required: false description: | - Choose how to exit the action if no artifact is found + Choose how to exit the action if no artifact is found: - fail, warn or ignore + - `fail` (default) + - `warn` + - `ignore` + required: false default: fail + outputs: error_message: - description: The error message, if an error occurs + description: The error message if an error occurs + # TODO: dry_run should be merged with found_artifact output dry_run: - description: Boolean output which is true if the dry run was successful and false otherwise + description: Boolean output indicating if the dry run was successful (true) or not (false) + found_artifact: - description: Boolean output which is true if the artifact was found and false otherwise + description: Boolean output indicating if the artifact was found (true) or not (false) + artifacts: description: JSON array with details about found artifacts + runs: using: node20 main: main.js From 5fb88485a47f522377784935e59e148defeb42ea Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:09:46 +0300 Subject: [PATCH 07/12] Update main script --- main.js | 266 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/main.js b/main.js index 7ff54a54..68d42c8f 100644 --- a/main.js +++ b/main.js @@ -1,22 +1,22 @@ -const core = require('@actions/core') -const github = require('@actions/github') -const artifact = require('@actions/artifact') -const AdmZip = require('adm-zip') -const filesize = require('filesize') -const pathname = require('path') -const fs = require('fs') +const core = require('@actions/core'); +const github = require('@actions/github'); +const artifact = require('@actions/artifact'); +const AdmZip = require('adm-zip'); +const filesize = require('filesize'); +const pathname = require('path'); +const fs = require('fs'); async function downloadAction(name, path) { - const artifactClient = artifact.create() + const artifactClient = artifact.create(); const downloadOptions = { createArtifactFolder: false - } + }; const downloadResponse = await artifactClient.downloadArtifact( name, path, downloadOptions - ) - core.setOutput("found_artifact", true) + ); + core.setOutput("found_artifact", true); } async function getWorkflow(client, owner, repo, runID) { @@ -24,47 +24,48 @@ async function getWorkflow(client, owner, repo, runID) { owner: owner, repo: repo, run_id: runID || github.context.runId, - }) - return run.data.workflow_id + }); + return run.data.workflow_id; } async function main() { try { - const token = core.getInput("github_token", { required: true }) - const [owner, repo] = core.getInput("repo", { required: true }).split("/") - const path = core.getInput("path", { required: true }) - const name = core.getInput("name") - const nameIsRegExp = core.getBooleanInput("name_is_regexp") - const skipUnpack = core.getBooleanInput("skip_unpack") - const ifNoArtifactFound = core.getInput("if_no_artifact_found") - let workflow = core.getInput("workflow") - let workflowSearch = core.getBooleanInput("workflow_search") - let workflowConclusion = core.getInput("workflow_conclusion") - let pr = core.getInput("pr") - let commit = core.getInput("commit") - let branch = core.getInput("branch") - let event = core.getInput("event") - let runID = core.getInput("run_id") - let runNumber = core.getInput("run_number") - let checkArtifacts = core.getBooleanInput("check_artifacts") - let searchArtifacts = core.getBooleanInput("search_artifacts") - const allowForks = core.getBooleanInput("allow_forks") - let dryRun = core.getInput("dry_run") - - const client = github.getOctokit(token) - - core.info(`==> Repository: ${owner}/${repo}`) - core.info(`==> Artifact name: ${name}`) - core.info(`==> Local path: ${path}`) + const token = core.getInput("github_token", { required: true }); + const [owner, repo] = core.getInput("repo", { required: true }).split("/"); + const path = core.getInput("path", { required: true }); + const name = core.getInput("name"); + const nameIsRegExp = core.getBooleanInput("name_is_regexp"); + const skipUnpack = core.getBooleanInput("skip_unpack"); + const ifNoArtifactFound = core.getInput("if_no_artifact_found"); + let workflow = core.getInput("workflow"); + let workflowSearch = core.getBooleanInput("workflow_search"); + let workflowConclusion = core.getInput("workflow_conclusion"); + let pr = core.getInput("pr"); + let commit = core.getInput("commit"); + let branch = core.getInput("branch"); + let event = core.getInput("event"); + let runID = core.getInput("run_id"); + let runNumber = core.getInput("run_number"); + let checkArtifacts = core.getBooleanInput("check_artifacts"); + let searchArtifacts = core.getBooleanInput("search_artifacts"); + const allowForks = core.getBooleanInput("allow_forks"); + let dryRun = core.getInput("dry_run"); + + const client = github.getOctokit(token); + + core.info(`==> Repository: ${owner}/${repo}`); + core.info(`==> Artifact name: ${name}`); + core.info(`==> Local path: ${path}`); if (!workflow && !workflowSearch) { - workflow = await getWorkflow(client, owner, repo, runID) + workflow = await getWorkflow(client, owner, repo, runID); } if (workflow) { - core.info(`==> Workflow name: ${workflow}`) + core.info(`==> Workflow name: ${workflow}`); } - core.info(`==> Workflow conclusion: ${workflowConclusion}`) + + core.info(`==> Workflow conclusion: ${workflowConclusion}`); const uniqueInputSets = [ { @@ -73,47 +74,47 @@ async function main() { "branch": branch, "run_id": runID } - ] + ]; uniqueInputSets.forEach((inputSet) => { - const inputs = Object.values(inputSet) - const providedInputs = inputs.filter(input => input !== '') + const inputs = Object.values(inputSet); + const providedInputs = inputs.filter(input => input !== ''); if (providedInputs.length > 1) { - throw new Error(`The following inputs cannot be used together: ${Object.keys(inputSet).join(", ")}`) + throw new Error(`The following inputs cannot be used together: ${Object.keys(inputSet).join(", ")}`); } - }) + }); if (pr) { - core.info(`==> PR: ${pr}`) + core.info(`==> PR: ${pr}`); const pull = await client.rest.pulls.get({ owner: owner, repo: repo, pull_number: pr, - }) - commit = pull.data.head.sha + }); + commit = pull.data.head.sha; //branch = pull.data.head.ref } if (commit) { - core.info(`==> Commit: ${commit}`) + core.info(`==> Commit: ${commit}`); } if (branch) { - branch = branch.replace(/^refs\/heads\//, "") - core.info(`==> Branch: ${branch}`) + branch = branch.replace(/^refs\/heads\//, ""); + core.info(`==> Branch: ${branch}`); } if (event) { - core.info(`==> Event: ${event}`) + core.info(`==> Event: ${event}`); } if (runNumber) { - core.info(`==> Run number: ${runNumber}`) + core.info(`==> Run number: ${runNumber}`); } - core.info(`==> Allow forks: ${allowForks}`) + core.info(`==> Allow forks: ${allowForks}`); if (!runID) { - const runGetter = workflow ? client.rest.actions.listWorkflowRuns : client.rest.actions.listWorkflowRunsForRepo + const runGetter = workflow ? client.rest.actions.listWorkflowRuns : client.rest.actions.listWorkflowRunsForRepo; // Note that the runs are returned in most recent first order. for await (const runs of client.paginate.iterator(runGetter, { owner: owner, @@ -122,66 +123,65 @@ async function main() { ...(branch ? { branch } : {}), ...(event ? { event } : {}), ...(commit ? { head_sha: commit } : {}), - } - )) { + })) { for (const run of runs.data) { if (runNumber && run.run_number != runNumber) { - continue + continue; } if (workflowConclusion && (workflowConclusion != run.conclusion && workflowConclusion != run.status)) { - continue + continue; } if (!allowForks && run.head_repository.full_name !== `${owner}/${repo}`) { - core.info(`==> Skipping run from fork: ${run.head_repository.full_name}`) - continue + core.info(`==> Skipping run from fork: ${run.head_repository.full_name}`); + continue; } if (checkArtifacts || searchArtifacts) { let artifacts = await client.paginate(client.rest.actions.listWorkflowRunArtifacts, { owner: owner, repo: repo, run_id: run.id, - }) + }); if (!artifacts || artifacts.length == 0) { - continue + continue; } if (searchArtifacts) { const artifact = artifacts.find((artifact) => { if (nameIsRegExp) { - return artifact.name.match(name) !== null + return artifact.name.match(name) !== null; } - return artifact.name == name - }) + return artifact.name == name; + }); if (!artifact) { - continue + continue; } } } - runID = run.id - core.info(`==> (found) Run ID: ${runID}`) - core.info(`==> (found) Run date: ${run.created_at}`) + runID = run.id; + core.info(`==> (found) Run ID: ${runID}`); + core.info(`==> (found) Run date: ${run.created_at}`); if (!workflow) { - workflow = await getWorkflow(client, owner, repo, runID) - core.info(`==> (found) Workflow: ${workflow}`) + workflow = await getWorkflow(client, owner, repo, runID); + core.info(`==> (found) Workflow: ${workflow}`); } - break + break; } if (runID) { - break + break; } } } if (!runID) { if (workflowConclusion && (workflowConclusion != 'in_progress')) { - return setExitMessage(ifNoArtifactFound, "no matching workflow run found with any artifacts?") + return setExitMessage(ifNoArtifactFound, "no matching workflow run found with any artifacts?"); } try { - return await downloadAction(name, path) + return await downloadAction(name, path); } catch (error) { - return setExitMessage(ifNoArtifactFound, "no matching artifact in this workflow?") + return setExitMessage(ifNoArtifactFound, "no matching artifact in this workflow?"); } } @@ -189,122 +189,122 @@ async function main() { owner: owner, repo: repo, run_id: runID, - }) + }); // One artifact if 'name' input is specified, one or more if `name` is a regular expression, all otherwise. if (name) { filtered = artifacts.filter((artifact) => { if (nameIsRegExp) { - return artifact.name.match(name) !== null + return artifact.name.match(name) !== null; } - return artifact.name == name - }) + return artifact.name == name; + }); if (filtered.length == 0) { - core.info(`==> (not found) Artifact: ${name}`) - core.info('==> Found the following artifacts instead:') + core.info(`==> (not found) Artifact: ${name}`); + core.info('==> Found the following artifacts instead:'); for (const artifact of artifacts) { - core.info(`\t==> (found) Artifact: ${artifact.name}`) + core.info(`\t==> (found) Artifact: ${artifact.name}`); } } - artifacts = filtered + artifacts = filtered; } - core.setOutput("artifacts", artifacts) + core.setOutput("artifacts", artifacts); if (dryRun) { if (artifacts.length == 0) { - core.setOutput("dry_run", false) - core.setOutput("found_artifact", false) - return + core.setOutput("dry_run", false); + core.setOutput("found_artifact", false); + return; } else { - core.setOutput("dry_run", true) - core.setOutput("found_artifact", true) - core.info('==> (found) Artifacts') + core.setOutput("dry_run", true); + core.setOutput("found_artifact", true); + core.info('==> (found) Artifacts'); for (const artifact of artifacts) { - const size = filesize(artifact.size_in_bytes, { base: 10 }) - core.info(`\t==> Artifact:`) - core.info(`\t==> ID: ${artifact.id}`) - core.info(`\t==> Name: ${artifact.name}`) - core.info(`\t==> Size: ${size}`) + const size = filesize(artifact.size_in_bytes, { base: 10 }); + core.info(`\t==> Artifact:`); + core.info(`\t==> ID: ${artifact.id}`); + core.info(`\t==> Name: ${artifact.name}`); + core.info(`\t==> Size: ${size}`); } - return + return; } } if (artifacts.length == 0) { - return setExitMessage(ifNoArtifactFound, "no artifacts found") + return setExitMessage(ifNoArtifactFound, "no artifacts found"); } - core.setOutput("found_artifact", true) + core.setOutput("found_artifact", true); for (const artifact of artifacts) { - core.info(`==> Artifact: ${artifact.id}`) + core.info(`==> Artifact: ${artifact.id}`); - const size = filesize(artifact.size_in_bytes, { base: 10 }) + const size = filesize(artifact.size_in_bytes, { base: 10 }); - core.info(`==> Downloading: ${artifact.name}.zip (${size})`) + core.info(`==> Downloading: ${artifact.name}.zip (${size})`); - let zip + let zip; try { zip = await client.rest.actions.downloadArtifact({ owner: owner, repo: repo, artifact_id: artifact.id, archive_format: "zip", - }) + }); } catch (error) { if (error.message.startsWith("Artifact has expired")) { - return setExitMessage(ifNoArtifactFound, "no downloadable artifacts found (expired)") + return setExitMessage(ifNoArtifactFound, "no downloadable artifacts found (expired)"); } else { - throw new Error(error.message) + throw new Error(error.message); } } if (skipUnpack) { - fs.mkdirSync(path, { recursive: true }) - fs.writeFileSync(`${pathname.join(path, artifact.name)}.zip`, Buffer.from(zip.data), 'binary') - continue + fs.mkdirSync(path, { recursive: true }); + fs.writeFileSync(`${pathname.join(path, artifact.name)}.zip`, Buffer.from(zip.data), 'binary'); + continue; } - const dir = name && !nameIsRegExp ? path : pathname.join(path, artifact.name) + const dir = name && !nameIsRegExp ? path : pathname.join(path, artifact.name); - fs.mkdirSync(dir, { recursive: true }) + fs.mkdirSync(dir, { recursive: true }); - const adm = new AdmZip(Buffer.from(zip.data)) + const adm = new AdmZip(Buffer.from(zip.data)); - core.startGroup(`==> Extracting: ${artifact.name}.zip`) + core.startGroup(`==> Extracting: ${artifact.name}.zip`); adm.getEntries().forEach((entry) => { - const action = entry.isDirectory ? "creating" : "inflating" - const filepath = pathname.join(dir, entry.entryName) + const action = entry.isDirectory ? "creating" : "inflating"; + const filepath = pathname.join(dir, entry.entryName); - core.info(` ${action}: ${filepath}`) - }) + core.info(` ${action}: ${filepath}`); + }); - adm.extractAllTo(dir, true) - core.endGroup() + adm.extractAllTo(dir, true); + core.endGroup(); } } catch (error) { - core.setOutput("found_artifact", false) - core.setOutput("error_message", error.message) - core.setFailed(error.message) + core.setOutput("found_artifact", false); + core.setOutput("error_message", error.message); + core.setFailed(error.message); } function setExitMessage(ifNoArtifactFound, message) { - core.setOutput("found_artifact", false) + core.setOutput("found_artifact", false); switch (ifNoArtifactFound) { case "fail": - core.setFailed(message) - break + core.setFailed(message); + break; case "warn": - core.warning(message) - break + core.warning(message); + break; case "ignore": default: - core.info(message) - break + core.info(message); + break; } } } -main() +main(); From 48188e5e5a940ea4e14aa1b5f2c6b36dc0d50d7a Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:10:21 +0300 Subject: [PATCH 08/12] Setup Dependabot --- .github/dependabot.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..e56501fc --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "npm" + directory: "/node_modules" + schedule: + interval: "daily" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" From 11a2b5ffbe9b35a764dc78b88795ec099825fb02 Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 15:11:29 +0300 Subject: [PATCH 09/12] Create .gitignore --- .gitignore | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..bcbfe97d --- /dev/null +++ b/.gitignore @@ -0,0 +1,129 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* From 037ad066293b2f1365bcd288ac7479de22f73c09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:01:09 +0000 Subject: [PATCH 10/12] build(deps): bump filesize from 9.0.11 to 10.1.6 Bumps [filesize](https://github.com/avoidwork/filesize.js) from 9.0.11 to 10.1.6. - [Changelog](https://github.com/avoidwork/filesize.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/avoidwork/filesize.js/compare/9.0.11...10.1.6) --- updated-dependencies: - dependency-name: filesize dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 11 +++++------ package.json | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77edb62f..b564add9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "@actions/core": "^1.11.1", "@actions/github": "^6.0.0", "adm-zip": "^0.5.16", - "filesize": "^9.0.11" + "filesize": "^10.1.6" } }, "node_modules/@actions/artifact": { @@ -1139,12 +1139,11 @@ } }, "node_modules/filesize": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-9.0.11.tgz", - "integrity": "sha512-gTAiTtI0STpKa5xesyTA9hA3LX4ga8sm2nWRcffEa1L/5vQwb4mj2MdzMkoHoGv4QzfDshQZuYscQSf8c4TKOA==", - "license": "BSD-3-Clause", + "version": "10.1.6", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", + "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", "engines": { - "node": ">= 0.4.0" + "node": ">= 10.4.0" } }, "node_modules/foreground-child": { diff --git a/package.json b/package.json index 80faa9ee..ea9d174d 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,6 @@ "@actions/core": "^1.11.1", "@actions/github": "^6.0.0", "adm-zip": "^0.5.16", - "filesize": "^9.0.11" + "filesize": "^10.1.6" } } From ec9640bcba6c5d00be2d9f522ac8ad66f720430e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:31:34 +0000 Subject: [PATCH 11/12] build(deps): bump @actions/artifact from 2.1.11 to 2.2.1 Bumps [@actions/artifact](https://github.com/actions/toolkit/tree/HEAD/packages/artifact) from 2.1.11 to 2.2.1. - [Changelog](https://github.com/actions/toolkit/blob/main/packages/artifact/RELEASES.md) - [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/artifact) --- updated-dependencies: - dependency-name: "@actions/artifact" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 9 ++++----- package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77edb62f..63e0770b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "action-download-artifact", "dependencies": { - "@actions/artifact": "^2.1.11", + "@actions/artifact": "^2.2.1", "@actions/core": "^1.11.1", "@actions/github": "^6.0.0", "adm-zip": "^0.5.16", @@ -14,10 +14,9 @@ } }, "node_modules/@actions/artifact": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-2.1.11.tgz", - "integrity": "sha512-V/N/3yM3oLxozq2dpdGqbd/39UbDOR54bF25vYsvn3QZnyZERSzPjTAAwpGzdcwESye9G7vnuhPiKQACEuBQpg==", - "license": "MIT", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-2.2.1.tgz", + "integrity": "sha512-V2cvKJ+Evg2n9Mcqz7kjbY2s0nd9MsBI2rw2E38pSEMv+Coo4i1sX0lyGcgSn1zyfVtmLwAI9LfuSptWF8PdaA==", "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", diff --git a/package.json b/package.json index 80faa9ee..1c4bcfdf 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "action-download-artifact", "main": "main.js", "dependencies": { - "@actions/artifact": "^2.1.11", + "@actions/artifact": "^2.2.1", "@actions/core": "^1.11.1", "@actions/github": "^6.0.0", "adm-zip": "^0.5.16", From 12f2b7297db401dea8f1308e29a32151f79ce27d Mon Sep 17 00:00:00 2001 From: blu3 Date: Thu, 9 Jan 2025 19:44:53 +0300 Subject: [PATCH 12/12] revert --- .github/workflows/upload.yml | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/upload.yml b/.github/workflows/upload.yml index 8e600ed7..a135acb9 100644 --- a/.github/workflows/upload.yml +++ b/.github/workflows/upload.yml @@ -5,39 +5,35 @@ on: branches: - master pull_request: - workflow_dispatch: jobs: upload: - runs-on: ubuntu-24.04 - + runs-on: ubuntu-latest steps: - name: Dump run: | mkdir artifact echo $GITHUB_SHA > artifact/sha - - - name: Upload artifact + - name: Upload uses: actions/upload-artifact@v4 with: name: artifact path: artifact - upload-multiple: - runs-on: ubuntu-24.04 - - strategy: - matrix: - artifact: [artifact1, artifact2] - sha: [sha1, sha2] + runs-on: ubuntu-latest steps: - name: Dump run: | - mkdir ${{ matrix.artifact }} - echo $GITHUB_SHA > ${{ matrix.artifact }}/${{ matrix.sha }} - - - name: Upload artifacts + mkdir artifact1 artifact2 + echo $GITHUB_SHA > artifact1/sha1 + echo $GITHUB_SHA > artifact2/sha2 + - name: Upload first + uses: actions/upload-artifact@v4 + with: + name: artifact1 + path: artifact1 + - name: Upload second uses: actions/upload-artifact@v4 with: - name: ${{ matrix.artifact }} - path: ${{ matrix.artifact }} + name: artifact2 + path: artifact2