Skip to content

Commit

Permalink
Github actions integration (#1205)
Browse files Browse the repository at this point in the history
Gradle and Maven plugin updates

### What's done:
- Support for the SARIF upload to the github in plugins (gradle/maven)
- Updated actions
- Readme updates
  • Loading branch information
orchestr7 authored Feb 3, 2022
1 parent 78a339f commit 0698727
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 78 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/diktat.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Run diKTat from release version
name: Run diKTat (release)

on:
push:
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/diktat_snapshot.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Run diKTat from snapshot
name: Run diKTat (snapshot)

on:
push:
Expand All @@ -12,7 +12,6 @@ env:
jobs:
diktat_snapshot_check:
runs-on: ubuntu-20.04

steps:
- uses: actions/checkout@v2.4.0
- name: Set up JDK 11
Expand Down Expand Up @@ -47,4 +46,9 @@ jobs:
mvn -B versions:set-property -Dproperty=diktat-check.version -DnewVersion=${{ env.BASE_VERSION }}-pre
- name: Run diktat snapshot via maven plugin
run: |
mvn -B diktat:check@diktat -Ddiktat.debug=true
mvn -B diktat:check@diktat -Ddiktat.debug=true -Ddiktat.githubActions=true
- name: Upload SARIF to Github using the upload-sarif action
uses: github/codeql-action/upload-sarif@v1
if: ${{ always() }}
with:
sarif_file: ${{ github.workspace }}
27 changes: 25 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
# Contributing

If you reading this - then you have decided to contribute to our project. Oh, poor you...
If you are reading this - then you have decided to contribute to our project. Oh, poor you...
Rules are very simple:
1. Fork this repository to your own account
2. Make your changes and verify that tests pass (or wait that our CI/CD will do everything for you)
3. Commit your work and push to a new branch on your fork
4. Submit a pull request
5. Participate in the code review process by responding to feedback

# Technical part

Main components are:
1) diktat-rules — number of rules that are supported by diKTat;
2) diktat-test-framework — functional/unit test framework that can be used for running your code fixer on the initial code and compare it with the expected result;
3) also see our demo: diktat-demo in a separate repository.

Mainly we wanted to create a common configurable mechanism that
will give us a chance to enable/disable and customize all rules.
That's why we added logic for:
1) Parsing `.yml` file with configurations of rules and passing it to visitors;
2) Passing information about properties to visitors.
This information is very useful, when you are trying to get,
for example, a filename of file where the code is stored;
3) We added a bunch of visitors, checkers and fixers that will extended KTlint functionaliity with code style rules;
4) We have proposed a code style for Kotlin language.

Before you make a pull request, make sure the build is clean as we have lot of tests and other prechecks:

```bash
$ mvn clean install
```

# Hooks

