Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2023.3 #223

Merged
merged 28 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f300e35
:zap: Add `send` command
tiulpin Oct 18, 2023
474562f
:bug: Docker container should support `/data/coverage` as coverage di…
hybloid Oct 23, 2023
d46b63c
:bug: Fix publisher fetching and running
tiulpin Oct 23, 2023
0c52e47
:recycle: Refactor CI/CD, Test and IDE related code
tiulpin Oct 26, 2023
b2b2222
:bug: Always validate token, if it was provided
tiulpin Oct 26, 2023
112e93b
:children_crossing: Add possibility to set TFMs for qodana-dotnet.
hybloid Oct 31, 2023
67c7b50
:children_crossing: .NET linter should use new profiles starting from…
hybloid Nov 15, 2023
9b12d5d
:bug: Do not use ID until analyzer is set
tiulpin Nov 16, 2023
88c8f98
:children_crossing: Execute `scan` if no subcommand provided by default
tiulpin Nov 22, 2023
a2e4ae8
:bug: Switch to `open-in-ide.json` for results report
tiulpin Nov 22, 2023
f1d2454
:bug: Use only `ENDPOINT` for qodana.cloud endpoints
tiulpin Nov 22, 2023
9cf6310
:bug: Fix corrupted by Docker Desktop for macOS caches directory (QD-…
tiulpin Nov 22, 2023
3c83ff3
:bug: Disable project opening via activities flag #216 (QD-7787)
MekhailS Nov 23, 2023
bfe805d
:bug: Disable git log indexing (QD-7829)
MekhailS Nov 28, 2023
f97866d
:bug: Status code 404 also treated as correct decline of token (QD-7185)
avafanasiev Nov 30, 2023
a369b03
:recycle: Fix project after the rebase
tiulpin Dec 2, 2023
7d3cfb3
:test_tube: Collect and merge all coverage artifacts for Qodana
tiulpin Dec 2, 2023
bd8f792
:bug: Handle license with community plan (QD-6789)
tiulpin Dec 4, 2023
e9a1754
:bricks: Update nightly build releases
tiulpin Dec 4, 2023
0ce8b93
:bricks: Update nightly build releases
tiulpin Dec 4, 2023
0bce788
:bug: Fix `--clear-cache` option for `scan`
tiulpin Dec 6, 2023
10fda69
:recycle: Refactor root command
tiulpin Dec 6, 2023
9d4fea4
:bricks: .NET linter in container should craft NuGet config file
hybloid Dec 7, 2023
1a55021
:bug: Do not run publisher for local runs (it's ran by QD)
tiulpin Dec 8, 2023
c6137e8
:bug: Do not report old report URLs
tiulpin Dec 8, 2023
3904faa
:children_crossing: Do not show message about the report for non-inte…
tiulpin Dec 8, 2023
77b14c1
:bug: Return `--coverage-dir` (QD-7943)
tiulpin Dec 8, 2023
01b78ac
:bug: Fail if IDE to run was not found (QD-7806)
tiulpin Dec 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 74 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ jobs:
with:
go-version: '1.21'
- name: golangci-lint
uses: golangci/[email protected]
with:
version: latest
uses: reviewdog/action-golangci-lint@v2

test:
runs-on: ${{ matrix.os }}
Expand All @@ -38,31 +36,91 @@ jobs:
- uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Set up gotestfmt
uses: gotesttools/gotestfmt-action@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- if: ${{ matrix.os == 'ubuntu-latest' }}
uses: docker/login-action@v3
with:
registry: registry.jetbrains.team
username: ${{ secrets.SPACE_USERNAME }}
password: ${{ secrets.SPACE_PASSWORD }}
- run: go test -v ./... -coverprofile cover.out -coverpkg=./...
- name: Run tests (with coverage)
if: ${{ matrix.os != 'windows-latest' }}
run: |
set -euo pipefail
go test -json -v ./... -coverprofile coverage-${{ matrix.os }}.out -coverpkg=./... 2>&1 | tee /tmp/gotest.log | gotestfmt
env:
QODANA_LICENSE_ONLY_TOKEN: ${{ secrets.QODANA_LICENSE_ONLY_TOKEN }}
- name: Run tests (with coverage) for Windows
if: ${{ matrix.os == 'windows-latest' }}
run: go test -v ./... -coverprofile coverage-${{ matrix.os }}.out -coverpkg=./...
env:
QODANA_LICENSE_ONLY_TOKEN: ${{ secrets.QODANA_LICENSE_ONLY_TOKEN }}
- if: startsWith(matrix.os, 'ubuntu')
uses: JetBrains/qodana-action@main
- name: Upload coverage artifact
uses: actions/upload-artifact@v3
with:
name: coverage-${{ matrix.os }}.out
path: coverage-${{ matrix.os }}.out

code-quality:
runs-on: ubuntu-latest
needs: [ lint, test ]
permissions:
checks: write
pull-requests: write
actions: read
contents: write
security-events: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: docker/login-action@v3
with:
registry: registry.jetbrains.team
username: ${{ secrets.SPACE_USERNAME }}
password: ${{ secrets.SPACE_PASSWORD }}
- name: Download all coverage artifacts
uses: actions/download-artifact@v3
with:
path: cov/
- name: Merge coverage profiles
run: |
go install -v github.com/hansboder/gocovmerge@latest
mkdir -p .qodana/code-coverage
export PATH=$PATH:$(go env GOPATH)/bin
ls -R cov/
gocovmerge cov/coverage-macos-latest.out/coverage-macos-latest.out cov/coverage-ubuntu-latest.out/coverage-ubuntu-latest.out cov/coverage-windows-latest.out/coverage-windows-latest.out > .qodana/code-coverage/coverage.out
- uses: JetBrains/qodana-action@main
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
with:
args: --fail-threshold,0
- if: startsWith(matrix.os, 'ubuntu')
uses: github/codeql-action/init@v2
- uses: github/codeql-action/init@v2
with:
languages: go
- if: startsWith(matrix.os, 'ubuntu')
uses: github/codeql-action/autobuild@v2
- if: startsWith(matrix.os, 'ubuntu')
uses: github/codeql-action/analyze@v2
- if: startsWith(matrix.os, 'ubuntu')
name: install chocolatey
- uses: github/codeql-action/autobuild@v2
- uses: github/codeql-action/analyze@v2

release-nightly:
runs-on: ubuntu-latest
needs: [ lint, test, code-quality ]
permissions:
checks: write
pull-requests: write
actions: read
contents: write
security-events: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: install chocolatey
run: |
mkdir -p /opt/chocolatey
wget -q -O - "https://github.com/chocolatey/choco/releases/download/${CHOCOLATEY_VERSION}/chocolatey.v${CHOCOLATEY_VERSION}.tar.gz" | tar -xz -C "/opt/chocolatey"
Expand All @@ -71,14 +129,12 @@ jobs:
chmod +x /usr/local/bin/choco
env:
CHOCOLATEY_VERSION: 1.2.0
- if: startsWith(matrix.os, 'ubuntu')
uses: goreleaser/goreleaser-action@v5
- uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser
version: latest
args: --snapshot --clean --debug
- if: startsWith(matrix.os, 'ubuntu') && github.ref == 'refs/heads/233'
run: |
- run: |
cd dist
gh release --repo JetBrains/qodana-cli delete nightly -y || true
git push --delete origin nightly || true
Expand Down
59 changes: 43 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ You can also add the linter by its name with the `--linter` option (e.g. `--lint

#### macOS and Linux
##### Install with [Homebrew](https://brew.sh) (recommended)
```console
```shell
brew install jetbrains/utils/qodana
```
##### Install with our installer
```console
```shell
curl -fsSL https://jb.gg/qodana-cli/install | bash
```
Also, you can install `nightly` or any other version (e.g. `v2023.2.9`) the following way:
Expand All @@ -52,15 +52,15 @@ curl -fsSL https://jb.gg/qodana-cli/install | bash -s -- nightly

#### Windows
##### Install with [Windows Package Manager](https://learn.microsoft.com/en-us/windows/package-manager/winget/) (recommended)
```console
```shell
winget install -e --id JetBrains.QodanaCLI
```
##### Install with [Chocolatey](https://chocolatey.org)
```console
```shell
choco install qodana
```
##### Install with [Scoop](https://scoop.sh)
```console
```shell
scoop bucket add jetbrains https://github.com/JetBrains/scoop-utils
scoop install qodana
```
Expand All @@ -72,7 +72,7 @@ from [this page](https://github.com/JetBrains/qodana-cli/releases/latest).

Or, if you have Go installed, you can install the latest version of the CLI with the following command:

```console
```shell
go install github.com/JetBrains/qodana-cli/v2023@main
```

Expand All @@ -90,7 +90,7 @@ If you know what linter you want to use, you can skip this step.

Also, Qodana CLI can choose a linter for you. Just run the following command in your **project root**:

```console
```shell
qodana init
```

Expand All @@ -99,7 +99,7 @@ qodana init
Right after you configured your project (or remember linter's name you want to run),
you can run Qodana inspections simply by invoking the following command in your project root:

```console
```shell
qodana scan
```

Expand All @@ -112,7 +112,7 @@ After the analysis, the results are saved to `./<userCacheDir>/JetBrains/<linter
Inside the directory `./<userCacheDir>/JetBrains/<linter>/results/report`, you can find a Qodana HTML report.
To view it in the browser, run the following command from your project root:

```console
```shell
qodana show
```

Expand Down Expand Up @@ -141,7 +141,7 @@ Configure a project for Qodana:
prepare Qodana configuration file by analyzing the project structure
and generating a default configuration qodana.yaml file.

```
```shell
qodana init [flags]
```

Expand All @@ -167,7 +167,7 @@ Note that most options can be configured via qodana.yaml (https://www.jetbrains.
But you can always override qodana.yaml options with the following command-line options.


```
```shell
qodana scan [flags]
```

Expand Down Expand Up @@ -222,7 +222,7 @@ be viewed via the file:// protocol (by double-clicking the index.html file).
https://www.jetbrains.com/help/qodana/html-report.html
This command serves the Qodana report locally and opens a browser to it.

```
```shell
qodana show [flags]
```

Expand All @@ -237,6 +237,33 @@ qodana show [flags]
-r, --report-dir string Specify HTML report path (the one with index.html inside) (default <userCacheDir>/JetBrains/<linter>/results/report)
```

### send

Send a Qodana report to Cloud

#### Synopsis

Send the report (qodana.sarif.json and other analysis results) to Qodana Cloud.

If report directory is not specified, the latest report will be fetched from the default linter results location.

If you are using other Qodana Cloud instance than https://qodana.cloud/, override it with declaring `ENDPOINT` environment variable.

```shell
qodana send [flags]
```

#### Options

```
-h, --help help for send
-l, --linter string Override linter to use
-i, --project-dir string Root directory of the inspected project (default ".")
-r, --report-dir string Specify HTML report path (the one with index.html inside) (default "/Users/tv/Library/Caches/JetBrains/Qodana/e3b0c442-250e5c26/results/report")
-o, --results-dir string Override directory to save Qodana inspection results to (default "/Users/tv/Library/Caches/JetBrains/Qodana/e3b0c442-250e5c26/results")
-y, --yaml-name string Override qodana.yaml name
```

### view

View SARIF files in CLI
Expand All @@ -245,7 +272,7 @@ View SARIF files in CLI

Preview all problems found in SARIF files in CLI.

```
```shell
qodana view [flags]
```

Expand All @@ -271,7 +298,7 @@ A command-line helper for Qodana pricing to calculate active contributors* in th
** Ultimate Plus plan currently has a discount, more information can be found on https://www.jetbrains.com/qodana/buy/


```
```shell
qodana contributors [flags]
```

Expand All @@ -289,7 +316,7 @@ A command-line helper for project statistics: languages, lines of code. Powered

#### Synopsis

```
```shell
qodana cloc [flags]
```

Expand All @@ -316,7 +343,7 @@ as there is some additional configuration tuning required that differs from proj

It's easy to try Qodana locally by running a _simple_ command:

```console
```shell
docker run --rm -it -p 8080:8080 -v <source-directory>/:/data/project/ -v <output-directory>/:/data/results/ -v <caches-directory>/:/data/cache/ jetbrains/qodana-<linter> --show-report
```

Expand Down
15 changes: 12 additions & 3 deletions cloud/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package cloud
import (
"bytes"
"encoding/json"
"fmt"
log "github.com/sirupsen/logrus"
"io"
"net/http"
Expand All @@ -28,18 +29,26 @@ import (
)

const (
QodanaEndpoint = "ENDPOINT"
DefaultEndpoint = "qodana.cloud"
baseUrl = "https://api.qodana.cloud"
maxNumberOfRetries = 3
waitTimeout = time.Second * 30
requestTimeout = time.Second * 30
)

func getCloudBaseUrl() string {
return fmt.Sprintf("https://%s", GetEnvWithDefault(QodanaEndpoint, DefaultEndpoint))
}

func getCloudApiBaseUrl() string {
return fmt.Sprintf("https://api.%s", GetEnvWithDefault(QodanaEndpoint, DefaultEndpoint))
}

// GetCloudTeamsPageUrl returns the team page URL on Qodana Cloud
func GetCloudTeamsPageUrl(origin string, path string) string {
name := filepath.Base(path)

return strings.Join([]string{"https://", DefaultEndpoint, "/?origin=", origin, "&name=", name}, "")
return strings.Join([]string{"https://", GetEnvWithDefault(QodanaEndpoint, DefaultEndpoint), "/?origin=", origin, "&name=", name}, "")
}

type QdClient struct {
Expand Down Expand Up @@ -92,7 +101,7 @@ func (client *QdClient) getProject() RequestResult {
}

func (client *QdClient) doRequest(path, method string, headers map[string]string, body []byte) RequestResult {
url := baseUrl + path
url := getCloudApiBaseUrl() + path
var resp *http.Response
var err error

Expand Down
43 changes: 43 additions & 0 deletions cloud/cloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
package cloud

import (
"encoding/json"
"net/http"
"os"
"path/filepath"
"testing"
)

Expand Down Expand Up @@ -45,3 +48,43 @@ func TestValidateToken(t *testing.T) {
t.Errorf("Problem")
}
}

func TestGetReportUrl(t *testing.T) {
for _, tc := range []struct {
name string
jsonData jsonData
reportUrlFile string
expectedReport string
}{
{
name: "valid json data and url",
jsonData: jsonData{Cloud: cloudInfo{URL: "https://cloud.qodana.com/report/url"}},
reportUrlFile: "https://raw.qodana.com/report/url",
expectedReport: "https://cloud.qodana.com/report/url",
},
{
name: "invalid json data, valid url file data",
jsonData: jsonData{Cloud: cloudInfo{URL: ""}},
reportUrlFile: "https://raw.qodana.com/report/url",
expectedReport: "https://raw.qodana.com/report/url",
},
} {
t.Run(tc.name, func(t *testing.T) {
dir := t.TempDir()
jsonFile := filepath.Join(dir, openInIdeJson)
jsonFileData, _ := json.Marshal(tc.jsonData)
if err := os.WriteFile(jsonFile, jsonFileData, 0644); err != nil {
t.Fatal(err)
}
urlFile := filepath.Join(dir, legacyReportFile)
if err := os.WriteFile(urlFile, []byte(tc.reportUrlFile), 0644); err != nil {
t.Fatal(err)
}

actual := GetReportUrl(dir)
if actual != tc.expectedReport {
t.Fatalf("Expected \"%s\" but got \"%s\"", tc.expectedReport, actual)
}
})
}
}
Loading