chore: devcontainer, docs, prettier config (#6119)

- Update devcontainer by setting Prettier as a formatter only for
  supported languages.
- Install only the VS Code extensions that we need for Super-linter
  development.
- Remove the devcontainer as soon as it's not needed to avoid leaving
  leftovers behind.
- Enable proseWrap in Prettier configuration.
- Update documentation about how to configure new linters.
- Fix linting issues.
This commit is contained in:
Marco Ferrari 2024-09-13 14:37:48 +02:00 committed by GitHub
parent 72a4884f7a
commit 170cabf92b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 302 additions and 179 deletions

View file

@ -1,32 +1,48 @@
{ {
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json",
"name": "Super-Linter", "name": "Super-Linter",
"image": "ghcr.io/super-linter/super-linter:latest", "image": "ghcr.io/super-linter/super-linter:latest",
"customizations": { "customizations": {
"vscode": { "vscode": {
"settings": { "settings": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.formatOnSaveMode": "file", "editor.formatOnSaveMode": "file",
"editor.wordWrap": "off", "editor.wordWrap": "off",
"hadolint.cliOptions": [
"--config",
"/workspaces/super-linter/.github/linters/.hadolint.yaml"
],
"markdownlint.config": {
"extends": "${workspaceFolder}/.github/linters/.markdown-lint.yml"
},
"prettier.resolveGlobalModules": true, "prettier.resolveGlobalModules": true,
"redhat.telemetry.enabled": false,
"telemetry.telemetryLevel": "off",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": { "[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.wordWrap": "off" "editor.wordWrap": "off"
}, },
"[shellscript]": { "[shellscript]": {
"editor.defaultFormatter": "mkhl.shfmt" "editor.defaultFormatter": "mkhl.shfmt"
}, },
"[terraform]": { "[yaml]": {
"editor.defaultFormatter": "hashicorp.terraform" "editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[terraform-vars]": {
"editor.defaultFormatter": "hashicorp.terraform"
} }
}, },
"extensions": [ "extensions": [
"DavidAnson.vscode-markdownlint", "DavidAnson.vscode-markdownlint",
"EditorConfig.EditorConfig", "EditorConfig.EditorConfig",
"HashiCorp.terraform",
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"exiasr.hadolint",
"GitHub.vscode-github-actions", "GitHub.vscode-github-actions",
"GitHub.vscode-pull-request-github", "GitHub.vscode-pull-request-github",
"mads-hartmann.bash-ide-vscode", "mads-hartmann.bash-ide-vscode",
@ -89,5 +105,5 @@
"type": "bind" "type": "bind"
} }
], ],
"runArgs": ["--env-file", ".devcontainer/devcontainer.env"] "runArgs": ["--env-file", ".devcontainer/devcontainer.env", "--rm"]
} }

View file

@ -2,8 +2,8 @@
:wave: Hi there! :wave: Hi there!
We're thrilled that you'd like to contribute to this project. We're thrilled that you'd like to contribute to this project. Your help is
Your help is essential for keeping it great. essential for keeping it great.
## Submitting a pull request ## Submitting a pull request
@ -16,7 +16,8 @@ request being accepted:
- Keep your change as focused as possible. If there are multiple changes you - Keep your change as focused as possible. If there are multiple changes you
would like to make that are not dependent upon each other, submit them as would like to make that are not dependent upon each other, submit them as
separate pull requests. separate pull requests.
- Write [descriptive commit messages](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). - Write
[descriptive commit messages](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
Draft pull requests are also welcome to get feedback early on, or if there is Draft pull requests are also welcome to get feedback early on, or if there is
something blocking you. something blocking you.

View file

@ -17,14 +17,20 @@ In order to have this pull request merged, complete the following tasks.
- [ ] I included all the needed documentation for this change. - [ ] I included all the needed documentation for this change.
- [ ] I provided the necessary tests. - [ ] I provided the necessary tests.
- [ ] I squashed all the commits into a single commit. - [ ] I squashed all the commits into a single commit.
- [ ] I followed the [Conventional Commit v1.0.0 spec](https://www.conventionalcommits.org/en/v1.0.0/). - [ ] I followed the
- [ ] I wrote the necessary upgrade instructions in the [upgrade guide](../docs/upgrade-guide.md). [Conventional Commit v1.0.0 spec](https://www.conventionalcommits.org/en/v1.0.0/).
- [ ] If this pull request is about and existing issue, - [ ] I wrote the necessary upgrade instructions in the
I added the `Fix #ISSUE_NUMBER` or `Close #ISSUE_NUMBER` text to the description of the pull request. [upgrade guide](../docs/upgrade-guide.md).
- [ ] If this pull request is about and existing issue, I added the
`Fix #ISSUE_NUMBER` or `Close #ISSUE_NUMBER` text to the description of
the pull request.
### Super-linter maintainer tasks ### Super-linter maintainer tasks
- [ ] Label as `breaking` if this change breaks compatibility with the previous released version. - [ ] Label as `breaking` if this change breaks compatibility with the previous
- [ ] Label as either: `automation`, `bug`, `documentation`, `enhancement`, `infrastructure`. released version.
- [ ] Label as either: `automation`, `bug`, `documentation`, `enhancement`,
`infrastructure`.
- [ ] Add the pull request to a milestone, eventually creating one, that matches - [ ] Add the pull request to a milestone, eventually creating one, that matches
with the version that release-please proposes in the `preview-release-notes` CI job. with the version that release-please proposes in the
`preview-release-notes` CI job.

View file

@ -207,6 +207,7 @@ jobs:
FILTER_REGEX_EXCLUDE: ".*(/test/linters/|CHANGELOG.md).*" FILTER_REGEX_EXCLUDE: ".*(/test/linters/|CHANGELOG.md).*"
RENOVATE_SHAREABLE_CONFIG_PRESET_FILE_NAMES: "default.json,hoge.json" RENOVATE_SHAREABLE_CONFIG_PRESET_FILE_NAMES: "default.json,hoge.json"
TYPESCRIPT_STANDARD_TSCONFIG_FILE: ".github/linters/tsconfig.json" TYPESCRIPT_STANDARD_TSCONFIG_FILE: ".github/linters/tsconfig.json"
VALIDATE_JAVASCRIPT_STANDARD: false
- name: Get the contents of the log file - name: Get the contents of the log file
run: | run: |
@ -221,6 +222,7 @@ jobs:
GITLEAKS_CONFIG_FILE: .gitleaks-ignore-tests.toml GITLEAKS_CONFIG_FILE: .gitleaks-ignore-tests.toml
FILTER_REGEX_EXCLUDE: ".*(/test/linters/|CHANGELOG.md).*" FILTER_REGEX_EXCLUDE: ".*(/test/linters/|CHANGELOG.md).*"
TYPESCRIPT_STANDARD_TSCONFIG_FILE: ".github/linters/tsconfig.json" TYPESCRIPT_STANDARD_TSCONFIG_FILE: ".github/linters/tsconfig.json"
VALIDATE_JAVASCRIPT_STANDARD: false
build-test-suite-matrix: build-test-suite-matrix:
name: Build test suite matrix name: Build test suite matrix

View file

@ -5,9 +5,9 @@
In the interest of fostering an open and welcoming environment, we as In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression, size, disability, ethnicity, sex characteristics, gender identity and
level of experience, education, socio-economic status, nationality, personal expression, level of experience, education, socio-economic status, nationality,
appearance, race, religion, or sexual identity and orientation. personal appearance, race, religion, or sexual identity and orientation.
## Our Standards ## Our Standards
@ -37,11 +37,11 @@ Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior. response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or Project maintainers have the right and responsibility to remove, edit, or reject
reject comments, commits, code, wiki edits, issues, and other contributions comments, commits, code, wiki edits, issues, and other contributions that are
that are not aligned to this Code of Conduct, or to ban temporarily or not aligned to this Code of Conduct, or to ban temporarily or permanently any
permanently any contributor for other behaviors that they deem inappropriate, contributor for other behaviors that they deem inappropriate, threatening,
threatening, offensive, or harmful. offensive, or harmful.
## Scope ## Scope
@ -58,8 +58,9 @@ Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at <opensource@github.com>. All reported by contacting the project team at <opensource@github.com>. All
complaints will be reviewed and investigated and will result in a response that complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident. obligated to maintain confidentiality with regard to the reporter of an
Further details of specific enforcement policies may be posted separately. incident. Further details of specific enforcement policies may be posted
separately.
Project maintainers who do not follow or enforce the Code of Conduct in good Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other faith may face temporary or permanent repercussions as determined by other
@ -67,11 +68,13 @@ members of the project's leadership.
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.4,
<!-- textlint-disable --> <!-- textlint-disable -->
available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct/) available at
[https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct/)
<!-- textlint-enable --> <!-- textlint-enable -->

View file

@ -242,6 +242,7 @@ test-git-flags: ## Run super-linter with different git-related flags
-e IGNORE_GENERATED_FILES=true \ -e IGNORE_GENERATED_FILES=true \
-e IGNORE_GITIGNORED_FILES=true \ -e IGNORE_GITIGNORED_FILES=true \
-e VALIDATE_ALL_CODEBASE=true \ -e VALIDATE_ALL_CODEBASE=true \
-e VALIDATE_JAVASCRIPT_STANDARD=false \
-v "$(CURDIR)":/tmp/lint \ -v "$(CURDIR)":/tmp/lint \
--rm \ --rm \
$(SUPER_LINTER_TEST_CONTAINER_URL) $(SUPER_LINTER_TEST_CONTAINER_URL)
@ -260,6 +261,7 @@ lint-codebase: ## Lint the entire codebase
-e SAVE_SUPER_LINTER_OUTPUT=true \ -e SAVE_SUPER_LINTER_OUTPUT=true \
-e SAVE_SUPER_LINTER_SUMMARY=true \ -e SAVE_SUPER_LINTER_SUMMARY=true \
-e VALIDATE_ALL_CODEBASE=true \ -e VALIDATE_ALL_CODEBASE=true \
-e VALIDATE_JAVASCRIPT_STANDARD=false \
-v "$(CURDIR):/tmp/lint" \ -v "$(CURDIR):/tmp/lint" \
--rm \ --rm \
$(SUPER_LINTER_TEST_CONTAINER_URL) $(SUPER_LINTER_TEST_CONTAINER_URL)
@ -288,6 +290,7 @@ fix-codebase: ## Fix and format the entire codebase
-e SAVE_SUPER_LINTER_OUTPUT=true \ -e SAVE_SUPER_LINTER_OUTPUT=true \
-e SAVE_SUPER_LINTER_SUMMARY=true \ -e SAVE_SUPER_LINTER_SUMMARY=true \
-e VALIDATE_ALL_CODEBASE=true \ -e VALIDATE_ALL_CODEBASE=true \
-e VALIDATE_JAVASCRIPT_STANDARD=false \
-v "$(CURDIR):/tmp/lint" \ -v "$(CURDIR):/tmp/lint" \
--rm \ --rm \
$(SUPER_LINTER_TEST_CONTAINER_URL) \ $(SUPER_LINTER_TEST_CONTAINER_URL) \
@ -618,3 +621,13 @@ release-please-dry-run: build-dev-container-image check-github-token ## Run rele
--target-branch ${RELEASE_PLEASE_TARGET_BRANCH} \ --target-branch ${RELEASE_PLEASE_TARGET_BRANCH} \
--token "${GITHUB_TOKEN}" \ --token "${GITHUB_TOKEN}" \
--trace --trace
.PHONY: open-shell-dev-container
open-shell-dev-container: build-dev-container-image ## Open a shell in the dev tools container
docker run $(DOCKER_FLAGS) \
--interactive \
--entrypoint /bin/bash \
--rm \
-v "$(CURDIR)/dev-dependencies/package-lock.json":/package-lock.json \
-v "$(CURDIR)/dev-dependencies/package.json":/package.json \
$(DEV_CONTAINER_URL)

View file

@ -1,7 +1,7 @@
# Super-Linter # Super-Linter
Super-linter is a ready-to-run collection of linters and code analyzers, to Super-linter is a ready-to-run collection of linters and code analyzers, to help
help validate and fix your source code. validate and fix your source code.
The goal of super-linter is to help you establish best practices and consistent The goal of super-linter is to help you establish best practices and consistent
formatting across multiple programming languages, and ensure developers are formatting across multiple programming languages, and ensure developers are
@ -10,9 +10,11 @@ adhering to those conventions.
Super-linter analyzes source code files using several tools, and reports the Super-linter analyzes source code files using several tools, and reports the
issues that those tools find as console output, and as issues that those tools find as console output, and as
[GitHub Actions status checks](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks). [GitHub Actions status checks](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks).
You can also [run super-linter outside GitHub Actions](#run-super-linter-outside-github-actions). You can also
[run super-linter outside GitHub Actions](#run-super-linter-outside-github-actions).
Super-linter can also help you [fix linting and formatting issues](#fix-linting-and-formatting-issues). Super-linter can also help you
[fix linting and formatting issues](#fix-linting-and-formatting-issues).
Super-linter is licensed under an Super-linter is licensed under an
[MIT License](https://github.com/super-linter/super-linter/blob/main/LICENSE). [MIT License](https://github.com/super-linter/super-linter/blob/main/LICENSE).
@ -29,9 +31,9 @@ Here are some notable Super-linter features:
[most widely used](https://github.com/super-linter/super-linter/network/dependents) [most widely used](https://github.com/super-linter/super-linter/network/dependents)
and [forked](https://github.com/super-linter/super-linter/forks) project of and [forked](https://github.com/super-linter/super-linter/forks) project of
this kind. this kind.
- **Runs linters in parallel**: Since `v6`, Super-linter parallelizes - **Runs linters in parallel**: Since `v6`, Super-linter parallelizes running
running all the included linters, leading to scanning massive code all the included linters, leading to scanning massive code repositories in
repositories in seconds. seconds.
- **Highly curated set of linters**: Avoid including linters that implement - **Highly curated set of linters**: Avoid including linters that implement
overlapping checks, reducing bloat, scanning times, and container image size. overlapping checks, reducing bloat, scanning times, and container image size.
- **Run on GitHub Actions or other environments**: Super-linter runs - **Run on GitHub Actions or other environments**: Super-linter runs
@ -114,11 +116,14 @@ Super-linter supports the following tools:
## Get started ## Get started
More in-depth [tutorial](https://www.youtube.com/watch?v=EDAmFKO4Zt0&t=118s) available More in-depth [tutorial](https://www.youtube.com/watch?v=EDAmFKO4Zt0&t=118s)
available
To run super-linter as a GitHub Action, you do the following: To run super-linter as a GitHub Action, you do the following:
1. Create a new [GitHub Actions workflow](https://docs.github.com/en/actions/using-workflows/about-workflows#about-workflows) in your repository with the following content: 1. Create a new
[GitHub Actions workflow](https://docs.github.com/en/actions/using-workflows/about-workflows#about-workflows)
in your repository with the following content:
```yaml ```yaml
--- ---
@ -182,8 +187,10 @@ For more information, see
Super-Linter provides several variants: Super-Linter provides several variants:
- `standard`: `super-linter/super-linter@[VERSION]`: includes all supported linters. - `standard`: `super-linter/super-linter@[VERSION]`: includes all supported
- `slim`: `super-linter/super-linter/slim@[VERSION]`: includes all supported linters except: linters.
- `slim`: `super-linter/super-linter/slim@[VERSION]`: includes all supported
linters except:
- Rustfmt - Rustfmt
- Rust Clippy - Rust Clippy
@ -419,9 +426,13 @@ You can configure Super-linter using the following environment variables:
The `VALIDATE_[LANGUAGE]` variables work as follows: The `VALIDATE_[LANGUAGE]` variables work as follows:
- super-linter runs all supported linters by default. - super-linter runs all supported linters by default.
- If you set any of the `VALIDATE_[LANGUAGE]` variables to `true`, super-linter defaults to leaving any unset variable to false (only validate those languages). - If you set any of the `VALIDATE_[LANGUAGE]` variables to `true`, super-linter
- If you set any of the `VALIDATE_[LANGUAGE]` variables to `false`, super-linter defaults to leaving any unset variable to true (only exclude those languages). defaults to leaving any unset variable to false (only validate those
- If you set any of the `VALIDATE_[LANGUAGE]` variables to both `true` and `false`, super-linter fails reporting an error. languages).
- If you set any of the `VALIDATE_[LANGUAGE]` variables to `false`, super-linter
defaults to leaving any unset variable to true (only exclude those languages).
- If you set any of the `VALIDATE_[LANGUAGE]` variables to both `true` and
`false`, super-linter fails reporting an error.
For more information about reusing Super-linter configuration across For more information about reusing Super-linter configuration across
environments, see environments, see
@ -430,9 +441,9 @@ environments, see
## Fix linting and formatting issues ## Fix linting and formatting issues
All the linters and formatters that Super-linter runs report errors if they All the linters and formatters that Super-linter runs report errors if they
detect linting or formatting issues without modifying your source detect linting or formatting issues without modifying your source code (_check
code (_check only mode_). Check only mode is the default for all linters and only mode_). Check only mode is the default for all linters and formatters that
formatters that Super-linter runs. Super-linter runs.
Certain linters and formatters support automatically fixing issues in your code Certain linters and formatters support automatically fixing issues in your code
(_fix mode_). You can enable fix mode for a particular linter or formatter by (_fix mode_). You can enable fix mode for a particular linter or formatter by
@ -467,8 +478,8 @@ configuration that doesn't ignore the `yaml` rule.
### Fix mode file and directory ownership ### Fix mode file and directory ownership
When fix mode is enabled, some linters and formatters don't maintain the When fix mode is enabled, some linters and formatters don't maintain the
original file or directory ownership, and use the user that Super-linter uses original file or directory ownership, and use the user that Super-linter uses to
to run the linter or formatter. run the linter or formatter.
### Fix mode examples and workflows ### Fix mode examples and workflows
@ -487,6 +498,7 @@ automatically fix linting and formatting issues, commit changes in the current
branch, and push commits to the remote branch tracking the current branch branch, and push commits to the remote branch tracking the current branch
whenever a pull request is created or updated: whenever a pull request is created or updated:
<!-- prettier-ignore-start -->
```yaml ```yaml
--- ---
name: Lint name: Lint
@ -538,6 +550,7 @@ jobs:
commit_user_name: super-linter commit_user_name: super-linter
commit_user_email: super-linter@super-linter.dev commit_user_email: super-linter@super-linter.dev
``` ```
<!-- prettier-ignore-end -->
This example uses This example uses
[GitHub Actions automatic token authentication](https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication) [GitHub Actions automatic token authentication](https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication)
@ -570,10 +583,11 @@ To work around these limitations, you do the following:
## Configure linters ## Configure linters
Super-linter provides default configurations for some linters in the [`TEMPLATES/`](./TEMPLATES/) Super-linter provides default configurations for some linters in the
directory. You can customize the configuration for the linters that support [`TEMPLATES/`](./TEMPLATES/) directory. You can customize the configuration for
this by placing your own configuration files in the `LINTER_RULES_PATH` the linters that support this by placing your own configuration files in the
directory. `LINTER_RULES_PATH` is relative to the `DEFAULT_WORKSPACE` directory. `LINTER_RULES_PATH` directory. `LINTER_RULES_PATH` is relative to the
`DEFAULT_WORKSPACE` directory.
Super-linter supports customizing the name of these configuration files. For Super-linter supports customizing the name of these configuration files. For
more information, refer to [Configure super-linter](#configure-super-linter). more information, refer to [Configure super-linter](#configure-super-linter).
@ -601,15 +615,17 @@ For example:
- Lint only the `src` folder: `FILTER_REGEX_INCLUDE: .*src/.*` - Lint only the `src` folder: `FILTER_REGEX_INCLUDE: .*src/.*`
- Do not lint files inside test folder: `FILTER_REGEX_EXCLUDE: .*test/.*` - Do not lint files inside test folder: `FILTER_REGEX_EXCLUDE: .*test/.*`
- Do not lint JavaScript files inside test folder: `FILTER_REGEX_EXCLUDE: .*test/.*.js` - Do not lint JavaScript files inside test folder:
- Do not lint files named `gradlew` and JavaScript files inside a specific directory: `.*/gradlew|.*/specific/directory/*.js` `FILTER_REGEX_EXCLUDE: .*test/.*.js`
- Do not lint files named `gradlew` and JavaScript files inside a specific
directory: `.*/gradlew|.*/specific/directory/*.js`
<!-- This `README.md` has both markers in the text, so it is considered not generated. --> <!-- This `README.md` has both markers in the text, so it is considered not generated. -->
Additionally, if you set `IGNORE_GENERATED_FILES` to `true`, super-linter Additionally, if you set `IGNORE_GENERATED_FILES` to `true`, super-linter
ignores any file with `@generated` string in it, unless the file ignores any file with `@generated` string in it, unless the file also has
also has `@not-generated` marker. For example, super-linter considers a file `@not-generated` marker. For example, super-linter considers a file with the
with the following contents as generated: following contents as generated:
```bash ```bash
#!/bin/sh #!/bin/sh
@ -665,7 +681,8 @@ env:
If you need to inject a SSL certificate into the trust store, you can use the If you need to inject a SSL certificate into the trust store, you can use the
`SSL_CERT_SECRET` variable. The value of that variable is expected to be the `SSL_CERT_SECRET` variable. The value of that variable is expected to be the
path to the files that contains a CA that can be used to validate the certificate: path to the files that contains a CA that can be used to validate the
certificate:
```yaml ```yaml
env: env:
@ -674,15 +691,15 @@ env:
## Outputs ## Outputs
Super-linter supports generating several outputs, and also supports exposing Super-linter supports generating several outputs, and also supports exposing the
the output of individual linters. output of individual linters.
### Summary outputs ### Summary outputs
Super-linter writes a summary of all the checks: Super-linter writes a summary of all the checks:
- If `SAVE_SUPER_LINTER_SUMMARY` is set to `true`, Super-linter writes - If `SAVE_SUPER_LINTER_SUMMARY` is set to `true`, Super-linter writes a summary
a summary to to
`${DEFAULT_WORKSPACE}/${SUPER_LINTER_OUTPUT_DIRECTORY_NAME}/${SUPER_LINTER_SUMMARY_FILE_NAME}`. `${DEFAULT_WORKSPACE}/${SUPER_LINTER_OUTPUT_DIRECTORY_NAME}/${SUPER_LINTER_SUMMARY_FILE_NAME}`.
- If `ENABLE_GITHUB_ACTIONS_STEP_SUMMARY` is set to `true`, Super-linter writes - If `ENABLE_GITHUB_ACTIONS_STEP_SUMMARY` is set to `true`, Super-linter writes
a GitHub Actions job summary. Setting `ENABLE_GITHUB_ACTIONS_STEP_SUMMARY` to a GitHub Actions job summary. Setting `ENABLE_GITHUB_ACTIONS_STEP_SUMMARY` to
@ -697,8 +714,8 @@ The summary output of previous Super-linter runs is not preserved.
### Super-linter outputs ### Super-linter outputs
If you set `SAVE_SUPER_LINTER_OUTPUT` to `true`, Super-linter saves its output If you set `SAVE_SUPER_LINTER_OUTPUT` to `true`, Super-linter saves its output
to `${DEFAULT_WORKSPACE}/${SUPER_LINTER_OUTPUT_DIRECTORY_NAME}/super-linter`, so you to `${DEFAULT_WORKSPACE}/${SUPER_LINTER_OUTPUT_DIRECTORY_NAME}/super-linter`, so
can further process it, if needed. you can further process it, if needed.
Most outputs are in JSON format. Most outputs are in JSON format.

View file

@ -1,6 +1,10 @@
# TEMPLATES # TEMPLATES
The files in this folder are template rules for the linters that will run against your codebase. If you choose to copy these to your local repository in the `.github/linters/` directory, they will be used at runtime. If rule files are not present locally, the templates will be used by default. The files in this folder are template rules for the linters that will run
against your codebase. If you choose to copy these to your local repository in
the `.github/linters/` directory, they will be used at runtime. If rule files
are not present locally, the templates will be used by default.
The file(s) will be parsed at runtime on the local branch to load all rules needed to run the **Super-Linter** **GitHub** Action. The file(s) will be parsed at runtime on the local branch to load all rules
The **GitHub** Action will inform the user via the **Checks API** on the status and success of the process. needed to run the **Super-Linter** **GitHub** Action. The **GitHub** Action will
inform the user via the **Checks API** on the status and success of the process.

View file

@ -1,39 +1,50 @@
# How to add support for a new tool to super-linter # How to add support for a new tool to super-linter
If you want to propose a _Pull Request_ to add **new** language support or a If you want to propose a _Pull Request_ to add **new** language support or a new
new tool, it should include: tool, do the following.
- Update documentation: ## Update documentation
- `README.md`
- Provide test cases:
1. Create the `test/linters/<LANGUAGE_NAME>` directory. - `README.md`
2. Provide at least one test case with a file that is supposed to pass validation,
with the right file extension if needed: `test/linters/<LANGUAGE_NAME>/<name-of-tool>-good`
3. Provide at least one test case with a file that is supposed to fail validation,
with the right file extension if needed: `test/linters/<LANGUAGE_NAME>/<name-of-tool>-bad`.
If the linter supports fix mode, the test case supposed to fail validation
should only contain violations that the fix mode can automatically fix.
Avoid test cases that fail only because of syntax errors, when possible.
4. Update expected summary reports: `test/data/super-linter-summary`.
5. If the linter supports check-only mode or fix mode, add the `<LANGUGAGE>`
to the `LANGUAGES_WITH_FIX_MODE` array in `test/testUtils.sh`
- Update the test suite to check for installed packages, the commands that your new tool needs in the `PATH`, and the expected version command: ## Provide test cases
- `test/inspec/super-linter/controls/super_linter.rb` 1. Create the `test/linters/<LANGUAGE_NAME>` directory.
2. Provide at least one test case with a file that is supposed to pass
validation, with the right file extension if needed:
`test/linters/<LANGUAGE_NAME>/<name-of-tool>-good`
3. Provide at least one test case with a file that is supposed to fail
validation, with the right file extension if needed:
`test/linters/<LANGUAGE_NAME>/<name-of-tool>-bad`. If the tool supports fix
mode, the test case supposed to fail validation should only contain
violations that the fix mode can automatically fix. Avoid test cases that
fail only because of syntax errors, when possible.
4. Update expected summary reports: `test/data/super-linter-summary`.
5. If the tool supports check-only mode or fix mode, add the `<LANGUGAGE>` to
the `LANGUAGES_WITH_FIX_MODE` array in `test/testUtils.sh`
## Update the test suite
Update the test suite to check for installed packages, the commands that your
new tool needs in the `PATH`, and the expected version command:
- `test/inspec/super-linter/controls/super_linter.rb`
## Install the tool
- Install the tool by pointing to specific package or container image versions: - Install the tool by pointing to specific package or container image versions:
- If there are PyPi packages, create a text file named `dependencies/python/<name-of-tool>.txt` - If there are PyPi packages, create a text file named
and list the packages there. `dependencies/python/<name-of-tool>.txt` and list the packages there.
- If there are npm packages, update `dependencies/package.json` and `dependencies/package-lock.json`. - If there are npm packages, update `dependencies/package.json` and
by adding the new packages. `dependencies/package-lock.json`. by adding the new packages.
- If there are Ruby Gems, update `dependencies/Gemfile` and `dependencies/Gemfile.lock` - If there are Ruby Gems, update `dependencies/Gemfile` and
`dependencies/Gemfile.lock`
- If there are Maven or Java packages: - If there are Maven or Java packages:
1. Create a directory named `dependencies/<name-of-tool>`. 1. Create a directory named `dependencies/<name-of-tool>`.
2. Create a `dependencies/<name-of-tool>/build.gradle` file with the following contents: 2. Create a `dependencies/<name-of-tool>/build.gradle` file with the
following contents:
```gradle ```gradle
repositories { repositories {
@ -50,8 +61,8 @@ new tool, it should include:
version '1.0.0-SNAPSHOT' version '1.0.0-SNAPSHOT'
``` ```
3. Update the `dependencies` section in `dependencies/<name-of-tool>/build.gradle` to 3. Update the `dependencies` section in
install your dependencies. `dependencies/<name-of-tool>/build.gradle` to install your dependencies.
4. Add the following content to the `Dockerfile`: 4. Add the following content to the `Dockerfile`:
```dockerfile ```dockerfile
@ -59,8 +70,9 @@ new tool, it should include:
RUN --mount=type=secret,id=GITHUB_TOKEN /<name-of-tool>.sh && rm -rf /<name-of-tool>.sh RUN --mount=type=secret,id=GITHUB_TOKEN /<name-of-tool>.sh && rm -rf /<name-of-tool>.sh
``` ```
5. Create `scripts/install-<name-of-tool>.sh`, and implement the logic to install your tool. 5. Create `scripts/install-<name-of-tool>.sh`, and implement the logic to
You get the version of a dependency from `build.gradle`. Example: install your tool. You get the version of a dependency from
`build.gradle`. Example:
```sh ```sh
GOOGLE_JAVA_FORMAT_VERSION="$(grep <"google-java-format/build.gradle" "google-java-format" | awk -F ':' '{print $3}' | tr -d "'")" GOOGLE_JAVA_FORMAT_VERSION="$(grep <"google-java-format/build.gradle" "google-java-format" | awk -F ':' '{print $3}' | tr -d "'")"
@ -84,89 +96,119 @@ new tool, it should include:
FROM your/image:version as <name-of-tool> FROM your/image:version as <name-of-tool>
``` ```
1. Copy the necessary binaries and libraries to the relevant locations. Example: 1. Copy the necessary binaries and libraries to the relevant locations.
Example:
```sh ```sh
COPY --from=<name-of-tool> /usr/local/bin/<name-of-command> /usr/bin/ COPY --from=<name-of-tool> /usr/local/bin/<name-of-command> /usr/bin/
``` ```
- Configure the new tool: ## Run the new tool
- Provide a default configuration file only if the tool cannot function without one: `TEMPLATES/<template file for language>`
- Provide a configuration file for the new linter only if the default configuration is unsuitable for the super-linter repository: `.github/linters/.<lintrc>`
- Update the orchestration scripts to run the new tool: - Update the orchestration scripts to run the new tool:
- `lib/globals/languages.sh`: add a new item to `LANGUAGES_ARRAY` array. Use the - `lib/globals/languages.sh`: add a new item to `LANGUAGES_ARRAY` array. Use
"name" of the language, then a `_`, and finally the name of the linter. Example: `PYTHON_RUFF`. the "name" of the language, then a `_`, and finally the name of the tool. To
In the context of this document, to avoid repetitions we reference this new allow for future additions, use a language name and a tool name for the new
item as `<LANGUAGE_NAME>`. item. Example: `PYTHON_RUFF`. In the context of this document, to avoid
repetitions we reference this new item as `<LANGUAGE_NAME>`.
- Linter configuration: - Define the command to invoke the new tool:
- Create a new minimal configuration file in the `TEMPLATES` directory with the same name as the - `lib/functions/linterCommands.sh`: add the command to invoke the tool.
default configuration filename. Example: `TEMPLATES/.ruff.toml`. Define a new variable: `LINTER_COMMANDS_ARRAY_<LANGUAGE_NAME>`. Example:
- `lib/globals/linterRules.sh`: `LINTER_COMMANDS_ARRAY_GO_MODULES=(golangci-lint run --allow-parallel-runners)`
- If the new linter accepts a configuration files from the command line, - If there are arguments that you can only pass using the command line,
define a new variable: and you think users might want to customize them, define a new variable
`<LANGUAGE_NAME>_FILE_NAME="${<LANGUAGE_NAME>_CONFIG_FILE:-"default-config-file-name.conf"}"` using `<LANGUAGE_NAME>_COMMAND_ARGS` and add it to the command if the
where `default-config-file-name.conf` is the name of the new,
minimal configuration for the linter. Example:
`PYTHON_RUFF_FILE_NAME="${PYTHON_RUFF_CONFIG_FILE:-.ruff.toml}"`.
- If there are arguments that you can only pass using the command line, and you think users
might want to customize them, define a new variable using
`<LANGUAGE_NAME>_COMMAND_ARGS` and add it to the command if the
configuration provides it. Example: configuration provides it. Example:
```bash ```bash
<LANGUAGE_NAME>_COMMAND_ARGS="${<LANGUAGE_NAME>_COMMAND_ARGS:-""}" <LANGUAGE_NAME>_COMMAND_ARGS="${<LANGUAGE_NAME>_COMMAND_ARGS:-""}"
if [ -n "${<LANGUAGE_NAME>_COMMAND_ARGS:-}" ]; then if [ -n "${<LANGUAGE_NAME>_COMMAND_ARGS:-}" ]; then
export <LANGUAGE_NAME>_COMMAND_ARGS export <LANGUAGE_NAME>_COMMAND_ARGS
LINTER_COMMANDS_ARRAY_<LANGUAGE_NAME>+=("${<LANGUAGE_NAME>_COMMAND_ARGS}") AddOptionsToCommand "LINTER_COMMANDS_ARRAY_<LANGUAGE_NAME>" "${<LANGUAGE_NAME>_COMMAND_ARGS}"
fi fi
``` ```
- Define the command to invoke the new linter:
- `lib/functions/linterCommands.sh`: add the command to invoke the linter.
Define a new variable: `LINTER_COMMANDS_ARRAY_<LANGUAGE_NAME>`.
Example:
`LINTER_COMMANDS_ARRAY_GO_MODULES=(golangci-lint run --allow-parallel-runners -c "${GO_LINTER_RULES}")`
If the linter needs to load a configuration file, add the relevant options
and paths to the command you just defined. The path to the configuration
file is automatically initialized by Super-linter using in the
`<LANGUAGE_NAME>_LINTER_RULES` variable, as in the `GO_LINTER_RULES`
example above for the `GO` language.
- `lib/globals/linterCommandsOptions.sh`: add "check only mode" and "fix - `lib/globals/linterCommandsOptions.sh`: add "check only mode" and "fix
linting and formatting issues mode" options if the linter supports it. linting and formatting issues mode" options if the tool supports it.
Super-linter will automatically add them to the command to run the linter. Super-linter will automatically add them to the command to run the tool.
- If the linter runs in "fix linting and formatting issues mode" by - If the tool runs in "fix linting and formatting issues mode" by default,
default, define a new variable with the options to add to the linter define a new variable with the options to add to the tool command to
command to enable "check only mode": enable "check only mode":
`<LANGUAGE_NAME>_CHECK_ONLY_MODE_OPTIONS=(....)`. `<LANGUAGE_NAME>_CHECK_ONLY_MODE_OPTIONS=(....)`. Example:
Example: `PYTHON_BLACK_CHECK_ONLY_MODE_OPTIONS=(--diff --check)` `PYTHON_BLACK_CHECK_ONLY_MODE_OPTIONS=(--diff --check)`
- If the linter runs in "check only mode" by - If the tool runs in "check only mode" by default, define a new variable
default, define a new variable with the options to add to the linter with the options to add to the tool command to enable "fix linting and
command to enable "fix linting and formatting issues mode": formatting issues mode": `<LANGUAGE_NAME>_FIX_MODE_OPTIONS=(...)`.
`<LANGUAGE_NAME>_FIX_MODE_OPTIONS=(...)`.
Example: `ANSIBLE_FIX_MODE_OPTIONS=(--fix)` Example: `ANSIBLE_FIX_MODE_OPTIONS=(--fix)`
- Provide the logic to populate the list of files or directories to examine: `lib/functions/buildFileList.sh` - If the tool needs option for both the "check only mode" and the fix
- Provide the logic to populate the versions file: `scripts/linterVersions.sh` mode, define both variables as described in the previous points.
- If necessary, provide elaborate logic to detect if the tool should examine a file or a directory: `lib/functions/detectFiles.sh`
- If the tool needs to take into account special cases, reach out to the
maintainers by creating a draft pull request and ask relevant questions
there. For example, you might need to provide new logic or customize
the existing one to:
- Validate the runtime environment: `lib/functions/validation.sh`. ## Configure the new tool
- Get the installed version of the linter: `scripts/linterVersions.sh`
- Load configuration files: `lib/functions/linterRules.sh` If the new tool doesn't support a configuration file search mechanism, update
- Run the linter: `lib/functions/worker.sh` the command to run the new tool to set the path to the configuration file:
- Compose the linter command: `lib/functions/linterCommands.sh`
- Modify the core Super-linter logic: `lib/linter.sh` 1. Define a new variable in `lib/globals/linterRules.sh`:
`<LANGUAGE_NAME>_FILE_NAME="${<LANGUAGE_NAME>_CONFIG_FILE:-"default-config-file-name.conf"}"`
where `default-config-file-name.conf` is the name of the new configuration
file for the new tool. Use one of the default recommended configurationfile
names for the new tool. Example:
`PYTHON_RUFF_FILE_NAME="${PYTHON_RUFF_CONFIG_FILE:-.ruff.toml}"`.
Super-linter automatically initializes the path to the configuration file in
the `<LANGUAGE_NAME>_LINTER_RULES` variable using the
`<LANGUAGE_NAME>_FILE_NAME`. Example: `PYTHON_RUFF_LINTER_RULES`
1. Create a new minimal configuration file in the `TEMPLATES` directory.
Example: `TEMPLATES/default-config-file-name.conf`.
1. Update `lib/functions/linterCommands.sh` to set the path to the configuration
file path. Example: `htmlhint --config "${HTML_LINTER_RULES}"`
### Configure the new tool for the Super-linter repository
If the default configuration of the new tool is unsuitable for the Super-linter
repository, create a new configuration file for the new tool using the default
filename:
- If the new tool supports a configuration file search mechanism, create the
configuration file in a location where the new tool will find it.
- If the new tool doesn't support a configuration file search mechanism and you
updated the new tool command to set the configuration file path, create the
configuration file in the `.github/linters` directory using its default
filename.
## Populate the file list
Provide the logic to populate the list of files or directories to examine:
`lib/functions/buildFileList.sh`
## Get the tool version
Provide the logic to populate the versions file: `scripts/linterVersions.sh`
## Detection logic
If necessary, provide elaborate logic to detect if the tool should examine a
file or a directory: `lib/functions/detectFiles.sh`
## Special cases
If the tool needs to take into account special cases, reach out to the
maintainers by creating a draft pull request and ask relevant questions there.
For example, you might need to provide new logic or customize the existing one
to:
- Validate the runtime environment: `lib/functions/validation.sh`.
- Get the installed version of the tool: `scripts/linterVersions.sh`
- Load configuration files: `lib/functions/linterRules.sh`
- Run the tool: `lib/functions/worker.sh`
- Compose the tool command: `lib/functions/linterCommands.sh`
- Modify the core Super-linter logic: `lib/linter.sh`

View file

@ -6,9 +6,9 @@ The Process to create a super-linter release is as follows:
## Preview the release pull request ## Preview the release pull request
In order to have a preview of the next release before merging a pull In order to have a preview of the next release before merging a pull request
request that updates the configuration of the tooling that we use to create that updates the configuration of the tooling that we use to create releases, do
releases, do the following: the following:
1. Run: 1. Run:

View file

@ -5,7 +5,8 @@ runtime engine to run the super-linter container image.
## Run super-linter Locally ## Run super-linter Locally
You can run the container locally with the following configuration options to run your code: You can run the container locally with the following configuration options to
run your code:
```bash ```bash
docker run \ docker run \
@ -16,16 +17,21 @@ docker run \
ghcr.io/super-linter/super-linter:latest ghcr.io/super-linter/super-linter:latest
``` ```
This example uses the `latest` container image version. If you're trying to reproduce This example uses the `latest` container image version. If you're trying to
an issue, or running super-linter as part of your CI pipeline, we recommend that reproduce an issue, or running super-linter as part of your CI pipeline, we
you **refer to a specific version instead**. recommend that you **refer to a specific version instead**.
Notes: Notes:
- To run against a single file you can use: `docker run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true -v /path/to/local/codebase/file:/tmp/lint/file ghcr.io/super-linter/super-linter` - To run against a single file you can use:
- You need to pass the `RUN_LOCAL` option to bypass some of the GitHub Actions checks, as well as the mapping of your local codebase to `/tmp/lint`. `docker run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true -v /path/to/local/codebase/file:/tmp/lint/file ghcr.io/super-linter/super-linter`
- If you want to override the `/tmp/lint` folder, you can set the `DEFAULT_WORKSPACE` environment variable to point to the folder you'd prefer to scan. - You need to pass the `RUN_LOCAL` option to bypass some of the GitHub Actions
- You can add as many configuration options as needed. Configuration options are documented in the [readme](../README.md#configure-super-linter). checks, as well as the mapping of your local codebase to `/tmp/lint`.
- If you want to override the `/tmp/lint` folder, you can set the
`DEFAULT_WORKSPACE` environment variable to point to the folder you'd prefer
to scan.
- You can add as many configuration options as needed. Configuration options are
documented in the [readme](../README.md#configure-super-linter).
### GitLab ### GitLab
@ -48,7 +54,8 @@ Note that this is a high-level example that you should customize for your needs.
### Run on Codespaces and Visual Studio Code ### Run on Codespaces and Visual Studio Code
This repository provides a DevContainer for [remote development](https://code.visualstudio.com/docs/remote/containers). This repository provides a DevContainer for
[remote development](https://code.visualstudio.com/docs/remote/containers).
## Share Environment variables between environments ## Share Environment variables between environments
@ -122,8 +129,8 @@ make
You can run the test suite against an arbitrary super-linter container image. You can run the test suite against an arbitrary super-linter container image.
Here is an example that runs the test suite against the `v5.4.3` container Here is an example that runs the test suite against the `v5.4.3` container image
image version. version.
```shell ```shell
CONTAINER_IMAGE_ID="ghcr.io/super-linter/super-linter:v5.4.3" \ CONTAINER_IMAGE_ID="ghcr.io/super-linter/super-linter:v5.4.3" \

View file

@ -13,9 +13,9 @@ This section helps you upgrade from super-linter `v6` to `v7`.
### sql-lint, VALIDATE_SQL and SQL_CONFIG_FILE ### sql-lint, VALIDATE_SQL and SQL_CONFIG_FILE
[sql-lint](https://github.com/joereynolds/sql-lint) appears to be unmaintained, [sql-lint](https://github.com/joereynolds/sql-lint) appears to be unmaintained,
and its dependencies are affected by known security vulnerabilities. and its dependencies are affected by known security vulnerabilities. For this
For this reason, Super-linter `v7` doesn't include sql-lint anymore. If you reason, Super-linter `v7` doesn't include sql-lint anymore. If you are using
are using sql-lint to check your SQL files, we recommend that you evaluate sql-lint to check your SQL files, we recommend that you evaluate
[sqlfluff](https://sqlfluff.com/), included in Super-linter since `v4.6.0`. [sqlfluff](https://sqlfluff.com/), included in Super-linter since `v4.6.0`.
You can remove the `VALIDATE_SQL` and `SQL_CONFIG_FILE` because they have no You can remove the `VALIDATE_SQL` and `SQL_CONFIG_FILE` because they have no
@ -62,8 +62,8 @@ This section helps you upgrade from super-linter `v6.7.0` to `v6.8.0`.
- If you set `TYPESCRIPT_DEFAULT_STYLE=prettier`, set - If you set `TYPESCRIPT_DEFAULT_STYLE=prettier`, set
`VALIDATE_TYPESCRIPT_STANDARD=false` `VALIDATE_TYPESCRIPT_STANDARD=false`
Finally, remove both `JAVASCRIPT_DEFAULT_STYLE` and Finally, remove both `JAVASCRIPT_DEFAULT_STYLE` and `TYPESCRIPT_DEFAULT_STYLE`
`TYPESCRIPT_DEFAULT_STYLE` from your Super-linter configuration. from your Super-linter configuration.
## Upgrade from v5 to v6 ## Upgrade from v5 to v6
@ -120,8 +120,8 @@ This section helps you upgrade from super-linter `v5` to `v6`.
entire workspace instead of linting files one by one. You can safely remove entire workspace instead of linting files one by one. You can safely remove
the `VALIDATE_JSCPD_ALL_CODEBASE` variable from your configuration. the `VALIDATE_JSCPD_ALL_CODEBASE` variable from your configuration.
- Jscpd doesn't consider the `FILTER_REGEX_EXCLUDE`, `FILTER_REGEX_INCLUDE`, - Jscpd doesn't consider the `FILTER_REGEX_EXCLUDE`, `FILTER_REGEX_INCLUDE`,
`IGNORE_GENERATED_FILES` variables. For more `IGNORE_GENERATED_FILES` variables. For more information about how to ignore
information about how to ignore files with Jscpd, see files with Jscpd, see
[the Jscpd documentation](https://github.com/kucherenko/jscpd/tree/master/apps/jscpd). [the Jscpd documentation](https://github.com/kucherenko/jscpd/tree/master/apps/jscpd).
### USE_FIND_ALGORITHM and VALIDATE_ALL_CODEBASE used together ### USE_FIND_ALGORITHM and VALIDATE_ALL_CODEBASE used together
@ -137,6 +137,6 @@ This section helps you upgrade from super-linter `v5` to `v6`.
- The `VALIDATE_KOTLIN_ANDROID` variable has been deprecated because ktlint - The `VALIDATE_KOTLIN_ANDROID` variable has been deprecated because ktlint
handles linting Kotlin files for Android using a configuration option, so handles linting Kotlin files for Android using a configuration option, so
super-linter doesn't need to account for this special case anymore. If you super-linter doesn't need to account for this special case anymore. If you set
set `VALIDATE_KOTLIN_ANDROID` in your configuration, change it to `VALIDATE_KOTLIN_ANDROID` in your configuration, change it to
`VALIDATE_KOTLIN` and configure ktlint to lint Android files. `VALIDATE_KOTLIN` and configure ktlint to lint Android files.

11
prettier.config.js Normal file
View file

@ -0,0 +1,11 @@
module.exports = {
// Overrides for specific file types
overrides: [
{
files: ["**/*.md"],
options: {
proseWrap: "always",
},
},
],
};

View file

@ -154,6 +154,7 @@ run_test_case_use_find_and_ignore_gitignored_files() {
ignore_test_cases ignore_test_cases
COMMAND_TO_RUN+=(-e IGNORE_GITIGNORED_FILES="true") COMMAND_TO_RUN+=(-e IGNORE_GITIGNORED_FILES="true")
COMMAND_TO_RUN+=(-e USE_FIND_ALGORITHM="true") COMMAND_TO_RUN+=(-e USE_FIND_ALGORITHM="true")
COMMAND_TO_RUN+=(--env VALIDATE_JAVASCRIPT_STANDARD="false")
} }
run_test_cases_save_super_linter_output() { run_test_cases_save_super_linter_output() {