jfrog / setup-jfrog-cli

Set up JFrog CLI in your GitHub Actions workflow
Apache License 2.0
249 stars 80 forks source link

Getting --url option is mandatory error for ping and upload commands #94

Open mackaybeth opened 1 year ago

mackaybeth commented 1 year ago

Describe the bug

I'm trying to upload in a GitHub Action with jfrog rt upload --spec build/upload_spec.json, and I get the --url option is mandatory error. I tried configuring the JFrog CLI with environment variables (JF_URL and JF_TOKEN), and also with the Config Token exported from my local setup (where the command works).

I tried even just running jfrog rt ping, and that also gives the same error.

If I add --url on on the command line, the ping command works, but the upload does not (get 401 Unauthorized).

Current behavior

This is the output from the jfrog/setup-jfrog-cli@v3 step

Run jfrog/setup-jfrog-cli@v3
  with:
    version: [2](https://github.com/REDACTED/actions/runs/4582980103/jobs/8093546472#step:12:2).[3](https://github.com/REDACTED/actions/runs/4582980103/jobs/8093546472#step:12:3)5.0
  env:
    BRANCH_NAME: 2/merge
    CI: true
    CHANGE_ID: 2
    BUILD_NUMBER: 18
    CHANGE_TARGET: master
    GITHUB_TOKEN: ***
    JFROG_CLI_LOG_LEVEL: DEBUG
    AWS_DEFAULT_REGION: us-east-2
    AWS_REGION: us-east-2
    AWS_ACCESS_KEY_ID: ***
    AWS_SECRET_ACCESS_KEY: ***
    AWS_SESSION_TOKEN: ***
    pythonLocation: /opt/actions-runner/_work/_tool/Python/3.7.16/x6[4](https://github.com/REDACTED/actions/runs/4582980103/jobs/8093546472#step:12:4)
    PKG_CONFIG_PATH: /opt/actions-runner/_work/_tool/Python/3.7.16/x64/lib/pkgconfig
    Python_ROOT_DIR: /opt/actions-runner/_work/_tool/Python/3.7.16/x64
    Python2_ROOT_DIR: /opt/actions-runner/_work/_tool/Python/3.7.16/x64
    Python3_ROOT_DIR: /opt/actions-runner/_work/_tool/Python/3.7.16/x64
    LD_LIBRARY_PATH: /opt/actions-runner/_work/_tool/Python/3.7.16/x64/lib
    JF_ENV_1: 
Setup JFrog CLI
  Downloading JFrog CLI from https://releases.jfrog.io/artifactory/jfrog-cli/v2/2.3[5](https://github.com/REDACTED/actions/runs/4582980103/jobs/8093546472#step:12:5).0/jfrog-cli-linux-amd[6](https://github.com/REDACTED/actions/runs/4582980103/jobs/8093546472#step:12:6)4/jfrog

This is the out put from my next step, which runs the JFrog CLI command

Run jfrog rt upload --spec build/upload_spec.json
11:56:56 [Debug] JFrog CLI version: 2.35.0
11:56:56 [Debug] OS/Arch: linux/amd64
11:56:56 [Debug] Locking config file to run config Clear command.
11:56:56 [Debug] Creating lock in: /home/ubuntu/.jfrog/locks/config
11:56:56 [Debug] Releasing lock: /home/ubuntu/.jfrog/locks/config/jfrog-cli.conf.lck.5874.1680350216994187067
11:56:56 [Debug] Config Clear command completed successfully. config file is released.
Error: 6 [Error] the --url option is mandatory
Error: Process completed with exit code 1.

When I run the jfrog rt ping command locally with the JFROG_CLI_LOG_LEVEL="DEBUG" flag set, I see successful HTTP GET commands and 200 responses.

Reproduction steps

I have this in my action:

      - name: Setup Jfrog CLI
        uses: jfrog/setup-jfrog-cli@v3
        env:
          JF_ENV_1: ${{ secrets.JF_SECRET_ENV_1 }}
#          JF_URL: ${{ secrets.ARTIFACTORY_URL }}
#          JF_ACCESS_TOKEN: ${{ secrets.ARTIFACTORY_TOKEN }}
      - name: Upload to Artifactory
        shell: bash
        run: jfrog rt upload --spec build/upload_spec.json

When I run the action, the Upload to Artifactory step fails with the error the --url option is mandatory. If I add the URL, I get 401 Unauthorized errors (which is the same thing that happens when I run the jfrog rt upload command locally with that flag). The same thing happens if I run with the Config Token (as shown above in the snip), or with the commented out JF_URL and JF_ACCESS_TOKEN env vars instead. I do not try to run with all 3 env vars set.

I created the admin-level access token in the Artifactory UI. We run a self-hosted installation of Artifactory, and do not use JFrog Platform.

Expected behavior

I expect to see something like this

{
  "status": "success",
  "totals": {
    "success": 1,
    "failure": 0
  }

And find my artifact in Artifactory.

Setup JFrog CLI version

@v3 (as of today, this is 3.2.0)

JFrog CLI version

I'm using the default, which is 2.35.0 as of today.

Workflow operating system type and version

linux/amd64 self-hosted runner, ubuntu-jammy-22.04

JFrog Artifactory version (if relevant)

self-hosted, 7.41.7

JFrog Xray version (if relevant)

N/A

sverdlov93 commented 1 year ago

Hi @mackaybeth , Thanks for reporting this issue. Are you sure that you added the secrets correctly on the secrets section under /settings/secrets/actions?

JF_ENV_1: ${{ secrets.JF_SECRET_ENV_1 }} OR

JF_URL: ${{ secrets.ARTIFACTORY_URL }}
JF_ACCESS_TOKEN: ${{ secrets.ARTIFACTORY_TOKEN }}

Can you try running an echo command to print the value of secrets.ARTIFACTORY_URL on runtime? Also, can you add the JFROG_CLI_LOG_LEVEL="DEBUG" env to the Action and provide the full logs? It looks like the JFrog CLI is not getting your Credentials and that's why it asks for url.

shelling21 commented 11 months ago

I also experience this issue in my GitHub pipelines. But it doesn't occur always. Usually after a retry it works. If I enable JFROG_CLI_LOG_LEVEL="DEBUG" I get the following output.

Run jf rt ping 13:55:15 [Debug] JFrog CLI version: 2.50.4 13:55:15 [Debug] OS/Arch: windows/amd64 13:55:15 [Debug] Locking config file to run config Clear command. 13:55:15 [Debug] Creating lock in: C:\windows\ServiceProfiles\NetworkService.jfrog\locks\config 13:55:15 [Debug] Releasing lock: C:\windows\ServiceProfiles\NetworkService.jfrog\locks\config\jfrog-cli.conf.lck.1952.1701348915532607900 13:55:15 [Debug] Config Clear command completed successfully. config file is released. Error: 5 [Error] the --url option is mandatory

yahavi commented 11 months ago

@shelling21 It looks like a race condition - the config got cleared before the JFrog CLI read it. Could you please provide an outline of the workflow you used?

shelling21 commented 11 months ago

I'm curious where the race condition can take place. We use this in a pipeline that performs a hardware-in-the-loop test on a windows host which take about 3-4 minutes to complete. It looks like:

---
name: Hardware in the loop test

on:
  workflow_call:
    inputs:
      buildNumber:
        description: GitHub build number
        required: true
        type: string
      configuration:
        description: Use a Debug or Release configuration in hil test
        required: true
        type: string
      testTag:
        description: Test tag
        required: true
        type: string

permissions:
  contents: read

env:
  GIT_COMMIT: ${{ github.sha }}
  JFROG_CLI_LOG_LEVEL: DEBUG

jobs:
    steps:
      - name: Checkout repository
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          persist-credentials: false
          submodules: false
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Setup jfrog-cli
        uses: jfrog/setup-jfrog-cli@901bb9632db90821c2d3f076012bdeaf66598555 # v3.4.1
        env:
            JF_ENV_1: ${{ secrets.ARTIFACTORY_TOKEN }}

      - name: Download xxx tool
        run: jf rt download generic-external/xxx.exe "xxx.exe"

      - name: Download embedded builds
        env:
          JFROG_CLI_BUILD_NAME: pkgs-embedded+arm-none-eabi
        run: jf rt download --build pkgs-embedded+arm-none-eabi/${{ inputs.buildNumber }} "*/(*)/${{ inputs.configuration }}/(*)" "install/{1}/${{ inputs.configuration }}/{2}"

      - name: Download tools
        env:
          JFROG_CLI_BUILD_NAME: pkgs-embedded+i686-w64-mingw32
        run: jf rt download --build pkgs-embedded+i686-w64-mingw32/${{ inputs.buildNumber }} "*/(*)/Debug/(*)" "install/tools/{1}/Debug/{2}"

      - name: Program device 1
        run: |
          <Programming commands>

      - name: Program device 2
        run: |
          <Programming commands>

      - name: Reset test setup
        run: |
          <Reset commands>

      - name: Sleep for 3 seconds
        run: Start-Sleep -s 3
        shell: powershell

      - name: Run hardware-in-the-loop tests
        run: >
          <Run hardware-in-the-loop commands>

      - name: Upload test report
        if: success() || failure()
        env:
          DEST_PATH: pkgs-embedded-snapshot/nic/${{ github.head_ref || github.ref_name }}/${{ github.run_number }}/
          JFROG_CLI_BUILD_NAME: pkgs-embedded+smoke-test-output-${{ inputs.testTag }}
        run: |
          jf rt ping
          jf rt build-collect-env
          jf rt upload "integration_test_output/*" "${{ env.DEST_PATH }}"
          jf rt build-publish

(I removed the unrelevant parts) Usually the process fails on the jf commands in the last step.

shelling21 commented 11 months ago

@yahavi : I'm really curious what the problem can be and how to resolve it. Currently our CI/CD pipeline is unstable because of this issue and I would like to fix that.

sverdlov93 commented 10 months ago

Hi @shelling21 and @mackaybeth, We believe that the issue was fixed on https://github.com/jfrog/setup-jfrog-cli/releases/tag/v3.4.2 so feel free to update to the latest version. Looking forward to your feedback on it.

shelling21 commented 10 months ago

Hi @sverdlov93,

I've updated the setup-jfrog-cli action to v3.4.2 but it does not seem to resolve the issue. The same issue happens. The problem seems to be most likely to trigger when there is a longer time between the setup-jfrog-cli action and actually using the jf command in later steps. In our use case we're downloading some binaries with the jf cli, then programming a hw target, run some tests, and then upload the test results to artifactory. Usually the failures are happening in the last upload step. It looks like some token gets expired.

For now I got a workable solution to do a setup-jfrog-cli action before each time I use jf cli. Then when the token seems to get renewed when necessary. If there is already a config with a valid token it passes the action in 0s.

sverdlov93 commented 10 months ago

Hi @shelling21 , Are you getting the same debug logs with [Debug] Config Clear command completed successfully. config file is released. that happens before your last command? can you share again the full logs?

shelling21 commented 10 months ago

@sverdlov93: I've sent you the logs via e-mail (from your GitHub profile)

sverdlov93 commented 10 months ago

Hi @shelling21 , I see from your logs that you are using an old version of jfrog/setup-jfrog-cli. The latest is v3.5.1 and it should use the version v2.52.7 of JFrog CLI.

On your logs it was:

jfrog/setup-jfrog-cli@901bb9632db90821c2d3f076012bdeaf66598555
with:
 version: 2.50.4
ssplatt commented 3 months ago

I'm running into this today with

- uses: jfrog/setup-jfrog-cli@v4
        with:
          version: latest

putting jf config show in the action does show a proper config

sverdlov93 commented 3 months ago

@ssplatt , how do you configure the credentials for the task? Can you share the full yaml you use?

here is an example:

- uses: jfrog/setup-jfrog-cli@v4
  env:
    # JFrog platform url (for example: https://acme.jfrog.io)
    JF_URL: ${{ vars.JF_URL }}

    # Basic authentication credentials
    JF_USER: ${{ secrets.JF_USER }}
    JF_PASSWORD: ${{ secrets.JF_PASSWORD }}
    or
    # JFrog Platform access token
    JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }}
- run: |
    jf rt ping
ssplatt commented 3 months ago

Jf_url and jf_access_token as env vars

sverdlov93 commented 3 months ago

is there a chance that your env URL is empty? can you add another step before the jfrog-cli step that prints ${{ vars.JF_URL }} to the prompt?

alexquitiaquez commented 2 weeks ago

We've been having the same issue recently in enterprise at the Post Download/Upload cleanup, here down some log,

Download Artefacts from Artifactory ... Run jfrog/setup-jfrog-cli@v4 with: download-repository: jfrog-cli-remote version: 2.67.0 disable-job-summary: false disable-auto-build-publish: false env: product-name: product-fake component-name: xxxxxx-service version: 1729012922-xxxxx archive-extension: jar artifact-path: artefact-release project-name: ProductService docker-registry-source: docker.registry.com artifactory-url: https://artifacts.server.com artifactory-serverid: artifactory reports-format: ALL ARTIFACTORY_API_KEY: ARTIFACTORY_USER: JF_URL: https://artifacts.server.com/ JF_USER: JF_PASSWORD: Setup JFrog CLI Downloading JFrog CLI from https://artifacts.artifacts.server.com/artifactory/jfrog-cli-remote/v2/2.67.0/jfrog-cli-linux-amd64/jfrog /opt/hostedtoolcache/jf/2.67.0/x64/jf config add setup-jfrog-cli-server --url https://artifacts.artifacts.server.com/ --interactive=false --overwrite=true --user --password [Warn] You are using JFrog CLI version 2.67.0, however version 2.71.1 is available. To install the latest version, visit: https://jfrog.com/getcli To see the release notes, visit: https://github.com/jfrog/jfrog-cli/releases To avoid this message, set the JFROG_CLI_AVOID_NEW_VERSION_WARNING variable to TRUE ...

Post Download Artefacts from Artifactory Post job cleanup. Post job cleanup. Checking connection to JFrog Artifactory /opt/hostedtoolcache/jf/2.67.0/x64/jf rt ping (https://github.com/Enterprise/xxxxxx-service/actions/runs/11521703694/job/32075950521#step:9:3):31 [Info] Trace ID for JFrog Platform logs: 4f3268f7c9abd8e7 Error: 1 [Error] the --url option is mandatory Warning: An error occurred while trying to connect to Artifactory: Error: JFrog CLI exited with exit code 1. Skipping Build Info post tasks. Cleanup JFrog CLI servers configuration /opt/hostedtoolcache/jf/2.67.0/x64/jf c rm --quiet

JF_URL var is not empty at the Download step, but it seems it is empty an the Post job cleanup.

I guess it comes from this function checkConnectionToArtifactory at the cleanup.js, but we don't understand why. https://github.com/jfrog/setup-jfrog-cli/blob/master/lib/cleanup.js#L163

function checkConnectionToArtifactory() {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            core.startGroup('Checking connection to JFrog Artifactory');
            const pingResult = yield utils_1.Utils.runCliAndGetOutput(['rt', 'ping']);
            if (pingResult.trim() !== 'OK') {
                core.debug(`Ping result: ${pingResult}`);
                core.warning('Could not connect to Artifactory. Skipping Build Info post tasks.');
                return false;
            }
            return true;
        }
        catch (error) {
            core.warning(`An error occurred while trying to connect to Artifactory: ${error}. Skipping Build Info post tasks.`);
            return false;
        }
        finally {
            core.endGroup();
        }
    });
}

