From fe481b267f844b2428f175fb174e08a7176bb808 Mon Sep 17 00:00:00 2001 From: Or Geva Date: Thu, 1 Sep 2022 12:16:38 +0300 Subject: [PATCH] Split GitHub-Actions tests (#1619) --- .github/workflows/accessTests.yml | 37 ++++ .github/workflows/analysis.yml | 29 +++- .github/workflows/artifactoryTests.yml | 50 ++++++ .github/workflows/cla.yml | 14 +- .github/workflows/distributionTests.yml | 37 ++++ .github/workflows/dockerTests.yml | 33 ++++ .github/workflows/frogbot.yml | 6 +- .github/workflows/goTests.yml | 38 ++++ .github/workflows/gradleTests.yml | 46 +++++ .github/workflows/mavenTests.yml | 44 +++++ .github/workflows/npmTests.yml | 48 +++++ .github/workflows/nugetTests.yml | 52 ++++++ .github/workflows/pluginsTests.yml | 44 +++++ .github/workflows/pythonTests.yml | 51 ++++++ .github/workflows/removeLabel.yml | 19 ++ .github/workflows/scriptTests.yml | 31 ++++ .github/workflows/tests.yml | 213 ----------------------- .github/workflows/transferTests.yml | 12 +- .github/workflows/xrayTests.yml | 56 ++++++ README.md | 222 +++++++++++++++++++++++- images/access.png | Bin 0 -> 3072 bytes images/artifactory.png | Bin 0 -> 494 bytes images/distribution.png | Bin 0 -> 3176 bytes images/docker.png | Bin 0 -> 533 bytes images/go.png | Bin 0 -> 628 bytes images/gradle.png | Bin 0 -> 935 bytes images/maven.png | Bin 0 -> 1098 bytes images/npm.png | Bin 0 -> 323 bytes images/nuget.png | Bin 0 -> 1045 bytes images/python.png | Bin 0 -> 613 bytes images/xray.png | Bin 0 -> 672 bytes 31 files changed, 844 insertions(+), 238 deletions(-) create mode 100644 .github/workflows/accessTests.yml create mode 100644 .github/workflows/artifactoryTests.yml create mode 100644 .github/workflows/distributionTests.yml create mode 100644 .github/workflows/dockerTests.yml create mode 100644 .github/workflows/goTests.yml create mode 100644 .github/workflows/gradleTests.yml create mode 100644 .github/workflows/mavenTests.yml create mode 100644 .github/workflows/npmTests.yml create mode 100644 .github/workflows/nugetTests.yml create mode 100644 .github/workflows/pluginsTests.yml create mode 100644 .github/workflows/pythonTests.yml create mode 100644 .github/workflows/removeLabel.yml create mode 100644 .github/workflows/scriptTests.yml delete mode 100644 .github/workflows/tests.yml create mode 100644 .github/workflows/xrayTests.yml create mode 100644 images/access.png create mode 100644 images/artifactory.png create mode 100644 images/distribution.png create mode 100644 images/docker.png create mode 100644 images/go.png create mode 100644 images/gradle.png create mode 100644 images/maven.png create mode 100644 images/npm.png create mode 100644 images/nuget.png create mode 100644 images/python.png create mode 100644 images/xray.png diff --git a/.github/workflows/accessTests.yml b/.github/workflows/accessTests.yml new file mode 100644 index 000000000..406cbc1ce --- /dev/null +++ b/.github/workflows/accessTests.yml @@ -0,0 +1,37 @@ +name: Access Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-access + cancel-in-progress: true +jobs: + Access-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Run Access tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.access --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --jfrog.user=${{ secrets.PLATFORM_USER }} --ci.runId=${{ runner.os }}-access diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 295ffbee1..f54463cc2 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -1,7 +1,33 @@ name: "Static Analysis" -on: [ "push", "pull_request" ] +on: [push, pull_request] jobs: + Go-Lint: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: Lint ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go + - name: Run Go vet + run: go vet -v ./... Static-Check: + name: Static Check ubuntu-latest runs-on: ubuntu-latest steps: - name: Checkout Source @@ -15,6 +41,7 @@ jobs: with: install-go: false Go-Sec: + name: Go-Sec ubuntu-latest runs-on: ubuntu-latest steps: - name: Checkout Source diff --git a/.github/workflows/artifactoryTests.yml b/.github/workflows/artifactoryTests.yml new file mode 100644 index 000000000..a8bf26372 --- /dev/null +++ b/.github/workflows/artifactoryTests.yml @@ -0,0 +1,50 @@ +name: Artifactory Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-artifactory + cancel-in-progress: true +jobs: + Artifactory-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.suite }} ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + suite: [artifactory, artifactoryProject] + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Setup Artifactory + run: | + go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest + ~/go/bin/local-rt-setup + env: + RTLIC: ${{secrets.RTLIC}} + GOPROXY: direct + if: ${{ matrix.suite == 'artifactory' }} + - name: Run Artifactory tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.artifactory + if: ${{ matrix.suite == 'artifactory' }} + - name: Run Artifactory projects tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.artifactoryProject --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --jfrog.user=${{ secrets.PLATFORM_USER }} --ci.runId=${{ runner.os }}-${{ matrix.suite }} + if: ${{ matrix.suite == 'artifactoryProject' }} diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index e3db3e89b..4c6b6c3c1 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -2,9 +2,9 @@ name: "CLA Assistant" on: # issue_comment triggers this action on each comment on issues and pull requests issue_comment: - types: [ created ] + types: [created] pull_request_target: - types: [ opened,synchronize ] + types: [opened, synchronize] jobs: CLAssistant: @@ -26,10 +26,10 @@ jobs: # JFrog organization secret PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_SIGN_TOKEN }} with: - path-to-signatures: 'signed_clas.json' - path-to-document: 'https://jfrog.com/cla/' - remote-organization-name: 'jfrog' - remote-repository-name: 'jfrog-signed-clas' + path-to-signatures: "signed_clas.json" + path-to-document: "https://jfrog.com/cla/" + remote-organization-name: "jfrog" + remote-repository-name: "jfrog-signed-clas" # branch should not be protected - branch: 'master' + branch: "master" allowlist: bot* diff --git a/.github/workflows/distributionTests.yml b/.github/workflows/distributionTests.yml new file mode 100644 index 000000000..4c2122c7e --- /dev/null +++ b/.github/workflows/distributionTests.yml @@ -0,0 +1,37 @@ +name: Distribution Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-distribution + cancel-in-progress: true +jobs: + Distribution-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Run Distribution tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.distribution --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --jfrog.user=${{ secrets.PLATFORM_USER }} --ci.runId=${{ runner.os }}-distribution diff --git a/.github/workflows/dockerTests.yml b/.github/workflows/dockerTests.yml new file mode 100644 index 000000000..24f8ef58e --- /dev/null +++ b/.github/workflows/dockerTests.yml @@ -0,0 +1,33 @@ +name: Docker Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-docker + cancel-in-progress: true +jobs: + Docker-tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ubuntu-latest + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Run Docker tests + run: go test -v -timeout 0 --test.docker --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --rt.dockerRepoDomain=${{ secrets.CONTAINER_REGISTRY }} --rt.dockerVirtualRepo=${{ secrets.DOCKER_VIRTUAL }} --rt.dockerLocalRepo=${{ secrets.DOCKER_LOCAL }} --rt.dockerRemoteRepo=${{ secrets.DOCKER_REMOTE }} --rt.dockerPromoteLocalRepo=${{ secrets.DOCKER_PROMOTE_LOCAL }} diff --git a/.github/workflows/frogbot.yml b/.github/workflows/frogbot.yml index 4eace310e..c017b4b40 100644 --- a/.github/workflows/frogbot.yml +++ b/.github/workflows/frogbot.yml @@ -1,7 +1,7 @@ name: "Frogbot" on: pull_request_target: - types: [ opened, synchronize ] + types: [opened, synchronize] jobs: scan-pull-request: runs-on: ubuntu-latest @@ -24,11 +24,11 @@ jobs: # [Mandatory] # JFrog platform URL JF_URL: ${{ secrets.FROGBOT_URL }} - + # [Mandatory if JF_USER and JF_PASSWORD are not provided] # JFrog access token with 'read' permissions on Xray service JF_ACCESS_TOKEN: ${{ secrets.FROGBOT_ACCESS_TOKEN }} - + # [Manadatory] # The GitHub token automatically generated for the job JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/goTests.yml b/.github/workflows/goTests.yml new file mode 100644 index 000000000..d0f690b04 --- /dev/null +++ b/.github/workflows/goTests.yml @@ -0,0 +1,38 @@ +name: Go Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-go + cancel-in-progress: true +jobs: + GO-tests: + # Go modules doesn't allow passing credentials to a private registry using an HTTP URL. Therefore, the Go tests run against a remote Artifactory server. + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Run Go tests + run: go test -v -timeout 0 --test.go --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --ci.runId=${{ runner.os }}-go diff --git a/.github/workflows/gradleTests.yml b/.github/workflows/gradleTests.yml new file mode 100644 index 000000000..3bee4b009 --- /dev/null +++ b/.github/workflows/gradleTests.yml @@ -0,0 +1,46 @@ +name: Gradle Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-gradle + cancel-in-progress: true +jobs: + Gradle-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + env: + GRADLE_OPTS: -Dorg.gradle.daemon=false + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Setup Artifactory + run: | + go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest + ~/go/bin/local-rt-setup + env: + RTLIC: ${{secrets.RTLIC}} + GOPROXY: direct + - name: Run Gradle tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.gradle diff --git a/.github/workflows/mavenTests.yml b/.github/workflows/mavenTests.yml new file mode 100644 index 000000000..3a1f21583 --- /dev/null +++ b/.github/workflows/mavenTests.yml @@ -0,0 +1,44 @@ +name: Maven Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-maven + cancel-in-progress: true +jobs: + Maven-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go + - name: Setup Artifactory + run: | + go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest + ~/go/bin/local-rt-setup + env: + RTLIC: ${{secrets.RTLIC}} + GOPROXY: direct + - name: Run Maven tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.maven diff --git a/.github/workflows/npmTests.yml b/.github/workflows/npmTests.yml new file mode 100644 index 000000000..9c823f3e8 --- /dev/null +++ b/.github/workflows/npmTests.yml @@ -0,0 +1,48 @@ +name: npm Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-npm + cancel-in-progress: true +jobs: + npm-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Install npm + uses: actions/setup-node@v3 + with: + node-version: "16" + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Setup Artifactory + run: | + go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest + ~/go/bin/local-rt-setup + env: + RTLIC: ${{secrets.RTLIC}} + GOPROXY: direct + - name: Run npm tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.npm diff --git a/.github/workflows/nugetTests.yml b/.github/workflows/nugetTests.yml new file mode 100644 index 000000000..859da2e39 --- /dev/null +++ b/.github/workflows/nugetTests.yml @@ -0,0 +1,52 @@ +name: NuGet Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-nuget + cancel-in-progress: true +jobs: + NuGet-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Install NuGet + uses: nuget/setup-nuget@v1 + with: + nuget-version: 5.x + - name: Install dotnet + uses: actions/setup-dotnet@v2 + with: + dotnet-version: "3.x" + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go + - name: Setup Artifactory + run: | + go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest + ~/go/bin/local-rt-setup + env: + RTLIC: ${{secrets.RTLIC}} + GOPROXY: direct + - name: Run NuGet tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.nuget diff --git a/.github/workflows/pluginsTests.yml b/.github/workflows/pluginsTests.yml new file mode 100644 index 000000000..168596729 --- /dev/null +++ b/.github/workflows/pluginsTests.yml @@ -0,0 +1,44 @@ +name: Plugins Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-plugins + cancel-in-progress: true +jobs: + Plugins-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Setup Artifactory + run: | + go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest + ~/go/bin/local-rt-setup + env: + RTLIC: ${{secrets.RTLIC}} + GOPROXY: direct + - name: Run plugins tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.plugins diff --git a/.github/workflows/pythonTests.yml b/.github/workflows/pythonTests.yml new file mode 100644 index 000000000..ba73c2e1e --- /dev/null +++ b/.github/workflows/pythonTests.yml @@ -0,0 +1,51 @@ +name: Python Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-python + cancel-in-progress: true +jobs: + Python-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.suite }} ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + suite: [pip, pipenv] + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.suite }} ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Setup Python3 + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Setup Pipenv + run: pip3 install pipenv + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Setup Artifactory + run: | + go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest + ~/go/bin/local-rt-setup + env: + RTLIC: ${{secrets.RTLIC}} + GOPROXY: direct + - name: Run Python tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.${{ matrix.suite }} diff --git a/.github/workflows/removeLabel.yml b/.github/workflows/removeLabel.yml new file mode 100644 index 000000000..b87de7c73 --- /dev/null +++ b/.github/workflows/removeLabel.yml @@ -0,0 +1,19 @@ +name: Remove Label +on: + pull_request: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-remove-label + cancel-in-progress: true +jobs: + Remove-Label: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') + name: Remove label + runs-on: ubuntu-latest + steps: + - name: Remove 'safe to test' + uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: "safe to test" diff --git a/.github/workflows/scriptTests.yml b/.github/workflows/scriptTests.yml new file mode 100644 index 000000000..fe18b3336 --- /dev/null +++ b/.github/workflows/scriptTests.yml @@ -0,0 +1,31 @@ +name: Scripts Tests +on: [push, pull_request] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-script + cancel-in-progress: true +jobs: + Scripts-tests: + name: ${{ matrix.os }} + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Test install CLI - jf + run: sh build/installcli/jf.sh && jf --version + - name: Test install CLI - jfrog + run: sh build/installcli/jfrog.sh && jfrog --version + - name: Test get CLI - jf + run: sh build/getcli/jf.sh && ./jf --version + - name: Test get CLI - jfrog + run: sh build/getcli/jfrog.sh && ./jfrog --version diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index 846aa92bb..000000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,213 +0,0 @@ -name: JFrog CLI Tests -on: - push: - # Triggers the workflow on labeled PRs only. - pull_request_target: - types: [ labeled ] -# Ensures that only the latest commit is running for each PR at a time. -# Ignores this rule for push events. -concurrency: - group: ${{ github.event.pull_request.number || github.sha }} - cancel-in-progress: true -jobs: - Pretest: - if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' - runs-on: ubuntu-latest - steps: - - name: Unlabel 'safe to test' - uses: actions-ecosystem/action-remove-labels@v1 - if: ${{github.event_name != 'push' }} - with: - labels: 'safe to test' - - - name: Install Go - uses: actions/setup-go@v3 - with: - go-version: 1.18.x - - - name: Checkout code - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Go Cache - uses: actions/cache@v3 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: ${{ runner.os }}-go- - - - name: Run Go vet - run: go vet -v ./... - - CLI-Tests: - needs: Pretest - name: ${{ matrix.suite }} (${{ matrix.os }}) - strategy: - fail-fast: false - matrix: - suite: - [ - artifactory, - artifactoryProject, - pip, - pipenv, - distribution, - xray, - access, - plugins, - npm, - maven, - gradle, - nuget, - ] - os: [ ubuntu-latest, macos-latest, windows-latest ] - runs-on: ${{ matrix.os }} - env: - GRADLE_OPTS: -Dorg.gradle.daemon=false - steps: - - name: Install Go - uses: actions/setup-go@v3 - with: - go-version: 1.18.x - - - name: Install npm - uses: actions/setup-node@v3 - with: - node-version: "16" - if: ${{ matrix.suite == 'npm' || matrix.suite == 'xray' }} - - - name: Install Java - uses: actions/setup-java@v3 - with: - java-version: "11" - distribution: "adopt" - if: ${{ matrix.suite == 'maven' || matrix.suite == 'gradle' || matrix.suite == 'xray' }} - - - name: Install NuGet - uses: nuget/setup-nuget@v1 - with: - nuget-version: 5.x - if: ${{ matrix.suite == 'nuget' }} - - - name: Install dotnet - uses: actions/setup-dotnet@v2 - with: - dotnet-version: '3.x' - if: ${{ matrix.suite == 'nuget' }} - - - name: Setup Python3 - uses: actions/setup-python@v4 - with: - python-version: "3.x" - - - name: Setup Pipenv - if: ${{ matrix.suite == 'pipenv' || matrix.suite == 'xray' }} - run: pip3 install pipenv - - - name: Checkout code - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Go Cache - uses: actions/cache@v3 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: ${{ runner.os }}-go- - - - name: Setup Artifactory - run: | - go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest - ~/go/bin/local-rt-setup - env: - RTLIC: ${{secrets.RTLIC}} - GOPROXY: direct - if: ${{ matrix.suite != 'distribution' && matrix.suite != 'xray' && matrix.suite != 'access' && matrix.suite != 'artifactoryProject' }} - - - name: Run Artifactory / Build tools tests - run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.${{ matrix.suite }}=true --ci.runId=${{ runner.os }}-${{ matrix.suite }} - if: ${{ matrix.suite != 'distribution' && matrix.suite != 'xray' && matrix.suite != 'access'&& matrix.suite != 'artifactoryProject' }} - - - name: Run Distribution / Xray / Access tests - run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.${{ matrix.suite }}=true --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --jfrog.user=${{ secrets.PLATFORM_USER }} --ci.runId=${{ runner.os }}-${{ matrix.suite }} - if: ${{ matrix.suite == 'distribution' || matrix.suite == 'xray' || matrix.suite == 'access' || matrix.suite == 'artifactoryProject' }} - - Go-Tests: - # Go modules doesn't allow passing credentials to a private registry using an HTTP URL. Therefore, the Go tests run against a remote Artifactory server. - needs: Pretest - name: go (${{ matrix.os }}) - strategy: - fail-fast: false - matrix: - os: [ ubuntu-latest, macos-latest, windows-latest ] - runs-on: ${{ matrix.os }} - steps: - - name: Install Go - uses: actions/setup-go@v3 - with: - go-version: 1.18.x - - name: Checkout code - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Go Cache - uses: actions/cache@v3 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: ${{ runner.os }}-go- - - - name: Run Go tests - run: go test -v -timeout 0 --test.go --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} - - Docker-tests: - needs: Pretest - name: docker (ubuntu-latest) - runs-on: ubuntu-latest - steps: - - name: Install Go - uses: actions/setup-go@v3 - with: - go-version: 1.18.x - - - name: Checkout code - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Go Cache - uses: actions/cache@v3 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: ${{ runner.os }}-go- - - - name: Run Docker tests - run: go test -v -timeout 0 --test.docker=true --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --rt.dockerRepoDomain=${{ secrets.CONTAINER_REGISTRY }} --rt.dockerVirtualRepo=${{ secrets.DOCKER_VIRTUAL }} --rt.dockerLocalRepo=${{ secrets.DOCKER_LOCAL }} --rt.dockerRemoteRepo=${{ secrets.DOCKER_REMOTE }} --rt.dockerPromoteLocalRepo=${{ secrets.DOCKER_PROMOTE_LOCAL }} - - Scripts-tests: - name: scripts (${{ matrix.os }}) - defaults: - run: - shell: bash - strategy: - fail-fast: false - matrix: - os: [ ubuntu-latest, macos-latest, windows-latest ] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - - name: Test install CLI - jf - run: sh build/installcli/jf.sh && jf --version - - name: Test install CLI - jfrog - run: sh build/installcli/jfrog.sh && jfrog --version - - name: Test get CLI - jf - run: sh build/getcli/jf.sh && ./jf --version - - name: Test get CLI - jfrog - run: sh build/getcli/jfrog.sh && ./jfrog --version diff --git a/.github/workflows/transferTests.yml b/.github/workflows/transferTests.yml index 9eefcef2c..631ab81d6 100644 --- a/.github/workflows/transferTests.yml +++ b/.github/workflows/transferTests.yml @@ -3,39 +3,36 @@ on: push: # Triggers the workflow on labeled PRs only. pull_request_target: - types: [ labeled ] + types: [labeled] # Ensures that only the latest commit is running for each PR at a time. # Ignores this rule for push events. concurrency: - group: ${{ github.event.pull_request.number || github.sha }}transfer + group: ${{ github.event.pull_request.number || github.sha }}-transfer cancel-in-progress: true jobs: Transfer-Tests: if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' - name: transfer (${{ matrix.os }}) + name: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ ubuntu-latest, macos-latest, windows-latest ] + os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - - name: Install Go uses: actions/setup-go@v3 with: go-version: 1.18.x - - name: Go Cache uses: actions/cache@v3 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: ${{ runner.os }}-go- - - name: Setup Artifactory run: | go install github.com/jfrog/jfrog-testing-infra/local-rt-setup@latest @@ -44,6 +41,5 @@ jobs: RTLIC: ${{secrets.RTLIC}} GOPROXY: direct JFROG_HOME: ${{ runner.temp }} - - name: Run transfer tests run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.transfer --jfrog.targetUrl=${{ secrets.PLATFORM_URL }} --jfrog.targetAdminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --jfrog.home=${{ runner.temp }} --ci.runId=${{ runner.os }}-transfer diff --git a/.github/workflows/xrayTests.yml b/.github/workflows/xrayTests.yml new file mode 100644 index 000000000..9ed1f28ac --- /dev/null +++ b/.github/workflows/xrayTests.yml @@ -0,0 +1,56 @@ +name: Xray Tests +on: + push: + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +# Ignores this rule for push events. +concurrency: + group: ${{ github.event.pull_request.number || github.sha }}-xray + cancel-in-progress: true +jobs: + CLI-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + env: + GRADLE_OPTS: -Dorg.gradle.daemon=false + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Install npm + uses: actions/setup-node@v3 + with: + node-version: "16" + - name: Install Java + uses: actions/setup-java@v3 + with: + java-version: "11" + distribution: "adopt" + - name: Install NuGet + uses: nuget/setup-nuget@v1 + with: + nuget-version: 5.x + - name: Install dotnet + uses: actions/setup-dotnet@v2 + with: + dotnet-version: "3.x" + - name: Setup Python3 + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Setup Pipenv + run: pip3 install pipenv + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Run Xray tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.xray --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --jfrog.user=${{ secrets.PLATFORM_USER }} --ci.runId=${{ runner.os }}-xray diff --git a/README.md b/README.md index 68ad7974d..1230f0e0f 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,222 @@ -| Branch | Status | -| :----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| v2 | [![JFrog CLI Tests](https://github.com/jfrog/jfrog-cli/actions/workflows/tests.yml/badge.svg?branch=v2)](https://github.com/jfrog/jfrog-cli/actions/workflows/tests.yml) [![Static Analysis](https://github.com/jfrog/jfrog-cli/actions/workflows/analysis.yml/badge.svg?branch=v2)](https://github.com/jfrog/jfrog-cli/actions/workflows/analysis.yml) | -| dev | [![JFrog CLI Tests](https://github.com/jfrog/jfrog-cli/actions/workflows/tests.yml/badge.svg?branch=dev)](https://github.com/jfrog/jfrog-cli/actions/workflows/tests.yml) [![Static Analysis](https://github.com/jfrog/jfrog-cli/actions/workflows/analysis.yml/badge.svg?branch=dev)](https://github.com/jfrog/jfrog-cli/actions/workflows/analysis.yml) | -| v1 | [![JFrog CLI Tests](https://github.com/jfrog/jfrog-cli/actions/workflows/tests.yml/badge.svg?branch=v1)](https://github.com/jfrog/jfrog-cli/actions/workflows/tests.yml) | -| dev-v1 | [![JFrog CLI Tests](https://github.com/jfrog/jfrog-cli/actions/workflows/tests.yml/badge.svg?branch=dev-v1)](https://github.com/jfrog/jfrog-cli/actions/workflows/tests.yml) | +
+ Tests status + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
V2DEV
artifactory Artifactory +
+ 1 +
+
+
+ 1 +
+
xray Xray +
+ 1 +
+
+
+ 1 +
+
distribution Distribution +
+ 1 +
+
+
+ 1 +
+
access Access +
+ 1 +
+
+
+ 1 +
+
maven Maven +
+ 1 +
+
+
+ 1 +
+
gradle Gradle +
+ 1 +
+
+
+ 1 +
+
npm npm +
+ 1 +
+
+
+ 1 +
+
docker Docker +
+ 1 +
+
+
+ 1 +
+
nuget NuGet +
+ 1 +
+
+
+ 1 +
+
python Python +
+ 1 +
+
+
+ 1 +
+
go Go +
+ 1 +
+
+
+ 1 +
+
📃 Scripts +
+ 1 +
+
+
+ 1 +
+
📊 Code Analysis +
+ 1 +
+
+
+ 1 +
+
🔌 Plugins +
+ 1 +
+
+
+ 1 +
+
☁️ Transfer To Cloud +
+ 1 +
+
+
+ 1 +
+
+
# Table of Contents diff --git a/images/access.png b/images/access.png new file mode 100644 index 0000000000000000000000000000000000000000..d88a9a34a441ea613aa26f345387cdef4a246c1c GIT binary patch literal 3072 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 O0000`$ zB_!#4dGDWh0eX5a9R^$c*ai4V4`hhheFzH%u*U^w@7g|BZ3qiEthq|j0`(E_HzOc( zsYeE7L_T|Z;wPk&FLa+$(3t}q6lUg9FCl}05%#(iEH@vJVodr-4u8HY{Me(`19v{P zV5=EaY`iAFrg}gjmsl7nkcH1OH2VJ6JnwQR#^fg0rV7RPrp+8s8;a0oPDmHkZIpul zJ-HqNZTJt)CX|k6noPl11R-XWmR!W$r2ulh^M^|Z86v|=*|}{YGD3eQTp3^wP#Q2v zNtCbUqE$+P<7vfrfXqloGNInO2z`YEf+ifaPDa;rb~isXUDiN?E?|6hblMm#H{U3$ z_gpfpFuffgTf%qT3DF)2GO?&zWI7BZv Xz&ey7*8g{r00000NkvXXu0mjf(xcZ! literal 0 HcmV?d00001 diff --git a/images/go.png b/images/go.png new file mode 100644 index 0000000000000000000000000000000000000000..5ab6b8d836aa29fbd21dfd5da5a2bdefdc56fe73 GIT binary patch literal 628 zcmV-)0*n2LP)!I}k?-aezC(6(|ujj?fjTD^Pa;E3k}A6r-*{TmhIEa7K4v6Jx+Yd%bsDyl~sFw5Mp~(($HI?Iv zh_tUcLod8YPvzQ_b+hIdaNl6X1E6NNy+rckd??l^$*zs5ChuWIRKI4NrZX8&3J@j)li& z!Y8zg4IB^at@>xRH7KDDPk?JUFw)}?KZ-!B7NXxK?AYg+)4PT-j5Gj5&s^vIvHeP; z#sXA%2)hyaG18T|Z)N~3Bfm9jp%Y^fBM#idRiu*-SKjM^+k&H~K1H`?H=#`1NCsFn zBAq&VF|Wy-41{(WU|B^jx$E1JQ$$72kBNN02WG+F1E!n?y~7O`E2vTHk0q5=Lk?iT zu}g?{Egs7=|5$1#$ZeMA6X2Fb;AJ|Ary`d+_lcdwb!A{4LkY5FtV=HGTonq18p<*y>;a O0000h3j!3-bmHPk@++E)sW^7!xnRdNJ{$K7orbuw~~|FX-; zgNI!nz_@rKGSg*s_v~cd;b$*sOtvyR+g)8J?gg|m;rCI;fain1H+kPxCCRfkNNZcu@*5n?fs?@r|HfH8AVu=yP$j-6F-5K`doEbo(bi|IvQDBV|T5(hv zKkSIGBFq?YT!@rJ#t zSWz|ycPia!LHeOdly_!I2XKz4JSDi`JauVgoiJ~m@=QHvk!{G~S!1WM4+*hUpPfAy z+(^C&3H`2b$T~bd0Xf?&bI4dQ3=thN_y!ChIR+Tc%a}BoJFd+Ub2yl?As}1Btmm~W z3gUAZP)<39DW|4~ITLnyAL4k9oo`^bA(>MS^ggt$+Xk002ov JPDHLkV1mG#lxP3| literal 0 HcmV?d00001 diff --git a/images/maven.png b/images/maven.png new file mode 100644 index 0000000000000000000000000000000000000000..c4d3179ecfe3ea9d92081b5a782fbbcc67b0af0a GIT binary patch literal 1098 zcmV-Q1hxB#P)Za_^1ArmmMv?V*c$^M#|d#`5}BUG5|ZkjeP{lMkU%sn&bd(S=R z&IKOufFp*o2AW?@lyt|;X@w;PHS@?!5aJ#nvIdCE8EXizTofJHvp4{q3-V0!i;1tR zb5deZ0p>p?Kx&){GO&QCCc^fXH4@dxs9k}mE?!0-Y`%SbQMX00d6R-D6fzFUAVN9I z-p(3GcI*%uHLZzAVT6mTjD7OQ#jJNSBM|S3TCyX? zb=?a1nvxwWyp}(i&$3@D(WGj$$y-Vr6AMD3{U^R$ySSf#%m_68b~f6#ZAxksbZ*&* zYu1R4&G;c*j~z>XwY_7QZLv$1nYU9zDp6076xcgu~THUbiH9 zIl0ekIFj!wdu9apvN7P6U;Z!yg($lATxBKlnP;A@^*4 zlrPO1*plta=!)o$BT;ne#BW#UaW?|~<%;GHD;B~H3Kn9xi|N3(@>Q9@^%L0D^tpzR zT>*vyWh@_kvaf)2W-+f4JMj`YCN{2#;dtN40#^h1=@{RyCdQfKW>O)_(D@gGp936* zfEIEq>4zh@9=BRV4#izZ!_(~e9E%Df&WSjE-W{_8eyxlFpk4;w%hQ)NtSJRrWxbq) zT;JqybO^$zWt-GA&l@(^D(_gYp9+3h#sKun0d(N5@a%arbVKgbkfVX&v@a`i@=13Y zY((UKG^q2w1hAtePPS@f+;L98AQf=a8s+WX0f(HQ+2s}_p9eS~eF}sJelUMmN41_+u!k>wFUhGzWs5*7 zTKM$3AK(zM`ZX+v<@U+PP7m=h>-uMFAO3>-&8f+E3u#|^_Txe+?+f4Bu*YA? zcK4?^|LX_kh8pg9IyzL2KUKWrB=pKN?@i+<$;+ZQIq_BjN6F-5QQ{Ez2dE{^$l<8K Qr2qf`07*qoM6N<$f@-n^1ONa4 literal 0 HcmV?d00001 diff --git a/images/npm.png b/images/npm.png new file mode 100644 index 0000000000000000000000000000000000000000..4cb05464c6fd3609d4833eb5dbdeb6b45efb34cb GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oVGw3ym^DWND9BhG zycC!m@Y*7#Eybqmhl$lihkclPG zh|B+uq+7e<8)qfc4W;J``8;DE&wPAZbcMIalg-vob(Bh=EJt zO544ZIhW!bKiq!b-aJLk^uXQk+;cxKkXn%@*mjZOVP)AIZ)ITbkMhZC~pocVYiGWs=6DO)35cGgVCBzjW@dp%%3+2#O zf+Gq@P~`+gLg9y~2v8b9Q*6>CP`hg@>?6s$}>34At zK>Q|!U@yP_3+uYPLc{OP^X>{2r*MxD@|_h}V^tH5DKHQvob&LSJ3T$0OA>{>N(d$@ zRP6~0s%vZ&LdiRXzkNKDxr7Grzk;g^hn6<@2lKa_{UZaau`eDz#W=Etg)`q2BQQ(_ z7IQPTC76t+5Jmng7>qKcbqDDfJ##FZI=v$TE-o5|PK)JHEz$dvW0aq}R?*IV^=Akb zlcP|fuqc;_5^lEcL{c_?phrXKk7)>pRE+miIqdV#WK$=1M4*o8T&|~972kjOTR8c< zVPoonP7KF2oV{Gaq9hW8NQmIzP#2;R6%%_YvR(G%(TBEQ2Wdt?wb_yH3TpD^8pVsF zalAFT2QQ8H;j*g-r zn7R)q9_iiOxPgCb1W2&iV?&+WHm}1Ypfo-}OIJWt1=QTs0h2A5$u7ubK{!+(F`@?g zCHpk5I}+lKfY@jPMJRL8ur!l`uM`=oB?fa{fLgLcNMWsRut48@i6R6d9c!KXxGfQQHLSByKaDyJe|Iu2n)+%bVVKK(T}Cbc)gh0_~kLzGZi_Te8IZM=(J{BQ6V{|SV=b~$5$ P00000NkvXXu0mjf!xYch literal 0 HcmV?d00001 diff --git a/images/python.png b/images/python.png new file mode 100644 index 0000000000000000000000000000000000000000..3f4083d4c1a5877d9cc71b78c1e4be1de888b20c GIT binary patch literal 613 zcmV-r0-F7aP)>m)mpc}yf1S%W8pj<(y%NK-v!7i%QE6KGI(N-!)NOIyx`v>_0 zB9RlJo{rO2ZBjexr0uEuB=4?0GxoFn>{*~hiMtNcI45aV`DY$%fq7E`qZ#vol>B@4 zz6}M8#(7Nlb7D>mIQN*VQd%$5ofHbF2*`pxwv6_E_TdWy18;}KZ=isZfExhWt4}+> zJzKC4?rEG^W-rhFX?4#%h^T>UU@n0d>2|zCroo^H3XHmMGkGOKc1WONxz=eyOF$GK zjcKXtzEwv>V42qpQRE^;E7iZop2IS25r#ffqF*wEo5Y~NY2^iP{H-!Jj zn>!{5Zoz*3vG+RNt~1P*s}r%ycF|=|?qM#dy;ds*K`Rs(b?b65Q9RQ@>tbD&`*7u1 zC&v|`PDZm3ac;VT$tge#bIaKEt z@-ggFNj7a+?%`Rx`=-g;zFS%Ururo-QKG~##9)~LS-Y}600000NkvXXu0mjfWHJT+ literal 0 HcmV?d00001 diff --git a/images/xray.png b/images/xray.png new file mode 100644 index 0000000000000000000000000000000000000000..5109cd9cd47635621e1ca32f1f538b5dbcde4dff GIT binary patch literal 672 zcmV;R0$=@!P)-wp?>M-bgLw?hTi`nntEh#m& z$@KF-g9G#pK(8J_8H6U}=$5=oDbgq8aHgn5+f0;B_GO|A!1HDcz&`~TtZ?bnp3f4Z z=!QJSa7RFu+S;_uXSl+wLB{Y+T1S=5}X4Z!1!FU~AKmsar}A zMFYq*EHEzsbBYhZjX2w1Az(s({9CN~a!jrwOhpddfqX0W6|60D0CdT#QJ&4CO!YBo zeIfGXG&SEFV5(w!K7Cz~bjjZAE9Y>C`7%pH9rIZnner zZ2ylbdHE=+(vb}vWM5zyFa*xfaczz76yW|#wm70GnbN=8#R{