diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a6ba019 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,28 @@ +# Dockette / Adminer + +Adminer database UI served by the PHP built-in web server, one image per database driver set. + +## Stack + +- Docker image built with `docker buildx`, base `alpine:3.23` or `dockette/debian:bookworm-slim` (MS SQL, Oracle) +- Adminer 6.1.0 on PHP 8 +- Published to Docker Hub as `dockette/adminer` for linux/amd64 and linux/arm64 by GitHub Actions + +## Development + +```bash +make build # build all variant images +make test # smoke test all variant images +make run # run one image on port 8000 (DOCKER_RUN_TAG=full) +make build-full # build one variant; also test-full, run-full +``` + +Run `make` to list every target. + +## Principles + +- KISS: one image does one job; no extra services or tools. +- DRY: shared steps live in the base image, not copied into every Dockerfile. +- YAGNI: add a package only when the image needs it. +- Pin versions, keep layers small, clean package caches in the same `RUN`. +- Every change is built and smoke tested with `make build test` before a commit. diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..31e11c9 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,104 @@ +# Adminer Design + +The Adminer images serve the Adminer database UI on port `80`. Developers open it in a browser to inspect and +edit databases in local and staging stacks. The UI is upstream [Adminer](https://www.adminer.org); this file +describes only what the image adds on top of it. + +## Principles + +- **Upstream UI, unmodified PHP.** The `Dockerfile` downloads the release file `adminer-{version}.php` (or + `editor-{version}.php`) to `/srv/index.php`; nothing patches it. +- **Everything is opt-in by environment.** Themes and plugins are off until a variable turns them on, so a + container started with no variables looks like upstream Adminer. The one exception is `mssql`, where + `mssql-encrypt` is on by default. +- **Credentials never reach the browser.** The server list and autologin plugins parse DSNs from the environment + on the server; the page only receives server names. +- **One entrypoint per variant.** Each `adminer-{tag}/entrypoint.sh` enables only the features its variant + supports. + +## Inventory + +- Login and database screens: upstream `adminer-{version}.php`, served as `/srv/index.php` (`ADMINER_VERSION`). +- Editor screens (`editor` tag): upstream `editor-{version}.php`, the data-only Adminer Editor. +- Server dropdown with Auto Sign-In: `.plugins/adminer-server-list.php`, enabled by `ADMINER_PLUGIN_SERVER_LIST=1`. +- Autologin, which skips the login form: `.plugins/adminer-autologin.php`, enabled by `ADMINER_PLUGIN_AUTOLOGIN=1`. +- MSSQL encryption options: `.plugins/adminer-mssql-encrypt.php`, `mssql` tag only, on unless + `ADMINER_PLUGIN_MSSQL_ENCRYPT=0`. +- Upstream driver plugins: the release `plugins/drivers/` folder, copied into `/srv/adminer-plugins/` at start, + `full` tag only. +- Themes: the release `designs/` folder, copied to `/srv/designs/` at build time (not in `dg`). +- The `dg` tag serves the separate `adminer-custom` project with its own look. None of the plugins or themes + above apply to it. +- The other variants differ in drivers, not in UI: `full`, `mysql`, `postgres`, `mongo`, `mssql`, `oracle-*`. + +## Layout + +- Upstream. The server list plugin changes the login form: the Server text field becomes a `` helper and a plain + ``, both keyboard reachable. Its button is hidden with `display: none` for servers without + credentials. + +## Dark Mode + +- Only through a theme that ships `adminer-dark.css`; how it is switched on is upstream behaviour. + +## Responsive + +- Desktop first, as upstream. Our plugins add no layout of their own and are not tested on narrow screens. + +## Screenshots + +- `.docs/assets/adminer.png` (default look), `.docs/assets/adminer-dg.png` (`dg` tag) and + `.docs/assets/themes/{name}.png`, one per theme, shown 200 px wide in the README table. +- To retake one, run `make build-full`, then `docker run --rm -p 8000:80 -e ADMINER_THEME={name} + dockette/adminer:full`, open `http://localhost:8000` and capture the login screen. +- After an Adminer version bump, retake the default screenshot and check the theme list against `designs/`. + +## Changing the UI + +- Variable names (`ADMINER_THEME`, `ADMINER_PLUGIN_*`, `ADMINER_SERVERS_*`, `ADMINER_AUTOLOGIN_SERVER`) are + public; rename them only with a deprecation note in the README. +- A new upstream major can change the plugin API (`Adminer\Plugin`, `loginFormField`, `credentials`); start + every variant and log in once. +- The server list script finds the Login button by `value="Login"`; an upstream label change hides the Auto + Sign-In button. +- Adding a theme to the README table needs its screenshot in `.docs/assets/themes/`. + +## Checklist + +- [ ] The default container (no variables) looks like upstream Adminer +- [ ] Each changed plugin tested with and without credentials, in `full` and one Debian variant +- [ ] `ADMINER_THEME` with a valid and an invalid name +- [ ] No DSN or password appears in the page source +- [ ] `mssql` still connects with `ADMINER_PLUGIN_MSSQL_ENCRYPT` unset and set to `0` +- [ ] Screenshots updated if the UI changed diff --git a/Makefile b/Makefile index 493ea19..10197ff 100644 --- a/Makefile +++ b/Makefile @@ -3,62 +3,143 @@ DOCKER_PLATFORMS?=linux/amd64 DOCKER_RUN_PORT?=8000 DOCKER_RUN_TAG?=full -build: build-all +.DEFAULT_GOAL := help -test: test-all +##@ Help -run: +.PHONY: help +help: ## Show this help + @awk 'BEGIN {FS = ":.*##"; printf "Usage: make \033[36m\033[0m\n"} /^[a-zA-Z0-9_.-]+:.*##/ { sub(/^ +/, "", $$2); printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) }' $(firstword $(MAKEFILE_LIST)) + +##@ Docker + +.PHONY: build +build: build-all ## Build all variant images + +.PHONY: test +test: test-all ## Test all variant images + +.PHONY: run +run: ## Run one image on port 8000 (DOCKER_RUN_TAG=full) docker run --rm -it -p ${DOCKER_RUN_PORT}:80 ${DOCKER_IMAGE}:${DOCKER_RUN_TAG} -build-all: build-full build-dg build-editor build-mongo build-mssql build-mysql build-postgres build-oracle-11 build-oracle-12 build-oracle-19 +.PHONY: build-all +build-all: build-full build-dg build-editor build-mongo build-mssql build-mysql build-postgres build-oracle-11 build-oracle-12 build-oracle-19 ## Build all variant images + +.PHONY: test-all +test-all: test-full test-dg test-editor test-mongo test-mssql test-mysql test-postgres test-oracle-11 test-oracle-12 test-oracle-19 ## Run php --version in all variant images _docker-build-%: TAG=$* _docker-build-%: docker buildx build --platform ${DOCKER_PLATFORMS} -t ${DOCKER_IMAGE}:${TAG} -f ./adminer-${TAG}/Dockerfile . -build-full: _docker-build-full -build-dg: _docker-build-dg -build-editor: _docker-build-editor -build-mongo: _docker-build-mongo -build-mssql: _docker-build-mssql -build-mysql: _docker-build-mysql -build-postgres: _docker-build-postgres -build-oracle-11: _docker-build-oracle-11 -build-oracle-12: _docker-build-oracle-12 -build-oracle-19: _docker-build-oracle-19 - _docker-test-%: TAG=$* _docker-test-%: docker run --rm --platform ${DOCKER_PLATFORMS} ${DOCKER_IMAGE}:${TAG} php --version -test-full: _docker-test-full -test-dg: _docker-test-dg -test-editor: _docker-test-editor -test-mongo: _docker-test-mongo -test-mssql: _docker-test-mssql -test-mysql: _docker-test-mysql -test-postgres: _docker-test-postgres -test-oracle-11: _docker-test-oracle-11 -test-oracle-12: _docker-test-oracle-12 -test-oracle-19: _docker-test-oracle-19 - -test-all: test-full test-dg test-editor test-mongo test-mssql test-mysql test-postgres test-oracle-11 test-oracle-12 test-oracle-19 - _docker-run-%: TAG=$* _docker-run-%: docker run --rm -it -p ${DOCKER_RUN_PORT}:80 ${DOCKER_IMAGE}:${TAG} -run-full: _docker-run-full -run-dg: _docker-run-dg -run-editor: _docker-run-editor -run-mongo: _docker-run-mongo -run-mssql: _docker-run-mssql -run-mysql: _docker-run-mysql -run-postgres: _docker-run-postgres -run-oracle-11: _docker-run-oracle-11 -run-oracle-12: _docker-run-oracle-12 -run-oracle-19: _docker-run-oracle-19 - -update-versions: +##@ Build Variants + +.PHONY: build-full +build-full: _docker-build-full ## Build the full (MySQL, PostgreSQL, SQLite, MongoDB) image + +.PHONY: build-dg +build-dg: _docker-build-dg ## Build the adminer-custom image + +.PHONY: build-editor +build-editor: _docker-build-editor ## Build the Adminer Editor image + +.PHONY: build-mongo +build-mongo: _docker-build-mongo ## Build the MongoDB image + +.PHONY: build-mssql +build-mssql: _docker-build-mssql ## Build the MS SQL Server image + +.PHONY: build-mysql +build-mysql: _docker-build-mysql ## Build the MySQL image + +.PHONY: build-postgres +build-postgres: _docker-build-postgres ## Build the PostgreSQL image + +.PHONY: build-oracle-11 +build-oracle-11: _docker-build-oracle-11 ## Build the Oracle 11 image + +.PHONY: build-oracle-12 +build-oracle-12: _docker-build-oracle-12 ## Build the Oracle 12 image + +.PHONY: build-oracle-19 +build-oracle-19: _docker-build-oracle-19 ## Build the Oracle 19 image + +##@ Test Variants + +.PHONY: test-full +test-full: _docker-test-full ## Test the full (MySQL, PostgreSQL, SQLite, MongoDB) image + +.PHONY: test-dg +test-dg: _docker-test-dg ## Test the adminer-custom image + +.PHONY: test-editor +test-editor: _docker-test-editor ## Test the Adminer Editor image + +.PHONY: test-mongo +test-mongo: _docker-test-mongo ## Test the MongoDB image + +.PHONY: test-mssql +test-mssql: _docker-test-mssql ## Test the MS SQL Server image + +.PHONY: test-mysql +test-mysql: _docker-test-mysql ## Test the MySQL image + +.PHONY: test-postgres +test-postgres: _docker-test-postgres ## Test the PostgreSQL image + +.PHONY: test-oracle-11 +test-oracle-11: _docker-test-oracle-11 ## Test the Oracle 11 image + +.PHONY: test-oracle-12 +test-oracle-12: _docker-test-oracle-12 ## Test the Oracle 12 image + +.PHONY: test-oracle-19 +test-oracle-19: _docker-test-oracle-19 ## Test the Oracle 19 image + +##@ Run Variants + +.PHONY: run-full +run-full: _docker-run-full ## Run the full (MySQL, PostgreSQL, SQLite, MongoDB) image on port 8000 + +.PHONY: run-dg +run-dg: _docker-run-dg ## Run the adminer-custom image on port 8000 + +.PHONY: run-editor +run-editor: _docker-run-editor ## Run the Adminer Editor image on port 8000 + +.PHONY: run-mongo +run-mongo: _docker-run-mongo ## Run the MongoDB image on port 8000 + +.PHONY: run-mssql +run-mssql: _docker-run-mssql ## Run the MS SQL Server image on port 8000 + +.PHONY: run-mysql +run-mysql: _docker-run-mysql ## Run the MySQL image on port 8000 + +.PHONY: run-postgres +run-postgres: _docker-run-postgres ## Run the PostgreSQL image on port 8000 + +.PHONY: run-oracle-11 +run-oracle-11: _docker-run-oracle-11 ## Run the Oracle 11 image on port 8000 + +.PHONY: run-oracle-12 +run-oracle-12: _docker-run-oracle-12 ## Run the Oracle 12 image on port 8000 + +.PHONY: run-oracle-19 +run-oracle-19: _docker-run-oracle-19 ## Run the Oracle 19 image on port 8000 + +##@ Maintenance + +.PHONY: update-versions +update-versions: ## Set ENV ADMINER_VERSION in every Dockerfile (ADMINER_VERSION=x, BSD sed) find . -type f -name Dockerfile -exec sed -i '' 's/ENV ADMINER_VERSION=.*/ENV ADMINER_VERSION=${ADMINER_VERSION}/g' {} + find . -type f -name Dockerfile -exec sed -i '' 's/ENV ADMINER_EDITOR_VERSION=.*/ENV ADMINER_EDITOR_VERSION=${ADMINER_VERSION}/g' {} + diff --git a/README.md b/README.md index d4c799f..99289fc 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,5 @@