Thanks

sverdlov93 commented 2 weeks ago

Hi @alexquitiaquez, thanks for reaching out!

Quick question: is this issue causing the workflow to fail, or is it just displaying a warning?

The JF_URL and similar environment variables are not directly used by the postJob task. Instead, it relies on the server configuration set up by the setup-jfrog-cli task, which is stored locally on the runner VM during the run. It appears that the local JFrog configuration may have been removed between steps, affecting the cleanup process.

Could you share your workflow YAML file for further troubleshooting? Could you also explain the following fields I see on your envs:

artifactory-url: https://artifacts.server.com/
artifactory-serverid: artifactory
ARTIFACTORY_API_KEY: ***
ARTIFACTORY_USER: ***
alexquitiaquez commented 2 weeks ago

Hi @sverdlov93 , No, the workflow doesn't fail, we just have a warning under the Annotations section, but I think it's because the warning on the next line during the execution, not because the error message. The error message is only shown in the logs.

Error: 1 [Error] the --url option is mandatory Warning: An error occurred while trying to connect to Artifactory: Error: JFrog CLI exited with exit code 1. Skipping Build Info post tasks.

The annoying thing is having the same warning as many times as you use the action. In this example of a multilayer workflow, I mean a reusable workflow that uses other reusable workflows, the action is used by 5 different jobs,