We have some hooks to a commit messages:
Expand All @@ -20,4 +43,4 @@ Brief Description
2) Long description
```

2) Please also do not forget to update documentation on Wiki after the merge approval and before merge.
2) Please also do not forget to update documentation on Wiki after the merge approval and before merge.
117 changes: 60 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
![Build and test](https://github.com/cqfn/diKTat/workflows/Build%20and%20test/badge.svg)
![deteKT static analysis](https://github.com/cqfn/diKTat/workflows/Run%20deteKT/badge.svg)
![diKTat code style](https://github.com/cqfn/diKTat/workflows/Run%20diKTat%20from%20release%20version/badge.svg?branch=master)
[![License](https://img.shields.io/github/license/cqfn/diKtat)](https://github.com/cqfn/diKTat/blob/master/LICENSE)
[![codecov](https://codecov.io/gh/analysis-dev/diKTat/branch/master/graph/badge.svg)](https://codecov.io/gh/analysis-dev/diKTat)

[![Releases](https://img.shields.io/github/v/release/cqfn/diKTat)](https://github.com/cqfn/diKTat/releases)
[![Maven Central](https://img.shields.io/maven-central/v/org.cqfn.diktat/diktat-rules)](https://mvnrepository.com/artifact/org.cqfn.diktat)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcqfn%2FdiKTat.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcqfn%2FdiKTat?ref=badge_shield)
[![ktlint](https://img.shields.io/badge/code%20style-%E2%9D%A4-FF4081.svg)](https://ktlint.github.io/)
[![Chat on Telegram](https://img.shields.io/badge/Chat%20on-Telegram-brightgreen.svg)](https://t.me/diktat_help)

[![Hits-of-Code](https://hitsofcode.com/github/cqfn/diktat)](https://hitsofcode.com/view/github/cqfn/diktat)
Expand All @@ -35,16 +33,15 @@ Now diKTat was already added to the lists of [static analysis tools](https://git
There are several tools like `detekt` and `ktlint` that are doing static analysis. Why do I need diktat?

First of all - actually you can combine diktat with any other static analyzers. And diKTat is even using ktlint framework for parsing the code into the AST.
And we are trying to contribute to those projects.
Main features of diktat are the following:

1) **More inspections.** It has 100+ inspections that are tightly coupled with it's codestyle.

2) **Unique inspections** that are missing in other linters.
1) **More inspections.** It has 100+ inspections that are tightly coupled with it's [Codestyle](info/guide/diktat-coding-convention.md).
2) **Unique [Inspections](info/available-rules.md)** that are missing in other linters.

3) **Highly configurable**. Each and every inspection can be configured and suppressed both from the code or from the configuration file.
3) **Highly configurable**. Each and every inspection can be [configured](#config) or [suppressed](#suppress).

4) **Strict detailed coding convention** that you can use in your project.
4) **Strict detailed [Codestyle](info/guide/diktat-coding-convention.md)** that you can adopt and use in your project.

## Run as CLI-application
<details>
Expand All @@ -63,7 +60,10 @@ Main features of diktat are the following:
```bash
$ curl -sSLO https://github.com/cqfn/diKTat/releases/download/v1.0.2/diktat-1.0.2.jar
```

</details>

<details>
<summary>Run diktat:</summary>
3. Finally, run KTlint (with diKTat injected) to check your `*.kt` files in `dir/your/dir`:
```bash
$ ./ktlint -R diktat.jar --disabled_rules=standard "dir/your/dir/**/*.kt"
Expand All @@ -72,25 +72,6 @@ Main features of diktat are the following:
To **autofix** all code style violations use `-F` option.
</details>

