Skip to content

Commit

Permalink
Fix #79 Add CLI frontend for formatting and validating
Browse files Browse the repository at this point in the history
While many of the features provided by the language server protocol
only make sense in the context of an editor, formatting and
validation are both operations that can be performed on a Dockerfile
even if they haven't been opened in an editor. These two features
have been added to the docker-langserver binary so that a user can
now format and validate Dockerfiles straight from the command line
without the use of any editors.

Signed-off-by: Remy Suen <[email protected]>
  • Loading branch information
rcjsuen committed Oct 25, 2017
1 parent 8245123 commit f9af603
Show file tree
Hide file tree
Showing 7 changed files with 503 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog
All notable changes to this project will be documented in this file.

## [Unreleased]
### Added
- add formatting and validation to the docker-langserver binary ([#79](https://github.com/rcjsuen/dockerfile-language-server-nodejs/issues/79))

## [0.0.10] - 2017-10-23
### Added
- textDocument/codeAction
Expand Down
63 changes: 63 additions & 0 deletions FORMATTER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Formatting Dockerfiles

The formatter included will perform the following operations on a Dockerfile:

- remove leading whitespace if it begins with an instruction
- remove trailing whitespace if and only if the line only contains whitespace characters
- take escaped newlines into account and indent Dockerfile instructions that span multiple lines

## Command Line Interface

The formatter used by the language server can be run standalone from the CLI.
If no file is specified, the CLI will attempt to format the contents of a file named `Dockerfile` in the current working directory if it exists.

### Help
```
> docker-langserver format --help
Usage: docker-langserver format [options] [file]
Options:
-h, --help Output usage information
-s, --spaces <number> Format with the <number> of spaces
-t, --tabs Format with tabs
```

### Example
```Dockerfile
FROM node
HEALTHCHECK --interva=30s CMD ls
RUN "echo" ls \

"echoS"sdfdf \
asdfasdf
copy . .
ADD app.zip
CMD ls
```
#### Formatting with Tabs
```
> docker-langserver format -t
FROM node
HEALTHCHECK --interva=30s CMD ls
RUN "echo" ls \
"echoS"sdfdf \
asdfasdf
copy . .
ADD app.zip
CMD ls
```
#### Formatting with Spaces
```
> docker-langserver format -s 5
FROM node
HEALTHCHECK --interva=30s CMD ls
RUN "echo" ls \
"echoS"sdfdf \
asdfasdf
copy . .
ADD app.zip
CMD ls
```
32 changes: 27 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ Supported features:
- code actions
- code completion
- definition
- diagnostics
- [diagnostics](https://github.com/rcjsuen/dockerfile-language-server-nodejs/blob/master/VALIDATOR.md)
(can be used from the command line)
- document highlight
- document symbols
- formatting
- [formatting](https://github.com/rcjsuen/dockerfile-language-server-nodejs/blob/master/FORMATTER.md)
(can be used from the command line)
- hovers
- rename
- signature help
Expand Down Expand Up @@ -55,9 +57,29 @@ the desired method of communciating with the language server via one
of the three arguments shown below.

```
docker-langserver --node-ipc
docker-langserver --stdio
docker-langserver --socket=<port>
docker-langserver listen --node-ipc
docker-langserver listen --stdio
docker-langserver listen --socket=<port>
```

The installed binary is not only used for launching the language server. It can
also be used to [format](https://github.com/rcjsuen/dockerfile-language-server-nodejs/blob/master/FORMATTER.md)
and [validate](https://github.com/rcjsuen/dockerfile-language-server-nodejs/blob/master/VALIDATOR.md)
Dockerfiles as a standalone command line application.
```
> docker-langserver --help
Usage: docker-langserver <command> [<args>]
Options:
-h, --help Output usage information
-v, --version Output version information
Commands:
listen Start the language server
format Format a Dockerfile
lint Validate a Dockerfile
```

### Settings
Expand Down
133 changes: 133 additions & 0 deletions VALIDATOR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Dockerfile Validation

The validator provided by the langauge server is intended to perform the same kinds of validation that the Docker builder performs when building an image.
Any errors that are generated by the validator should also be generated by the Docker builder (albeit the message strings itself may differ).
If the validator generates an error for a Dockerfile that the Docker builder is able to build, that is considered to be a bug.

However, errors that the Docker builder generates may not necessarily be replicated by the validator due to difficulties in verifying the validity of a given Dockerfile instruction's arguments given the build context and other factors.

The currently supported version of the Docker builder is **Docker CE 17.09 [2017-09-26]**

## Command Line Interface

The validator used by the language server can be run standalone from the CLI.
If no file is specified, the CLI will attempt to validate the contents of a file named `Dockerfile` in the current working directory if it exists.

### Help
```
> docker-langserver lint --help
Usage: docker-langserver lint [options] [file]
Options:
-h, --help Output usage information
-j, --json Output in JSON format
```

### Example
```Dockerfile
FROM node
HEALTHCHECK --interva=30s CMD ls
RUN "echo" ls \

"echoS"sdfdf \
asdfasdf
copy . .
ADD app.zip
CMD ls
```
#### CLI Output
```
> docker-langserver lint
Line: 2
HEALTHCHECK --interva=30s CMD ls
^^^^^^^^^
Error: Unknown flag: interva
Line: 4
Warning: Empty continuation line
Line: 7
copy . .
^^^^
Warning: Instructions should be written in uppercase letters
Line: 8
ADD app.zip
^^^^^^^
Error: ADD requires at least two arguments
```
#### JSON Output
```
> docker-langserver lint -j
[{"range":{"start":{"line":1,"character":12},"end":{"line":1,"character":21}},"message":"Unknown flag: interva","severity":"error"},{"range":{"start":{"line":3,"character":0},"end":{"line":4,"character":0}},"message":"Empty continuation line","severity":"warning"},{"range":{"start":{"line":6,"character":2},"end":{"line":6,"character":6}},"message":"Instructions should be written in uppercase letters","severity":"warning"},{"range":{"start":{"line":7,"character":4},"end":{"line":7,"character":11}},"message":"ADD requires at least two arguments","severity":"error"}]
```

## Supported Validation Checks

### General
#### Instructions
- instructions should be written in uppercase
- instruction has no arguments
- instruction has an insufficient number of arguments
- unknown instruction detected
- duplicate instruction flags detected
- unknown instruction flag detected
- instruction flag has no value defined
#### Directives
- invalid value specified for `escape` parser directive
- directives should be written in lowercase.
#### Others
- empty continuation lines

### CMD
- multiple `CMD` instructions detected

### ENTRYPOINT
- multiple `ENTRYPOINT` instructions detected

### ENV
- syntax missing equals sign '`=`'
- syntax missing single quote '`'`'
- syntax missing double quotes '`"`'
- property has no name

### EXPOSE
- invalid container port specified
- invalid protocol specified

### FROM
- `FROM` instruction not found at the beginning of the Dockerfile
- invalid build stage name specified
- duplicate build stage name detected
- second argument detected but not an `AS`

### HEALTHCHECK
- `CMD` form has no arguments
- `NONE` form has arguments defined
- type that is not `CMD` or `NONE` detected
- `--retries` flag has invalid syntax
- `--retries` value is not at least one
- duration of `--interval`, `--start-period`, or `--timeout` is invalid
- duration of `--interval`, `--start-period`, or `--timeout` is less than one millisecond
- duration of `--interval`, `--start-period`, or `--timeout` has an unknown unit of time specified
- multiple `HEALTHCHECK` instructions detected

### LABEL
- syntax missing equals sign '`=`'
- syntax missing single quote '`'`'
- syntax missing double quotes '`"`'
- property has no name

### MAINTAINER
- use of deprecated instruction detected

### ONBUILD
- can't chain `ONBUILD` instruction with `ONBUILD ONBUILD`
- invalid `ONBUILD` trigger instruction

### SHELL
- `SHELL` not written in JSON form

### STOPSIGNAL
- invalid stop signal
Loading

0 comments on commit f9af603

Please sign in to comment.