Annotations 5 warnings ci-with-gradle / build-and-test / build-and-test An error occurred while trying to connect to Artifactory: Error: JFrog CLI exited with exit code 1. Skipping Build Info post tasks. ci-with-gradle / deploy / deploy An error occurred while trying to connect to Artifactory: Error: JFrog CLI exited with exit code 1. Skipping Build Info post tasks. ci-with-gradle / smoke-test / smoke-test An error occurred while trying to connect to Artifactory: Error: JFrog CLI exited with exit code 1. Skipping Build Info post tasks. ci-with-gradle / generate-lst / generate-lst An error occurred while trying to connect to Artifactory: Error: JFrog CLI exited with exit code 1. Skipping Build Info post tasks. ci-with-gradle / static-analysis / static-analysis An error occurred while trying to connect to Artifactory: Error: JFrog CLI exited with exit code 1. Skipping Build Info post tasks.

Sorry, I can't share images of my corporate environment.

alexquitiaquez commented 2 weeks ago

About your other questions,

  1. Could you share your workflow YAML file for further troubleshooting? We have an internal composite action wrapping the setup-jfrog-cli, we can call it here wrapper-jfrog-cli-action it receives values through inputs, here below the main parts of the action.yml,
    
    name: "Upload|Download file(s) to|from Artifactory and/or Docker_Pull|Build_Docker_Create|Build_Publish|Docker_Promote Docker image and/or build_scan and/or bundle_create|bundle_Promote Release Bundle"
    description: "Artifactory"
    inputs:
    local-file-path:
    required: false
    description: "Local file pattern"
    destination-file-path:
    required: false
    description: "Destination file pattern"
    artifactory-action:
    required: true
    description: "upload, download or docker_promote"
    artifactory-serverid:
    required: false
    description: "Serverid du serveur Artifactory"
    default: "artifactory"
    jfrog-args:
    required: false
    description: "additional arguments for the Jfrog CLI, see [Welcome to JFrog CLI](https://www.jfrog.com/confluence/display/CLI/JFrog+CLI)"
    artifactory-user:
    required: true
    description: "Secret: username for Artifactory server."
    artifactory-api-key:
    required: true
    description: "Secret: artifactory-api-key for API Artifactory"
    artifactory-url:
    required: false
    description: "URL Artifactory server"
    default: "https://artifacts.server.com"
    search-artifacts-before-upload:
    required: false
    description: "Look for the artefacts before uploading them"
    default: "false"
    ...