## GitHub Native Integration
We suggest everyone to use common ["sarif"](https://docs.oasis-open.org/sarif/sarif/v2.0/sarif-v2.0.html) format as a `reporterType` in CI/CD.
GitHub has an [integration](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning)
with SARIF format and provides you a native reporting of diktat issues in Pull Requests.

```text
reporterType = "sarif"
output = "diktat-report.sarif"
```

Add the following code to your GitHub Action to upload diktat sarif report (after it was generated).

```yml
- name: Upload SARIF to Github using the upload-sarif action
uses: github/codeql-action/upload-sarif@v1
if: ${{ always() }}
with:
sarif_file: build/diktat-report.sarif
```

## Run with Maven using diktat-maven-plugin
This plugin is available since version 0.1.3. You can see how it is configured in our project for self-checks: [pom.xml](pom.xml).
Expand Down Expand Up @@ -256,7 +237,44 @@ Diktat can be run via spotless-maven-plugin since version 2.8.0
```
</details>

## Customizations via `diktat-analysis.yml`
## GitHub Native Integration
We suggest everyone to use common ["sarif"](https://docs.oasis-open.org/sarif/sarif/v2.0/sarif-v2.0.html) format as a `reporterType` in CI/CD.
GitHub has an [integration](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning)
with SARIF format and provides you a native reporting of diktat issues in Pull Requests.

![img.png](example.png)

<details>
<summary> Github Integration</summary>
1) Add the following configuration to your project's setup for GitHub Actions:
Gradle Plugin:
```text
githubActions = true
```
Maven Plugin (pom.xml):
```xml
<githubActions>true</githubActions>
```
Maven Plugin (cli options):
```text
mvn -B diktat:check@diktat -Ddiktat.githubActions=true
```
2) Add the following code to your GitHub Action to upload diktat SARIF report (after it was generated):
```yml
- name: Upload SARIF to Github using the upload-sarif action
uses: github/codeql-action/upload-sarif@v1
if: ${{ always() }}
with:
sarif_file: ${{ github.workspace }}
```
</details>
## <a name="config"></a> Customizations via `diktat-analysis.yml`
In KTlint, rules can be configured via `.editorconfig`, but
this does not give a chance to customize or enable/disable
Expand All @@ -281,7 +299,11 @@ Note, that you can specify and put `diktat-analysis.yml` that contains configura
See default configuration in [diktat-analysis.yml](diktat-rules/src/main/resources/diktat-analysis.yml) \
Also see [the list of all rules supported by diKTat](info/available-rules.md).
## Suppress warnings on individual code blocks
## <a name="suppress"></a> Suppress warnings/inspections
<details>
<summary>Suppress warnings on individual code blocks</summary>
In addition to enabling/disabling warning globally via config file (`enable = false`), you can suppress warnings by adding `@Suppress` annotation on individual code blocks
For example:
Expand All @@ -293,9 +315,11 @@ class SomeClass {
}
}
```
```
</details>
## Suppress groups of inspections
<details>
<summary>Suppress groups of inspections</summary>
It is easy to suppress even groups of inspections in diKTat.
These groups are linked to chapters of [Codestyle](info/guide/diktat-coding-convention.md).
Expand All @@ -305,7 +329,8 @@ To disable chapters, you will need to add the following configuration to common
disabledChapters: "1, 2, 3"
```
Mapping of inspections to chapters can be found in [Groups of Inspections](info/rules-mapping.md) .
Mapping of inspections to chapters can be found in [Groups of Inspections](info/rules-mapping.md).
</details>
## Running against the baseline
When setting up code style analysis on a large existing project, one often doesn't have an ability to fix all findings at once.
Expand All @@ -318,27 +343,5 @@ java -jar ktlint -R dikat.jar --baseline=diktat-baseline.xml **/*.kt
or with corresponding configuration options in maven or gradle plugins. Baseline report is intended to be added into the VCS,
but it can be removed and re-generated later, if needed.

## How to contribute?
Main components are:
1) diktat-rules — number of rules that are supported by diKTat;
2) diktat-test-framework — functional/unit test framework that can be used for running your code fixer on the initial code and compare it with the expected result;
3) also see our demo: diktat-demo in a separate repository.
Mainly we wanted to create a common configurable mechanism that
will give us a chance to enable/disable and customize all rules.
That's why we added logic for:
1) Parsing `.yml` file with configurations of rules and passing it to visitors;
2) Passing information about properties to visitors.
This information is very useful, when you are trying to get,
for example, a filename of file where the code is stored;
3) We added a bunch of visitors, checkers and fixers that will extended KTlint functionaliity with code style rules;
4) We have proposed a code style for Kotlin language.

Before you make a pull request, make sure the build is clean as we have lot of tests and other prechecks:

```bash
$ mvn clean install
```

Also see our [Contributing Policy](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md)
## Contribution
See our [Contributing Policy](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md)
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ open class DiktatExtension(
*/
var debug = false

/**
* Property that will be used if you need to publish the report to GitHub
*/
var githubActions = false

/**
* Type of the reporter to use
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,37 @@ open class DiktatJavaExecTaskBase @Inject constructor(
// appending the flag with the reporter
setReporter(diktatExtension, flag)

if (diktatExtension.output.isNotEmpty()) {
flag.append(",output=${diktatExtension.output}")
val outFlag = when {
// githubActions should have higher priority than a custom input
diktatExtension.githubActions -> ",output=${project.projectDir}/${project.name}"
diktatExtension.output.isNotEmpty() -> ",output=${diktatExtension.output}"
else -> ""
}

flag.append(outFlag)

return flag.toString()
}

@Suppress("SAY_NO_TO_VAR")
private fun setReporter(diktatExtension: DiktatExtension, flag: java.lang.StringBuilder) {
val name = diktatExtension.reporter.trim()
val validReporters = listOf("sarif", "plain", "json", "html")
if (name.isEmpty() || !validReporters.contains(name)) {
var reporterFlag = if (name.isEmpty() || !validReporters.contains(name)) {
project.logger.warn("Reporter name $name was not specified or is invalid. Falling to 'plain' reporter")
flag.append("--reporter=plain")
"--reporter=plain"
} else {
flag.append("--reporter=$name")
"--reporter=$name"
}

// githubActions should have higher priority than a custom input
if (diktatExtension.githubActions) {
// need to set user.home specially for ktlint, so it will be able to put a relative path URI in SARIF
System.setProperty("user.home", project.projectDir.toString())
reporterFlag = "--reporter=sarif"
}

flag.append(reporterFlag)
}

@Suppress("MagicNumber")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.pinterest.ktlint.reporter.html.HtmlReporter
import com.pinterest.ktlint.reporter.json.JsonReporter
import com.pinterest.ktlint.reporter.plain.PlainReporter
import com.pinterest.ktlint.reporter.sarif.SarifReporter
import org.apache.maven.execution.MavenSession
import org.apache.maven.plugin.AbstractMojo
import org.apache.maven.plugin.MojoExecutionException
import org.apache.maven.plugin.MojoFailureException
Expand All @@ -34,6 +35,12 @@ abstract class DiktatBaseMojo : AbstractMojo() {
@Parameter(property = "diktat.debug")
var debug = false

/**
* Property that will be used if you need to publish the report to GitHub
*/
@Parameter(property = "diktat.githubActions")
var githubActions = false

/**
* Type of the reporter to use
*/
Expand Down Expand Up @@ -80,6 +87,9 @@ abstract class DiktatBaseMojo : AbstractMojo() {
@Parameter(property = "diktat.excludes", defaultValue = "")
lateinit var excludes: List<String>

@Parameter(defaultValue = "\${session}", readonly = true)
private lateinit var mavenSession: MavenSession

/**
* @param params instance of [KtLint.Params] used in analysis
*/
Expand All @@ -106,6 +116,7 @@ abstract class DiktatBaseMojo : AbstractMojo() {
val baselineResults = baseline?.let { loadBaseline(it.absolutePath) }
?: CurrentBaseline(emptyMap(), false)
reporterImpl = resolveReporter(baselineResults)
reporterImpl.beforeAll()
val lintErrors: MutableList<LintError> = mutableListOf()

inputs
Expand All @@ -121,16 +132,30 @@ abstract class DiktatBaseMojo : AbstractMojo() {
}

private fun resolveReporter(baselineResults: CurrentBaseline): Reporter {
val output = if (this.output.isBlank()) System.`out` else PrintStream(FileOutputStream(this.output, true))

val actualReporter = when (this.reporter) {
"sarif" -> SarifReporter(output)
"plain" -> PlainReporter(output)
"json" -> JsonReporter(output)
"html" -> HtmlReporter(output)
else -> {
log.warn("Reporter name ${this.reporter} was not specified or is invalid. Falling to 'plain' reporter")
PlainReporter(output)
val output = if (this.output.isBlank()) {
if (this.githubActions) {
// need to set user.home specially for ktlint, so it will be able to put a relative path URI in SARIF
System.setProperty("user.home", mavenSession.executionRootDirectory)
PrintStream(FileOutputStream("${mavenProject.basedir}/${mavenProject.name}.sarif", false))
} else {
System.`out`
}
} else {
PrintStream(FileOutputStream(this.output, false))
}

val actualReporter = if (this.githubActions) {
SarifReporter(output)
} else {
when (this.reporter) {
"sarif" -> SarifReporter(output)
"plain" -> PlainReporter(output)
"json" -> JsonReporter(output)
"html" -> HtmlReporter(output)
else -> {
log.warn("Reporter name ${this.reporter} was not specified or is invalid. Falling to 'plain' reporter")
PlainReporter(output)
}
}
}

Expand Down
Binary file added example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0698727

Please sign in to comment.