Dockette / Adminer

-

- 🎁 Tiniest boxed dockerized Adminer (MySQL, PostgreSQL, SQLite, Mongo, Oracle, MSSQL) Dockerfiles. Database management in a single PHP file. -

- -

-🕹 f3l1x.io | 💻 f3l1x | 🐦 @xf3l1x -

-

GitHub Actions Docker Hub pulls @@ -15,158 +7,87 @@ Support/Discussions

-![Adminer](.docs/assets/adminer.png) - ------- - -## Prologue - -There are few variants of this adminer image based: +

+ Adminer 6.1.0, the single-file database manager, served by the PHP 8.4 built-in web server. Each tag carries the drivers for one database (mysql, postgres, mongo, mssql, oracle-19) or for several (full), on Alpine Linux or Debian Bookworm. For developers who need a database UI next to a local or staging stack. +

-- full (mysql, pgsql, sqlite, mongo) -- mysql (only) -- pgsql (only) -- mongo (only) -- mssql (only) -- oracle-11 / oracle-12 / oracle-19 (only) -- dg (custom) +

+🕹 f3l1x.io | 💻 f3l1x | 🐦 @xf3l1x +

-**Features** +

+ Adminer login screen +

-- Alpine Linux (full, editor, dg, mongo, mysql, postgres) -- Debian Bookworm (mssql, oracle-11, oracle-12, oracle-19) -- PHP 8 (concurrency via PHP cli workers) +----- ## Usage -```sh -docker run \ - --rm - -p 8000:80 - dockette/adminer:dg -``` - -By default container is running with these settings, you can override it using environment variables. - -- `MEMORY=256M` (memory_limit) -- `UPLOAD=2048M` (upload_max_filesize, post_max_size) -- `PORT=80` (PHP server listening port) -- `WORKERS=4` (concurrency) - -```sh -docker run \ - --rm - -p 8000:8080 - -e MEMORY=512M - -e UPLOAD=4096M - -e PORT=8080 - dockette/adminer:dg -``` - -## Versions - -| Image | Technologies | Size | Docker Hub | -|------------------------------|---------------------------------------|------|---------------------------------------------------------| -| dockette/adminer | MySQL / PostgreSQL / MongoDB / Sqlite | 12mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:full | MySQL / PostgreSQL / MongoDB / Sqlite | 12mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:mysql | MySQL | 9mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:pgsql | PostgreSQL | 8mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:mongo | MongoDB | 9mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:mssql | MS SQL Server | - | [link](https://hub.docker.com/r/dockette/adminer/tags/) | -| dockette/adminer:dg | MySQL / PostgreSQL / MongoDB / Sqlite | 16mb | [link](https://hub.docker.com/r/dockette/adminer/tags/) | - -### `dockette/adminer:mssql` - -Debian-based image with Microsoft ODBC Driver 18 and PHP `sqlsrv` / `pdo_sqlsrv` extensions. +Run the image and open `http://localhost:8000`: ```sh -docker run \ - --rm \ - -p 8080:80 \ - dockette/adminer:mssql +docker run -p 8000:80 dockette/adminer ``` -By default, `TrustServerCertificate` is set to `yes` so the image works out of the box with self-signed certificates (common in development). You can control encryption behavior via environment variables: +The image adds the drivers for its tag, a set of upstream plugins and themes, and an entrypoint that sets them up +from environment variables (see [Environment](#environment)). Pick a tag for your database from the table below; +see the [Adminer documentation](https://www.adminer.org/en/plugins/) for what the plugins do. -| Variable | Description | Default | -|---|---|---| -| `ADMINER_PLUGIN_MSSQL_ENCRYPT` | Set to `0` to disable the encryption plugin | enabled | -| `ADMINER_MSSQL_ENCRYPT` | `yes`, `no`, or `strict` | not set | -| `ADMINER_MSSQL_TRUST_CERT` | `yes` or `no` | `yes` | +> [!CAUTION] +> Adminer gives full access to every database it can reach. Don't expose the port to the internet, and never +> publish a container with the autologin plugin enabled. -### `dockette/adminer:dg` - -> Customization for the best database management tool written in PHP, Adminer - -You should take a look to the official github profile (https://github.com/dg/adminer-custom). +## Versions -![Adminer DG](.docs/assets/adminer-dg.png) +| Tag | Description | +|-----|-------------| +| `dockette/adminer:full` | MySQL, PostgreSQL, SQLite and MongoDB drivers, plus the upstream driver plugins; Alpine 3.23 | +| `dockette/adminer:latest` | Same as `full` | +| `dockette/adminer:editor` | [Adminer Editor](https://www.adminer.org/en/editor/) (data only) with MySQL, PostgreSQL and MongoDB; Alpine 3.23 | +| `dockette/adminer:mysql` | MySQL and MariaDB; Alpine 3.22 | +| `dockette/adminer:postgres` | PostgreSQL; Alpine 3.23 | +| `dockette/adminer:mongo` | MongoDB; Alpine 3.23 | +| `dockette/adminer:mssql` | MS SQL Server with Microsoft ODBC Driver 18 and `sqlsrv`, `pdo_sqlsrv`; Debian Bookworm, `linux/amd64` only | +| `dockette/adminer:oracle-19` | Oracle with Instant Client 19.30 and `oci8`; Debian Bookworm, `linux/amd64` only | +| `dockette/adminer:oracle-12` | Oracle with Instant Client 12.1 and `oci8`; Debian Bookworm, `linux/amd64` only | +| `dockette/adminer:oracle-11` | Oracle with Instant Client 11.2 and `oci8`; Debian Bookworm, `linux/amd64` only | +| `dockette/adminer:dg` | The `adminer-custom` 3.4.1 build with MySQL, PostgreSQL and MongoDB; Alpine 3.23. No plugins or themes | + +The Alpine tags are built for `linux/amd64` and `linux/arm64`; Microsoft and Oracle ship their drivers for +`amd64` only. Every tag is rebuilt every Monday. + +## Environment + +| Variable | Default | Description | +|----------|---------|-------------| +| `MEMORY` | `256M` | PHP `memory_limit` | +| `UPLOAD` | `2048M` | PHP `upload_max_filesize` and `post_max_size` | +| `PORT` | `80` | Port of the PHP built-in web server inside the container | +| `PHP_CLI_SERVER_WORKERS` | `8` | Number of PHP server workers. `WORKERS` only sets it at build time | +| `ADMINER_THEME` | (none) | Theme name from the table below | +| `ADMINER_PLUGIN_AUTOLOGIN` | (off) | `1` enables the autologin plugin | +| `ADMINER_AUTOLOGIN_SERVER` | (none) | DSN for autologin | +| `ADMINER_PLUGIN_SERVER_LIST` | (off) | `1` enables the server list plugin | +| `ADMINER_SERVERS_{Name}` | (none) | DSN of one server in the list; `{Name}` is its label | +| `ADMINER_PLUGIN_MSSQL_ENCRYPT` | (on) | `mssql` only: `0` disables the encryption plugin | +| `ADMINER_MSSQL_ENCRYPT` | (not set) | `mssql` only: `yes`, `no` or `strict` | +| `ADMINER_MSSQL_TRUST_CERT` | `yes` | `mssql` only: `TrustServerCertificate`, `yes` or `no` | +| `ADMINER_BANNER` | (on) | `0`, `false`, `no` or `off` hides the start banner | +| `ADMINER_DEBUG` | (off) | `1` traces the entrypoint with `set -x` | + +The `ADMINER_*` variables for themes and plugins work in every tag except `dg`. ## Plugins -Adminer plugins can be enabled via environment variables. All plugins are disabled by default. Available for all image variants except `dg`. - -### Autologin - -Skips the login form and connects directly to a database server. - -| Variable | Description | -|---|---| -| `ADMINER_PLUGIN_AUTOLOGIN=1` | Enable the autologin plugin | -| `ADMINER_AUTOLOGIN_SERVER` | DSN connection string | - -DSN format: `driver://username:password@host:port/database` - -```sh -docker run \ - --rm \ - -p 8080:80 \ - -e ADMINER_PLUGIN_AUTOLOGIN=1 \ - -e ADMINER_AUTOLOGIN_SERVER=server://root:secret@mysql:3306/mydb \ - dockette/adminer:full -``` - -Supported drivers: `server` (MySQL/MariaDB), `pgsql`, `sqlite`, `mongo`, `oracle`, `elastic`. - -### Server List - -Displays a dropdown of pre-configured database servers with an **Auto Sign-In** button. Credentials are handled server-side and never exposed to the browser. - -| Variable | Description | -|---|---| -| `ADMINER_PLUGIN_SERVER_LIST=1` | Enable the server list plugin | -| `ADMINER_SERVERS_` | DSN for each server (suffix becomes the display name) | - -```sh -docker run \ - --rm \ - -p 8080:80 \ - -e ADMINER_PLUGIN_SERVER_LIST=1 \ - -e ADMINER_SERVERS_MySQL=server://root:secret@mysql:3306/mydb \ - -e ADMINER_SERVERS_PostgreSQL=pgsql://postgres:pwd@pg:5432/app \ - -e ADMINER_SERVERS_DevDB=server://dev@devhost:3306 \ - dockette/adminer:full -``` - -Servers without credentials in the DSN (e.g. `server://devhost:3306`) appear in the dropdown but require manual login. The **Auto Sign-In** button only appears for servers with stored credentials. - -> **Note:** Autologin takes precedence over Server List. If both plugins are enabled, only Autologin is activated. +Plugins are off by default and are switched on with the `ADMINER_PLUGIN_*` variables. A DSN has the form +`driver://username:password@host:port/database`, where `driver` is `server` (MySQL and MariaDB), `pgsql`, +`sqlite`, `oracle` or `mongo`. The server list keeps the credentials on the server; when autologin is also on, +only autologin is active. The `mssql` tag has no autologin and no server list. ## Themes -You can apply a theme by setting the `ADMINER_THEME` environment variable: - -```sh -docker run \ - --rm - -p 8000:80 - -e ADMINER_THEME=dracula - dockette/adminer:full -``` - -If the specified theme is not found, the container will list all available themes. - -### Available Themes +`ADMINER_THEME` selects one of the themes from the Adminer release, for example `ADMINER_THEME=dracula`. When the +theme is not found, the container prints the available names and starts with the default look. @@ -213,14 +134,23 @@ If the specified theme is not found, the container will list all available theme
-## Upgrade +## Adminer Custom + +The `dg` tag serves the [`adminer-custom`](https://github.com/dg/adminer-custom) project, a customised Adminer with its own plugins and look, instead of +the upstream release. -**Upgrade Adminer and Adminer Editor versions to X.Y.Z** +adminer-custom login screen -```bash -ADMINER_VERSION=4.8.1 make update-versions +## Development + +```sh +make build # build every tag +make test # smoke test every tag +make run # run the full tag on port 8000 ``` +Run `make` to list every target. + ## Maintenance -See [how to contribute](https://github.com/dockette/.github/blob/master/CONTRIBUTING.md) to this package. Consider to [support](https://github.com/sponsors/f3l1x) **f3l1x**. Thank you for using this package. +See [how to contribute](https://github.com/dockette/.github/blob/master/CONTRIBUTING.md) to this package. Consider [supporting](https://github.com/sponsors/f3l1x) **f3l1x**. Thank you for using this package. diff --git a/fxnorm.yml b/fxnorm.yml new file mode 100644 index 0000000..5b45951 --- /dev/null +++ b/fxnorm.yml @@ -0,0 +1,12 @@ +# fxnorm configuration, written by `fxnorm init`. +# `fxnorm config` prints what runs and why; `fxnorm rules` lists every rule with its group. + +# A Dockette Docker image repository (a Dockerfile in the root or one folder below) +presets: + - dockette-image + +# groups: # add a group, or drop one with a leading minus +# - -ci + +# rules: # false, true, error, warning, or options +# common/agents-md-length: {min: 50, max: 120}