outputs: local-file-path: description: "Local file pattern" value: ${{ steps.jfrog.outputs.local-file-path }} destination-file-path: description: "Destination file pattern" value: ${{ steps.jfrog.outputs.destination-file-path }}

runs: using: "composite" steps:

      - name: Download artifact from Artifactory
        # Downloading artifact to be deployed
        id: artifacts-download
        uses: Corpo/wrapper-jfrog-cli-action@v1
        with:
          local-file-path: ${{ inputs.artifact-path }}/
          destination-file-path: ${{ inputs.artifactory-repo }}/${{ steps.group-id-to-path.outputs.group-id-path }}/${{ inputs.component-name }}/${{ inputs.build-version }}/${{ inputs.component-name }}-${{ inputs.build-version }}.${{inputs.archive-extension}}
          artifactory-action: download
          artifactory-serverid: ${{inputs.artifactory-serverid}}
          jfrog-args: --flat=true
          artifactory-user: ${{ steps.secrets.outputs.ARTIFACTORY_USER }}
          artifactory-api-key: ${{ steps.secrets.outputs.ARTIFACTORY_API_KEY }}
          artifactory-url: ${{ inputs.artifactory-url }}
  1. Could you also explain the following fields I see on your envs: It just because in my reduced and simpler version of an example workflow, I used environment variables at the top level of my example workflow in order to share the values through the whole workflow, but these values are usually taken from inputs:
    
    name: Example workflow

on: workflow_dispatch: inputs: version: description: Application version to be deployed required: true default: '1729058922-fdsf344'

env: product-name: ${{ github.event.repository.custom_properties.product }} component-name: xxxxxx-service version: ${{ inputs.version }} archive-extension: jar

Artifactory

artifact-path: artefact-release project-name: ProductService artifactory-url: https://artifacts.server.com/ artifactory-serverid: artifactory reports-format: ALL

jobs: dependency-check: runs-on: ${{ inputs.runs-on || vars.DEFAULT_RUNNER_LABEL }} steps:

Hope it's more clear now.

Thanks

alexquitiaquez commented 2 weeks ago

Now a quick question from my side, we are using self hosted runners, so you think there is some local JFrog configuration lost between the calling step and the cleanup process at the end, right? Could you share whith us, where this config is saved by the action on the runner please? I guess it is under the runner's file system? Thanks again

sverdlov93 commented 2 weeks ago

Hi @alexquitiaquez,

Thank you for your feedback. I understand the warnings are annoying, and they shouldn’t occur in the first place. I just wanted to clarify that these warnings are not causing the workflows to fail, which is the intended behavior.

I suspect the issue may be related to the self-hosted runner. The JFrog CLI configuration is stored in the <user home dir>/.jfrog directory (can be also set by JFROG_CLI_HOME_DIR env). Are you running multiple workflows concurrently on the same self-hosted runner?

alexquitiaquez commented 2 weeks ago

No, the runner is not supposed to run more than 1 workflow at a time and runners are ephemeres (destroyed after the execution)

sverdlov93 commented 2 weeks ago

Hi @alexquitiaquez,

I tried to reproduce this issue using a composite action in this workflow, and it worked as expected.

Could something in your workflow setup be removing the JFrog configuration? Possible causes might include:

1.  Deleting the <userhome>/.jfrog directory at some point.
2.  Running setup-jfrog-cli more than once within the same workflow.
3.  Running `jf c rm` manually, which would remove the JFrog CLI configuration.

also, can you run jf c show in your workflow and see your configuration there?