From 211cef5a6b3397ade15cfbc0e73fffa16519a9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Moreira?= Date: Tue, 29 Oct 2024 17:43:33 +0100 Subject: [PATCH] New lint setup and lint existing files (#34) * New lint setup * Lint existing files Inline HTML error is still in: docs/general-guidelines/maintenance.md and docs/stack/java.md * Expand allowed HTML tags * Lint placeholder files for JS and Python * table in maintenance.md * Set CI lint fail flag to false * Update second table in maintenance.md * Update github action checkout to v4 * Tabs to spaces in maintenance.md --------- Co-authored-by: Twan Goosen --- .github/workflows/lint.yml | 4 +- .github/workflows/publish.yml | 2 +- .github/workflows/test-build.yml | 2 +- .mdl.rb | 6 + .mdlrc | 4 +- LICENSE.md | 70 ++-- README.md | 4 +- docs/.mdlrc | 2 - docs/general-guidelines/api.md | 1 + docs/general-guidelines/code-licencing.md | 50 +-- docs/general-guidelines/code-lifecycle.md | 335 +++++++++--------- docs/general-guidelines/configuration.md | 1 + docs/general-guidelines/documentation.md | 1 + docs/general-guidelines/logging.md | 86 ++--- docs/general-guidelines/maintenance.md | 273 +++++++++++--- .../privacy-data-protection.md | 1 + docs/general-guidelines/security.md | 80 ++--- docs/general-guidelines/testing.md | 1 + .../authentication-mechanisms.md | 34 +- .../configuration.md | 122 +++---- .../localisation.md | 92 +++-- docs/stack/bash.md | 18 +- docs/stack/docker.md | 148 ++++---- docs/stack/javascript.md | 1 + docs/stack/python.md | 1 + lint.sh | 7 +- 26 files changed, 765 insertions(+), 581 deletions(-) create mode 100644 .mdl.rb delete mode 100644 docs/.mdlrc diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ac2fbd9..60f3945 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,9 +7,9 @@ jobs: lint: name: Lint markdown runs-on: ubuntu-latest - continue-on-error: true + continue-on-error: false steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Lint run: bash lint.sh diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a9674ba..aeb7050 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout main - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Deploy docs uses: mhausenblas/mkdocs-deploy-gh-pages@1.26 diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index ec57027..5d43d85 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build docs uses: mhausenblas/mkdocs-deploy-gh-pages@1.26 diff --git a/.mdl.rb b/.mdl.rb new file mode 100644 index 0000000..c88f929 --- /dev/null +++ b/.mdl.rb @@ -0,0 +1,6 @@ +all +rule "MD026", :punctuation => '.,;:!' + +# Allow in-line HTML +#exclude_rule 'MD033' +rule 'MD033', :allowed_elements => 'link, if, todo, table, thead, tr, th, td, tbody, p, a, strong, br' \ No newline at end of file diff --git a/.mdlrc b/.mdlrc index 36da32e..15ee04a 100644 --- a/.mdlrc +++ b/.mdlrc @@ -1 +1,3 @@ -rules "~MD013", "~MD036" +git_recurse true +rules "~MD002", "~MD013", "~MD036" +style ".mdl.rb" \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md index 311e8a4..ecc262e 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -14,7 +14,7 @@ Creative Commons public licenses provide a standard set of terms and conditions By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. -### Section 1 – Definitions. +### Section 1 – Definitions a. __Adapted Material__ means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. @@ -38,69 +38,69 @@ j. __Sui Generis Database Rights__ means rights other than copyright resulting f k. __You__ means the individual or entity exercising the Licensed Rights under this Public License. __Your__ has a corresponding meaning. -### Section 2 – Scope. +### Section 2 – Scope a. ___License grant.___ - 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: +1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: - A. reproduce and Share the Licensed Material, in whole or in part; and + A. reproduce and Share the Licensed Material, in whole or in part; and - B. produce, reproduce, and Share Adapted Material. + B. produce, reproduce, and Share Adapted Material. - 2. __Exceptions and Limitations.__ For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. +1. __Exceptions and Limitations.__ For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. - 3. __Term.__ The term of this Public License is specified in Section 6(a). +1. __Term.__ The term of this Public License is specified in Section 6(a). - 4. __Media and formats; technical modifications allowed.__ The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. +1. __Media and formats; technical modifications allowed.__ The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. - 5. __Downstream recipients.__ +1. __Downstream recipients.__ - A. __Offer from the Licensor – Licensed Material.__ Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. + A. __Offer from the Licensor – Licensed Material.__ Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. - B. __No downstream restrictions.__ You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. + B. __No downstream restrictions.__ You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. - 6. __No endorsement.__ Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). +1. __No endorsement.__ Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. ___Other rights.___ - 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. +1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. - 2. Patent and trademark rights are not licensed under this Public License. +1. Patent and trademark rights are not licensed under this Public License. - 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. +1. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. -### Section 3 – License Conditions. +### Section 3 – License Conditions Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. ___Attribution.___ - 1. If You Share the Licensed Material (including in modified form), You must: +1. If You Share the Licensed Material (including in modified form), You must: - A. retain the following if it is supplied by the Licensor with the Licensed Material: + A. retain the following if it is supplied by the Licensor with the Licensed Material: - i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); + i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); - ii. a copyright notice; + ii. a copyright notice; - iii. a notice that refers to this Public License; + iii. a notice that refers to this Public License; - iv. a notice that refers to the disclaimer of warranties; + iv. a notice that refers to the disclaimer of warranties; - v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; - B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and + B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and - C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. + C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. - 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. +1. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. - 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. +1. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. - 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. +1. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. -### Section 4 – Sui Generis Database Rights. +### Section 4 – Sui Generis Database Rights Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: @@ -112,7 +112,7 @@ c. You must comply with the conditions in Section 3(a) if You Share all or a sub For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. -### Section 5 – Disclaimer of Warranties and Limitation of Liability. +### Section 5 – Disclaimer of Warranties and Limitation of Liability a. __Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.__ @@ -120,15 +120,15 @@ b. __To the extent possible, in no event will the Licensor be liable to You on a c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. -### Section 6 – Term and Termination. +### Section 6 – Term and Termination a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: - 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or +1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or - 2. upon express reinstatement by the Licensor. +1. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. @@ -136,13 +136,13 @@ c. For the avoidance of doubt, the Licensor may also offer the Licensed Material d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. -### Section 7 – Other Terms and Conditions. +### Section 7 – Other Terms and Conditions a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. -### Section 8 – Interpretation. +### Section 8 – Interpretation a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. diff --git a/README.md b/README.md index 40f44ed..0712f07 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -**Read the docs at [clarin-eric.github.io/handbook-development](https://clarin-eric.github.io/handbook-development/)** - # Sources for the CLARIN ERIC Software Development Guidelines +**Read the docs at [clarin-eric.github.io/handbook-development](https://clarin-eric.github.io/handbook-development/)** + [![Publication to GitHub Pages](https://github.com/clarin-eric/handbook-development/actions/workflows/publish.yml/badge.svg)](https://github.com/clarin-eric/handbook-development/actions/workflows/publish.yml) This repository provides the content and configurations for the CLARIN ERIC Software diff --git a/docs/.mdlrc b/docs/.mdlrc deleted file mode 100644 index 7616f37..0000000 --- a/docs/.mdlrc +++ /dev/null @@ -1,2 +0,0 @@ -git_recurse true -rules "~MD002", "~MD013", "~MD036" diff --git a/docs/general-guidelines/api.md b/docs/general-guidelines/api.md index e69de29..5932792 100644 --- a/docs/general-guidelines/api.md +++ b/docs/general-guidelines/api.md @@ -0,0 +1 @@ +# API diff --git a/docs/general-guidelines/code-licencing.md b/docs/general-guidelines/code-licencing.md index 9972414..d0a5764 100644 --- a/docs/general-guidelines/code-licencing.md +++ b/docs/general-guidelines/code-licencing.md @@ -1,24 +1,24 @@ # Code licence -- Each code (including docker image/compose) or documentation project MUST be explicitly licenced - - Git repositories should have a LICENCE file if a single licence applies to the entire repo - - Docker: see below -- Default licence (see also ​​[https://www.clarin.eu/programmers](https://www.clarin.eu/programmers)): - - For code: GPLv3 \[Policy\] - - Exception: if not compatible with libraries or other context - - Includes bundled documentation (readme, change log etc) - - For documentation projects: CC0 - - e.g. [https://github.com/clarin-eric/cereal](https://github.com/clarin-eric/cereal) - - Put licence statement in footer of document itself - - Note: in some cases (e.g. GPL??) licence itself must also be bundled -- Tooling - - [https://www.fossology.org/](https://www.fossology.org/) - - Licence compliance - - e.g. maven licence plugin - - GitHub community standards check - - Licence compatibility - - check for conflicting licences - - [https://dwheeler.com/essays/floss-license-slide.html](https://dwheeler.com/essays/floss-license-slide.html) +- Each code (including docker image/compose) or documentation project MUST be explicitly licenced + - Git repositories should have a LICENCE file if a single licence applies to the entire repo + - Docker: see below +- Default licence (see also ​​[https://www.clarin.eu/programmers](https://www.clarin.eu/programmers)): + - For code: GPLv3 \[Policy\] + - Exception: if not compatible with libraries or other context + - Includes bundled documentation (readme, change log etc) + - For documentation projects: CC0 + - e.g. [https://github.com/clarin-eric/cereal](https://github.com/clarin-eric/cereal) + - Put licence statement in footer of document itself + - Note: in some cases (e.g. GPL??) licence itself must also be bundled +- Tooling + - [https://www.fossology.org/](https://www.fossology.org/) + - Licence compliance + - e.g. maven licence plugin + - GitHub community standards check + - Licence compatibility + - check for conflicting licences + - [https://dwheeler.com/essays/floss-license-slide.html](https://dwheeler.com/essays/floss-license-slide.html) ## Docker image repositories @@ -28,20 +28,20 @@ For docker images, we generally publish code (the Dockerfile itself, scripts, co For images that are deployed to a public container registry (i.e. submitted to the GitLab container registry typically via a CI job which is the case for virtually all of our central infrastructure images): -- Create a file README.legal.txt based on the following template: +- Create a file README.legal.txt based on the following template: View the \[licence information\](LICENSE.md) for the source code used to build this image. - + View the \[licence information\]() for the software included in this image. - + An image built from the sources in this repository is distributed by CLARIN. As with all Docker images, this likely also contains other software which may be under other licences (such as Bash, etc from the base distribution, along with any direct or indirect dependencies of the primary software being contained). As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licences for all software contained within. -- Add a reference to README.legal.txt to the README file of the repository, e.g. in a section titled ‘Licence’. -- Add the README.legal.txt file (???) to the root of the image’s file system (i.e. COPY that file into the image via the Dockerfile).  Add a symbolic link from the WORKDIR. -- Also copy the LICENSE.md file to the root of the image’s file system +- Add a reference to README.legal.txt to the README file of the repository, e.g. in a section titled ‘Licence’. +- Add the README.legal.txt file (???) to the root of the image’s file system (i.e. COPY that file into the image via the Dockerfile).  Add a symbolic link from the WORKDIR. +- Also copy the LICENSE.md file to the root of the image’s file system \----------------------------------------- For the Docker section ----------------------------->8--------- diff --git a/docs/general-guidelines/code-lifecycle.md b/docs/general-guidelines/code-lifecycle.md index 3531878..99cc456 100644 --- a/docs/general-guidelines/code-lifecycle.md +++ b/docs/general-guidelines/code-lifecycle.md @@ -8,15 +8,15 @@ where: - `major`, `minor` and `patch` `SHOULD` be integers, and -- the optional `qualifier`, if included, `SHOULD` be either `test`, `alpha`, -`beta` or `RC`, followed by an integer, OR a string such as `dev`, `SNAPSHOT` -[in case of work in progress]. +- the optional `qualifier`, if included, `SHOULD` be either `test`, `alpha`, + `beta` or `RC`, followed by an integer, OR a string such as `dev`, `SNAPSHOT` + [in case of work in progress]. Examples: - Examples of valid version numbers *without qualifiers*: `1.0.0`, `4.11.2` - Examples of valid version numbers *with qualifiers*: `3.0.1-alpha1`, `8.6.0-RC2`, -`2.5.0-SNAPSHOT` + `2.5.0-SNAPSHOT` - Examples of *invalid version numbers*: `1.0`, `2-alpha1`, `3.1.0-beta` 👉 Commit id (git hash) `SHOULD NOT` be used in the version number. It is good @@ -43,24 +43,24 @@ in the [API section of the handbook](api.md). Regarding version number increases, the following guidelines are to be considered: -- 👉 The *major* version number `SHOULD` be increased - - for major revisions affecting all or most features, or most of the - user interface; - - if significant features changed or reimplemented fundamentally, - or removed; - - if compatibility with existing configurations is broken; - - if public access paths (i.e. URLs) have changed in an incompatible way. +- 👉 The *major* version number `SHOULD` be increased + - for major revisions affecting all or most features, or most of the + user interface; + - if significant features changed or reimplemented fundamentally, + or removed; + - if compatibility with existing configurations is broken; + - if public access paths (i.e. URLs) have changed in an incompatible way. - 👉 The *minor* version number `SHOULD` be increased - - when new features have been added; - - when the underlying framework or other core dependencies have had a major + - when new features have been added; + - when the underlying framework or other core dependencies have had a major version upgrade. - 👉 The *patch* level version number `SHOULD` be increased - - for bug fixes and small improvements to existing features; - - for minor dependency upgrades; - - for any other kind of maintenance that does not affect functionality or - compatibility. + - for bug fixes and small improvements to existing features; + - for minor dependency upgrades; + - for any other kind of maintenance that does not affect functionality or + compatibility. - 👉 The *qualifier* can be increased at any point during alpha, beta and release -candidate development stages. For stable releases, it must be excluded altogether. + candidate development stages. For stable releases, it must be excluded altogether. ## Releasing @@ -72,41 +72,41 @@ Promote (or demote) according to the descriptions below. The version number presence of the qualifier part of the version number. - **Alpha**: Feature developments - - Stability and functionality do not have to be guaranteed - - Dependencies can still change, including updates to new minor versions - - Alpha status should be clear to the end user in the application's - interface (if applicable) + - Stability and functionality do not have to be guaranteed + - Dependencies can still change, including updates to new minor versions + - Alpha status should be clear to the end user in the application's + interface (if applicable) - **Beta**: Feature freeze - - Bug fixes and feature enhancements - - Dependency checks, update to latest within minor and apply any - available security updates - - Version control: branch off from development - - Beta status should be clear to the end user in the application's - interface (if applicable) + - Bug fixes and feature enhancements + - Dependency checks, update to latest within minor and apply any + available security updates + - Version control: branch off from development + - Beta status should be clear to the end user in the application's + interface (if applicable) - **Release candidate** - - Bugs are either fixed or documented as known issues - - Final dependency checks, main focus on security (high and critical - vulnerabilities must be resolved or else documented) - - Write or finalise a change log and upgrade instructions + - Bugs are either fixed or documented as known issues + - Final dependency checks, main focus on security (high and critical + vulnerabilities must be resolved or else documented) + - Write or finalise a change log and upgrade instructions - **Release** - - Should be identical to the last release candidate except for the - version number - + - Should be identical to the last release candidate except for the + version number + ### Hotfixes {TODO} ### Publication -👉 Make a GitHub or GitLab release for each stable tag. +👉 Make a GitHub or GitLab release for each stable tag. + - Specify any major changes in this version - If it is a maintenance release, write 'Maintenance release' - List major vulnerabilities resolved - For images: specify the version of base image os and relevant software packages -(also if not changed) + (also if not changed) - For 'base images': include the relevant platform versions in the title of the -release (e.g. `3.18.4 / Java 17.0.9`) - + release (e.g. `3.18.4 / Java 17.0.9`) ### Docker image versioning @@ -115,22 +115,21 @@ release (e.g. `3.18.4 / Java 17.0.9`) a platform or environment: - Scheme for the version number/tag is `{APP_VERSION}_{X.Y.Z}` - - Where `{X.Y.Z}` is a version that follows the guidlines above and starts with -`1.0.0` for each new value of `{APP_VERSION}` - - `{APP_VERSION}` `MAY` include qualifiers such as `alpha1`, but `{X.Y.Z}` - `SHOULD` consist of three dot separated digits only - - `{APP_VERSION}` `MAY` be reduced to a significant level such as `{major.minor}` - or in some cases even just `{major}` - - Resetting of the image version resets for every app version, so there will be, - for instance, `1.0_1.0.0`, followed by `1.0_2.0.0` and `1.1_1.0.0`. - - Examples: + - Where `{X.Y.Z}` is a version that follows the guidlines above and starts with + `1.0.0` for each new value of `{APP_VERSION}` + - `{APP_VERSION}` `MAY` include qualifiers such as `alpha1`, but `{X.Y.Z}` + `SHOULD` consist of three dot separated digits only + - `{APP_VERSION}` `MAY` be reduced to a significant level such as `{major.minor}` + or in some cases even just `{major}` + - Resetting of the image version resets for every app version, so there will be, + for instance, `1.0_1.0.0`, followed by `1.0_2.0.0` and `1.1_1.0.0`. + - Examples: | App v. | | Image v. | Combined | |--------------|---|----------|------------------------| | 1.0.0 | _ | 1.0.0 | app-1.0.0_1.0.0 | | 1.1.0-alpha1 | _ | 1.2.2 | app-1.1.0-alpha1_1.2.2 | - 👉 For *base images* and other images that provide a platform or 'environment' rather than an application (e.g. alpine, java, tomcat, nginx), version numbering `MAY` follow the same scheme as applications (`major.minor.path[-qualifier]`). @@ -140,99 +139,97 @@ rather than an application (e.g. alpine, java, tomcat, nginx), version numbering 👉 The following approach `SHOULD` be followed for compose projects: - IFF there is a single application with a single version number it is built -around, follow the same scheme as for application docker images (`{APP_VERSION}_{X.Y.Z}`) + around, follow the same scheme as for application docker images (`{APP_VERSION}_{X.Y.Z}`) - Otherwise use 'independent' version numbering (suite version) - Naming of the project typically reflects whether it is application centered or -a 'suite'. In the latter case it has (or could have) a name that is different to -one of the included services. + a 'suite'. In the latter case it has (or could have) a name that is different to + one of the included services. ## Branching, merging strategies -- General guidelines on workflow(s) - - - Default choice: Git Flow - - Stages (active development/out of development/deprecated) - - Projects that go ‘out of development’ can have their **development branch dropped**; in this stage, only make hotfixes. - - Hotfix should be in hotfix branch (not directly to main) -- Branches - - The main branch - - \= Stable - - Should have tests and checks in successful state (or warning, no fail) - - Avoid direct commits to main branch - - Use GH/GL repo config to protect main branch - - Name: use ‘main’ for new projects - ok but not necessary to rename in existing projects - - Configure your local git client to use ‘main’ as the default branch when initializing new repositories: -   git config --global init.defaultBranch main - ([source](https://github.blog/2020-07-27-highlights-from-git-2-28/#introducing-init-defaultbranch)) - - - Development branch(es) - - Name: ^dev(elop(ment)?)?$ - - “Permanent” development branch? - - Keep ahead of main branch! With merge. - - Alpha tags/release can be made from this branch - - Feature branches - - Naming - - Good practice to include issue number(s) if applicable - - Otherwise as descriptive (but short) as possible - - Should branch off directly from the development branch. Do not ‘stack’ - - Rebase and clean up before merging back into the targeted branch - - Don’t force push the feature branch unless it is a private one - - Alpha tags/release can be made from this branch - - Release branches - - Name - - release-x.y(.z) - - Upon feature freeze - - Version number in code base changes on this branch (not develop) - - From here you may tag x.y.z-betaN (also alpha) - - Bug fixes until ready for x.y.z release - - Merge into main branch at time of x.y.z release, then tag x.y.z on main branch -- Tags - - Avoid deleting tags - - Exception can be to try to avoid usage anywhere - - Exception can be to immediately clean up after a slip-up - - In case of image to be removed from container repo - - Delete the image from the container repo but keep the tag, adding a description to the release - - NEVER remove a tag if there has ever been a deployment based on that tag (whether testing, staging or production) - - Re-tagging - - Do not re-tag (use same tag name twice) UNLESS - - In a private repository - - Know for sure that it can not have been used anywhere - - Never for stable (non alpha, beta or RC) - - Examples of tag patterns for application (note: this repeats on the right hand side for  docker images, see section X) - - Towards release \`x.y.z\`, normally in this order - - alpha release(s): \`x.y.z-alphaN\` - - \[feature freeze\] - - beta release(s): \`x.y.z-betaN\` - - release candidates: \`x.y.z-rcN\` - - final release: \`x.y.z\` -- Pull requests / merge requests (PRs) - - Good practice to use PRs instead of merging directly in the client, especially if multiple people are actively working on a project - - Make pull requests on feature branches (& release branches) - - preferably pull requests are not made on permanent branches - - note: if your branching strategy includes permanent branches other than the main branch (e.g. development), it probably fits to make release branch - - Naming: PR name should describe the change and if applicable a reference to the issue # - - in case of feature branches the name of the branch might give this information - - beware of default behaviour of Git(Hub|Lab) to use last commit message as title - - PR acceptance - - Tests & checks should all pass - - If overriding failed checks, document reason in a comment - - Code reviews? - - See below - - Recommended to request review for PR if multiple active contributors - - Branch specific requirements -- Forks - - If the sausage making is very ugly, consider doing it in a fork - - Examples: - - work that is likely to require a lot of rewriting of git history - - testing - - experimenting with tags, CI pipeline - - Branch in fork with same name as upstream can serve as feature branch - PR must clearly describe the feature -- Maintaining multiple versions - - Keep a permanent branch for older versions that need to be maintained - - If need be such a branch can be created at any stage - - Avoid ‘orphaned’ tags - - +- General guidelines on workflow(s) + + - Default choice: Git Flow + - Stages (active development/out of development/deprecated) + - Projects that go ‘out of development’ can have their **development branch dropped**; in this stage, only make hotfixes. + - Hotfix should be in hotfix branch (not directly to main) +- Branches + - The main branch + - \= Stable + - Should have tests and checks in successful state (or warning, no fail) + - Avoid direct commits to main branch + - Use GH/GL repo config to protect main branch + - Name: use ‘main’ for new projects - ok but not necessary to rename in existing projects + - Configure your local git client to use ‘main’ as the default branch when initializing new repositories: +   git config --global init.defaultBranch main + ([source](https://github.blog/2020-07-27-highlights-from-git-2-28/#introducing-init-defaultbranch)) + + - Development branch(es) + - Name: ^dev(elop(ment)?)?$ + - “Permanent” development branch? + - Keep ahead of main branch! With merge. + - Alpha tags/release can be made from this branch + - Feature branches + - Naming + - Good practice to include issue number(s) if applicable + - Otherwise as descriptive (but short) as possible + - Should branch off directly from the development branch. Do not ‘stack’ + - Rebase and clean up before merging back into the targeted branch + - Don’t force push the feature branch unless it is a private one + - Alpha tags/release can be made from this branch + - Release branches + - Name + - release-x.y(.z) + - Upon feature freeze + - Version number in code base changes on this branch (not develop) + - From here you may tag x.y.z-betaN (also alpha) + - Bug fixes until ready for x.y.z release + - Merge into main branch at time of x.y.z release, then tag x.y.z on main branch +- Tags + - Avoid deleting tags + - Exception can be to try to avoid usage anywhere + - Exception can be to immediately clean up after a slip-up + - In case of image to be removed from container repo + - Delete the image from the container repo but keep the tag, adding a description to the release + - NEVER remove a tag if there has ever been a deployment based on that tag (whether testing, staging or production) + - Re-tagging + - Do not re-tag (use same tag name twice) UNLESS + - In a private repository + - Know for sure that it can not have been used anywhere + - Never for stable (non alpha, beta or RC) + - Examples of tag patterns for application (note: this repeats on the right hand side for  docker images, see section X) + - Towards release \`x.y.z\`, normally in this order + - alpha release(s): \`x.y.z-alphaN\` + - \[feature freeze\] + - beta release(s): \`x.y.z-betaN\` + - release candidates: \`x.y.z-rcN\` + - final release: \`x.y.z\` +- Pull requests / merge requests (PRs) + - Good practice to use PRs instead of merging directly in the client, especially if multiple people are actively working on a project + - Make pull requests on feature branches (& release branches) + - preferably pull requests are not made on permanent branches + - note: if your branching strategy includes permanent branches other than the main branch (e.g. development), it probably fits to make release branch + - Naming: PR name should describe the change and if applicable a reference to the issue # + - in case of feature branches the name of the branch might give this information + - beware of default behaviour of Git(Hub\|Lab) to use last commit message as title + - PR acceptance + - Tests & checks should all pass + - If overriding failed checks, document reason in a comment + - Code reviews? + - See below + - Recommended to request review for PR if multiple active contributors + - Branch specific requirements +- Forks + - If the sausage making is very ugly, consider doing it in a fork + - Examples: + - work that is likely to require a lot of rewriting of git history + - testing + - experimenting with tags, CI pipeline + - Branch in fork with same name as upstream can serve as feature branch - PR must clearly describe the feature +- Maintaining multiple versions + - Keep a permanent branch for older versions that need to be maintained + - If need be such a branch can be created at any stage + - Avoid ‘orphaned’ tags ## Code reviews @@ -240,43 +237,43 @@ one of the included services. ## Continuous integration -- Where? - - GitLab - - Docker builds -> deploy to GitLab (repo) docker registry - - Docker compose (test stage tested on GitLab; performance benefit of loading of images from registry) - - Building of GitHub projects on GitLab for full chain Maven -> Image build & deploy to registry - - Pay attention to artifact size limits - - GitHub actions - - For application code - - Can be used to trigger build on GitLab - - (Theoretically) more portable than Travis - - Travis - - Guideline: transition to GitHub actions if feasible - - +- Where? + - GitLab + - Docker builds -> deploy to GitLab (repo) docker registry + - Docker compose (test stage tested on GitLab; performance benefit of loading of images from registry) + - Building of GitHub projects on GitLab for full chain Maven -> Image build & deploy to registry + - Pay attention to artifact size limits + - GitHub actions + - For application code + - Can be used to trigger build on GitLab + - (Theoretically) more portable than Travis + - Travis + - Guideline: transition to GitHub actions if feasible + - Recommended to have all the following stages implemented: Stages -- Linting / resource validation - - Docker files - - Shell scripts - - JS - - CSS - - XML - - Python?? -- Compiling / building -- Testing - - Application code: unit tests - - Docker: build script test command (compose based) - - Docker compose: control script test command -- Security check/scan - - Docker (compose): snyk -- Release - - Application: deploy artifact to GitHub release - - Docker: deploy multi-architecture image to repository +- Linting / resource validation + - Docker files + - Shell scripts + - JS + - CSS + - XML + - Python?? +- Compiling / building +- Testing + - Application code: unit tests + - Docker: build script test command (compose based) + - Docker compose: control script test command +- Security check/scan + - Docker (compose): snyk +- Release + - Application: deploy artifact to GitHub release + - Docker: deploy multi-architecture image to repository Ignoring or skipping (failing) tests: -- During development -- In case of upstream issues that cannot be resolved +- During development +- In case of upstream issues that cannot be resolved diff --git a/docs/general-guidelines/configuration.md b/docs/general-guidelines/configuration.md index e69de29..a025a48 100644 --- a/docs/general-guidelines/configuration.md +++ b/docs/general-guidelines/configuration.md @@ -0,0 +1 @@ +# Configuration diff --git a/docs/general-guidelines/documentation.md b/docs/general-guidelines/documentation.md index e69de29..25f8d45 100644 --- a/docs/general-guidelines/documentation.md +++ b/docs/general-guidelines/documentation.md @@ -0,0 +1 @@ +# Documentation diff --git a/docs/general-guidelines/logging.md b/docs/general-guidelines/logging.md index beff444..76429cb 100644 --- a/docs/general-guidelines/logging.md +++ b/docs/general-guidelines/logging.md @@ -1,42 +1,44 @@ -- General - - Logging best practices??? -- Log levels - - What goes at what level - - Log levels in different ecosystems -- Log content - - Important things & events to log - - Tag - - Always include context (ideally provided by logging framework); i.e. line number, class & method, relevant exception etc - - Processability (consider grep, parsing, use in dashboards) - - Content to avoid in logs - - Secrets - - (Potentially) personal information at >= INFO level - - (user)names, IP addresses, e-mail, address, etc - - CLARIN policy/statement (re GDPR) - - Long content (can frameworks help you - formatting options) -- Log frameworks - - See language specific suggestions in section above -- Prepare for log aggregation: fluent - - log parsing - - Parse at the 'source' (i.e. local fluent config in image) - - Conventions / vocabulary for field names (with types) - - Full message, timestamp, log level, context, ... - - Required fields - - Include full/original/unparsed message - - Recommended fields - - Timestamp -- Log configurations - - Main log level(s) should be configurable - - At container level for main process(es) via environment variable(s) - - Other logging configuration - - Nice if it can be overridden -- Special cases - - Timing - - Include unit - - Process start/stop - - Progress - - Heartbeat - - ... -- Smells / bad practices - - Extensive logging for debugging (especially if not cleaned up) - - Expensive calculations in log messages (especially if not lazy) +# Logging + +- General + - Logging best practices??? +- Log levels + - What goes at what level + - Log levels in different ecosystems +- Log content + - Important things & events to log + - Tag + - Always include context (ideally provided by logging framework); i.e. line number, class & method, relevant exception etc + - Processability (consider grep, parsing, use in dashboards) + - Content to avoid in logs + - Secrets + - (Potentially) personal information at >= INFO level + - (user)names, IP addresses, e-mail, address, etc + - CLARIN policy/statement (re GDPR) + - Long content (can frameworks help you - formatting options) +- Log frameworks + - See language specific suggestions in section above +- Prepare for log aggregation: fluent + - log parsing + - Parse at the 'source' (i.e. local fluent config in image) + - Conventions / vocabulary for field names (with types) + - Full message, timestamp, log level, context, ... + - Required fields + - Include full/original/unparsed message + - Recommended fields + - Timestamp +- Log configurations + - Main log level(s) should be configurable + - At container level for main process(es) via environment variable(s) + - Other logging configuration + - Nice if it can be overridden +- Special cases + - Timing + - Include unit + - Process start/stop + - Progress + - Heartbeat + - ... +- Smells / bad practices + - Extensive logging for debugging (especially if not cleaned up) + - Expensive calculations in log messages (especially if not lazy) diff --git a/docs/general-guidelines/maintenance.md b/docs/general-guidelines/maintenance.md index 2e93e11..873ad3f 100644 --- a/docs/general-guidelines/maintenance.md +++ b/docs/general-guidelines/maintenance.md @@ -1,60 +1,239 @@ -## Maintenance +# Maintenance Project statuses -- Prototype -- Active development -- Maint -- Deprecated - deployed -- Deprecated - undeployed +- Prototype +- Active development +- Maint +- Deprecated - deployed +- Deprecated - undeployed -

Label

Development

Maintenance

Deployed

Notes

A

+

+

-

Prototyping to first RC

B

+

+

+

Matur(ing), in use

At least one stable release

C

-

+

+

Stable, feature frozen

D

-

-

+

Abandoned, in use

E

-

-

-

Dead

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Label

+
+

Development

+
+

Maintenance

+
+

Deployed

+
+

Notes

+
+

A

+
+

+

+
+

+

+
+

-

+
+

Prototyping to first RC

+
+

B

+
+

+

+
+

+

+
+

+

+
+

Matur(ing), in use

+

At least one stable release

+
+

C

+
+

-

+
+

+

+
+

+

+
+

Stable, feature frozen

+
+

D

+
+

-

+
+

-

+
+

+

+
+

Abandoned, in use

+
+

E

+
+

-

+
+

-

+
+

-

+
+

Dead

+
Definitions -- Development - - There is a development roadmap specific to the dev project - - Has at least one responsible developer assigned -- Maintenance - - Has at least one responsible maintainer assigned - - Responsible for monitoring code base in terms of vulnerabilities, functional breakages - - Responsible for addressing (at the very least) critical issues in the code base - - Example activities covered - - Dependency / base image updates - - Implement required adaptations to new or changed context (OS, runtime, servlet container, ...) +- Development + - There is a development roadmap specific to the dev project + - Has at least one responsible developer assigned +- Maintenance + - Has at least one responsible maintainer assigned + - Responsible for monitoring code base in terms of vulnerabilities, functional breakages + - Responsible for addressing (at the very least) critical issues in the code base + - Example activities covered + - Dependency / base image updates + - Implement required adaptations to new or changed context (OS, runtime, servlet container, ...) -

Status


Project examples

A

Prototyping - first RC

VCR JS widget

VLO 5.0

DOG

B

Matur(ing), in use

VLO

VCR

C

Stable, feature frozen

Switchboard

Component Registry

Centre Registry

OAI-PMH Harvester, viewer

RASA

D

Abandoned, in use

SAML-metadata-checker

earlier: FCS?

E

Dead

clarin-horizon_drupal_theme

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Status

+
  +

Project examples

+
+

A

+
+

Prototyping - first RC

+
+

VCR JS widget

+

VLO 5.0

+

DOG

+
+

B

+
+

Matur(ing), in use

+
+

VLO

+

VCR

+
+

C

+
+

Stable, feature frozen

+
+

Switchboard

+

Component Registry

+

Centre Registry

+

OAI-PMH Harvester, viewer

+

RASA

+
+

D

+
+

Abandoned, in use

+
+

SAML-metadata-checker

+

earlier: FCS?

+
+

E

+
+

Dead

+
+

clarin-horizon_drupal_theme

+
\[TODO: guidelines matrix for status X aspect\] Per project status: -- What drives releases? - - A-B: roadmap - - C: external factors, e.g. support for underlying technology, fixing of critical bugs and vulnerabilities - - D-E: n/a -- Maintainer(s) - tasks and responsibilities - - A-C MUST address critical security risks - - CAN address other issues - - enhancements and new functionality covered by developer role! - - No maintainer (cat D, E) -> operational handbook - - Possibility to (temporarily) address as C in short term - - OR (temporarily) shut down -- Repository - - Cat A-C: MUST be findable in Git repositories - - D: SHOULD be in Git repository, MAY be in deprecated repository system - - E: SHOULD be archived -- Issue reporting & tracking - - A-B: known issues, envisioned features are documented in issue tracking system by developer/maintainer - - may be for C as well but without commitment - - A-B-C: maintainer will handle incoming issue reports via repository system - - D-E: issue reporting is disabled -- Documentation - - A: needs to have minimal documentation (needs to be defined) for development, deployment, testing purposes (up-to-date README file) - - B-C: need to have up-to-date documentation both for development and operational purposes and end users; changelog - - D-E: documentation needs to include statement about status of project -- Monitoring -> operational - - B-C: needs permanent monitoring with alerting, log aggregation to ensure good health - - D: included in general monitoring to ensure being alive - - +- What drives releases? + - A-B: roadmap + - C: external factors, e.g. support for underlying technology, fixing of critical bugs and vulnerabilities + - D-E: n/a +- Maintainer(s) - tasks and responsibilities + - A-C MUST address critical security risks + - CAN address other issues + - enhancements and new functionality covered by developer role! + - No maintainer (cat D, E) -> operational handbook + - Possibility to (temporarily) address as C in short term + - OR (temporarily) shut down +- Repository + - Cat A-C: MUST be findable in Git repositories + - D: SHOULD be in Git repository, MAY be in deprecated repository system + - E: SHOULD be archived +- Issue reporting & tracking + - A-B: known issues, envisioned features are documented in issue tracking system by developer/maintainer + - may be for C as well but without commitment + - A-B-C: maintainer will handle incoming issue reports via repository system + - D-E: issue reporting is disabled +- Documentation + - A: needs to have minimal documentation (needs to be defined) for development, deployment, testing purposes (up-to-date README file) + - B-C: need to have up-to-date documentation both for development and operational purposes and end users; changelog + - D-E: documentation needs to include statement about status of project +- Monitoring -> operational + - B-C: needs permanent monitoring with alerting, log aggregation to ensure good health + - D: included in general monitoring to ensure being alive diff --git a/docs/general-guidelines/privacy-data-protection.md b/docs/general-guidelines/privacy-data-protection.md index e69de29..16bc6e1 100644 --- a/docs/general-guidelines/privacy-data-protection.md +++ b/docs/general-guidelines/privacy-data-protection.md @@ -0,0 +1 @@ +# Privacy and data protection diff --git a/docs/general-guidelines/security.md b/docs/general-guidelines/security.md index 9d7c5b7..d74cd2b 100644 --- a/docs/general-guidelines/security.md +++ b/docs/general-guidelines/security.md @@ -8,49 +8,49 @@ General guideline: any known vulnerability with HIGH or CRITICAL severity should ### Application code -- Use up-to-date dependencies - - Run check (e.g. [Maven dependency plugin](https://maven.apache.org/plugins/maven-dependency-plugin/analyze-mojo.html), npm/pip/.. update commands) - - Policy for use of unmaintained/unsupported deps?? - - -- Add project to snyk, enable GitHub security scans (Dependabot) -- Include linting in CI -- Cover AAI & input validation in unit tests -- Handle snyk reports: -- Sign binaries & packages? - - [Support in package managers](https://blog.tidelift.com/the-state-of-package-signing-across-package-managers) +- Use up-to-date dependencies + - Run check (e.g. [Maven dependency plugin](https://maven.apache.org/plugins/maven-dependency-plugin/analyze-mojo.html), npm/pip/.. update commands) + - Policy for use of unmaintained/unsupported deps?? + - +- Add project to snyk, enable GitHub security scans (Dependabot) +- Include linting in CI +- Cover AAI & input validation in unit tests +- Handle snyk reports: +- Sign binaries & packages? + - [Support in package managers](https://blog.tidelift.com/the-state-of-package-signing-across-package-managers) ### Image development -- Use up-to-date base images -- Use up-to-date build script -- Run docker security scan and linting in CI - - When can security scan be skipped/overridden/ignored - - Set allow\_failure: true in CI yaml config (GitLab) - - Pressure to get image out (e.g. RC -> stable release) - - Evaluate + document risk (create ticket) - - Pipeline conf change to security scan should be immediately reverted in branch or not merged -- Run services as users with minimal permissions (do not leave as or set to root) - - Make such a  user in docker file and set it in supervisor config -- Make configuration files read-only -- Make application code read-only -- Verify hash + signatures if available of downloaded binaries -- Verify signatures of static executed files at runtime if possible - - e.g. signed hash of python code -- Sign images?? +- Use up-to-date base images +- Use up-to-date build script +- Run docker security scan and linting in CI + - When can security scan be skipped/overridden/ignored + - Set allow\_failure: true in CI yaml config (GitLab) + - Pressure to get image out (e.g. RC -> stable release) + - Evaluate + document risk (create ticket) + - Pipeline conf change to security scan should be immediately reverted in branch or not merged +- Run services as users with minimal permissions (do not leave as or set to root) + - Make such a  user in docker file and set it in supervisor config +- Make configuration files read-only +- Make application code read-only +- Verify hash + signatures if available of downloaded binaries +- Verify signatures of static executed files at runtime if possible + - e.g. signed hash of python code +- Sign images?? ### Compose project development -- Only use images that have been checked for vulnerabilities (i.e. based on recent CLARIN base images) -- Run security check in CI (not yet implemented) -- Network configuration - - Don’t bind host to port if not needed (rarely needed) - - Make overlay for development if necessary (rather than commented out lines) - - Allow access beyond internal networks only if necessary. Use the ‘internal’ option of the network configuration, which creates an ​​externally isolated overlay network (see [Compose file version 3 reference](https://docs.docker.com/compose/compose-file/compose-file-v3/#internal)) - - e.g. database containers generally do not need to be able to access anything or be accessed by anything on the internet -- Volumes & mounts - - Don’t mount docker socket into container - - If possible avoid host mounts - - If needed, make read-only - - If needed, make a specific/minimal as possible - - Alternative solution: operation within container (e.g. on volume) and pull (copy) out of container or push out - - If needed for development, define in overlay +- Only use images that have been checked for vulnerabilities (i.e. based on recent CLARIN base images) +- Run security check in CI (not yet implemented) +- Network configuration + - Don’t bind host to port if not needed (rarely needed) + - Make overlay for development if necessary (rather than commented out lines) + - Allow access beyond internal networks only if necessary. Use the ‘internal’ option of the network configuration, which creates an ​​externally isolated overlay network (see [Compose file version 3 reference](https://docs.docker.com/compose/compose-file/compose-file-v3/#internal)) + - e.g. database containers generally do not need to be able to access anything or be accessed by anything on the internet +- Volumes & mounts + - Don’t mount docker socket into container + - If possible avoid host mounts + - If needed, make read-only + - If needed, make a specific/minimal as possible + - Alternative solution: operation within container (e.g. on volume) and pull (copy) out of container or push out + - If needed for development, define in overlay diff --git a/docs/general-guidelines/testing.md b/docs/general-guidelines/testing.md index e69de29..f00b526 100644 --- a/docs/general-guidelines/testing.md +++ b/docs/general-guidelines/testing.md @@ -0,0 +1 @@ +# Testing diff --git a/docs/interoperability-and-portability/authentication-mechanisms.md b/docs/interoperability-and-portability/authentication-mechanisms.md index 7a15a42..c01341e 100644 --- a/docs/interoperability-and-portability/authentication-mechanisms.md +++ b/docs/interoperability-and-portability/authentication-mechanisms.md @@ -1,19 +1,19 @@ # Authentication mechanisms -- Shibboleth - - Use library (Java: shhaa filter - [https://github.com/clarin-eric/mpgaai](https://github.com/clarin-eric/mpgaai)) - - Other cases: depend on headers (taken care of by central proxy) - - Developing a shibbolized application - - Local development: normally it should be sufficient to have swappable auth configuration (e.g. basic auth & saml) - - Testing - - Not easy to test until first deployment in a prepared (by sysops) environment - - Easiest would be with test environment (sandboxed with IdP and SP, proxy); deployment method is a question - - Not available right now! -- API authentication - - Browser based API access - - UI served from same server - user can authenticate, API can be used through same session - - Non-browser based - - Token based - - Token has to be requested in shibbolized session -- Other auth mechanism - - Support basic auth for testing, other deployments +- Shibboleth + - Use library (Java: shhaa filter - [https://github.com/clarin-eric/mpgaai](https://github.com/clarin-eric/mpgaai)) + - Other cases: depend on headers (taken care of by central proxy) + - Developing a shibbolized application + - Local development: normally it should be sufficient to have swappable auth configuration (e.g. basic auth & saml) + - Testing + - Not easy to test until first deployment in a prepared (by sysops) environment + - Easiest would be with test environment (sandboxed with IdP and SP, proxy); deployment method is a question + - Not available right now! +- API authentication + - Browser based API access + - UI served from same server - user can authenticate, API can be used through same session + - Non-browser based + - Token based + - Token has to be requested in shibbolized session +- Other auth mechanism + - Support basic auth for testing, other deployments diff --git a/docs/interoperability-and-portability/configuration.md b/docs/interoperability-and-portability/configuration.md index fbc88a9..cf9479d 100644 --- a/docs/interoperability-and-portability/configuration.md +++ b/docs/interoperability-and-portability/configuration.md @@ -2,76 +2,76 @@ ## What should be configurable and how? -- HOWs - - Config file - - App specific environment variable - - Global system property (application inherits) - - Potentially with override option - - Database - - External service - - ... -- User & role management - - Externalise all user, role, credentials information from code base - - Normally there is no need for 'real' management of usernames and passwords; standard situation: db or back end service username/password; end users authenticate through SAML - - Store roles (if applicable) in database, provided management interface - - Storing passwords in plain text (i.e. not a hash, unencrypted) should be avoided - - Having a property in the general configuration for e.g. defining admin user ids is an anti-pattern - - There can be a property to 'bootstrap' users and roles, e.g. a 'master' admin - - +- HOWs + - Config file + - App specific environment variable + - Global system property (application inherits) + - Potentially with override option + - Database + - External service + - ... +- User & role management + - Externalise all user, role, credentials information from code base + - Normally there is no need for 'real' management of usernames and passwords; standard situation: db or back end service username/password; end users authenticate through SAML + - Store roles (if applicable) in database, provided management interface + - Storing passwords in plain text (i.e. not a hash, unencrypted) should be avoided + - Having a property in the general configuration for e.g. defining admin user ids is an anti-pattern + - There can be a property to 'bootstrap' users and roles, e.g. a 'master' admin + - ## External configurability -- Means no (re-)build is needed to apply -- Reloading configuration - - Hot reloadable preferable (can also be manually triggered through UI) - - If application restart is required, make sure that active sessions don't get broken if at all possible - otherwise warn -- Docker (compose) - - Wherever possible, provide defaults - - Dockerfile - - - - Compose YAML file: "FOO: ${MY\_FOO:-default}" - - In .env this allows for optional "MY\_FOO=bar" - - Mandatory settings without a default - - Docker image should also have logic to check for mandatory settings (use init script) - - Compose YAML file: "FOO: ${MY\_FOO:?err}" or "${MY\_LOCAL\_DIRECTORY:?err}:/path/inside/container" - - See [compose file documentation](https://docs.docker.com/compose/compose-file/compose-file-v3/#variable-substitution) - - Particularly useful for mandatory volumes/mounts +- Means no (re-)build is needed to apply +- Reloading configuration + - Hot reloadable preferable (can also be manually triggered through UI) + - If application restart is required, make sure that active sessions don't get broken if at all possible - otherwise warn +- Docker (compose) + - Wherever possible, provide defaults + - Dockerfile + - + - Compose YAML file: "FOO: ${MY\_FOO:-default}" + - In .env this allows for optional "MY\_FOO=bar" + - Mandatory settings without a default + - Docker image should also have logic to check for mandatory settings (use init script) + - Compose YAML file: "FOO: ${MY\_FOO:?err}" or "${MY\_LOCAL\_DIRECTORY:?err}:/path/inside/container" + - See [compose file documentation](https://docs.docker.com/compose/compose-file/compose-file-v3/#variable-substitution) + - Particularly useful for mandatory volumes/mounts ## Parameters vs files -- Aim for lowest complexity -- Configuration parameters - - Environment variables -- Configuration files - - & docker images - - mounting as file vs mount as directory - - directory mount preferred as it can be modified without recreating the container - - 'Core application' configuration & library/util configuration (logging, scheduling, auth, ...) - - If one or more aspects of configuration are done through a mount (e.g. logging), configuration of this should be optional, i.e. provide a default - - You can provide a way of overriding the core application config (that is normally filtered as a template) through a mount - - & compose projects - - directory (or optionally file) configurable through .env variable - - Loading from external source - - e.g. GitHub - - Not a preferable method for application configuration, use conventions described above; suitable for other resources such as definitions (e.g. data mappings), display content (e.g. help page and other documentation, headers & footers) etc. - - Provide a local caching mechanism - don't depend on availability of external resource in real time - - use a local copy; e.g. in container environment load resource on container init - - try to reload if applicable - - warn if local copy is too old - - Do a validation after retrieval/refresh, before updating cache - - Syntax check - - If there is any risk e.g. of vulnerability injection or vandalism, it can be mitigated with a signature check - - Preferred format/serialization/syntax? - - {Investigate} - - Requirements: - - allows comments - - can be validated (schema?) - - transformable +- Aim for lowest complexity +- Configuration parameters + - Environment variables +- Configuration files + - & docker images + - mounting as file vs mount as directory + - directory mount preferred as it can be modified without recreating the container + - 'Core application' configuration & library/util configuration (logging, scheduling, auth, ...) + - If one or more aspects of configuration are done through a mount (e.g. logging), configuration of this should be optional, i.e. provide a default + - You can provide a way of overriding the core application config (that is normally filtered as a template) through a mount + - & compose projects + - directory (or optionally file) configurable through .env variable + - Loading from external source + - e.g. GitHub + - Not a preferable method for application configuration, use conventions described above; suitable for other resources such as definitions (e.g. data mappings), display content (e.g. help page and other documentation, headers & footers) etc. + - Provide a local caching mechanism - don't depend on availability of external resource in real time + - use a local copy; e.g. in container environment load resource on container init + - try to reload if applicable + - warn if local copy is too old + - Do a validation after retrieval/refresh, before updating cache + - Syntax check + - If there is any risk e.g. of vulnerability injection or vandalism, it can be mitigated with a signature check + - Preferred format/serialization/syntax? + - {Investigate} + - Requirements: + - allows comments + - can be validated (schema?) + - transformable ## Interactive management (e.g. configuration/admin panel) -- +- `` ## Links -- https://12factor.net/config +- diff --git a/docs/interoperability-and-portability/localisation.md b/docs/interoperability-and-portability/localisation.md index 303170b..2da4548 100644 --- a/docs/interoperability-and-portability/localisation.md +++ b/docs/interoperability-and-portability/localisation.md @@ -1,49 +1,47 @@ # Localisation / internationaliszation - -- Application configuration - - Default locale - - Make locale configurable (?)Determining locale for client - - Respect browser setting - - User override (through UI) - - Don't use location for this!! -- Character set - - on provisioning, set server/host default encoding to UTF-8 - - docker images: configure default encoding to UTF-8 - - Applications: use UTF-8 explicitly -- Multilingual interfaces - - Does the interface have to be multilingual? - - Only if content is also available in other languages - - \[insert link to articles about developer assumptions\] - - UI testing - - Very exotic Non-latin characters and diacritics (umlauts) - - Strings with variables inserted (order, split) - - Tests forms, error messages, generated strings - - Also check: - - numerical values (thousands and decimal separators) - - dates - pay attention to different renderings (long, short, month name, day of the week) - - Manual test with browser - - Set browser to non-standard language/locale - - Use platform's framework - - Do it from the start - - Use this consistently - - Don't use more different methods for defining string resources than necessary - - Gotchas - - {find online documentation for this} - - text direction; plural/singular; complex formatting (printf vs string concatenation) - - Aligning application, frameworks/libraries and content localisation - - Check that e.g. widgets don't do 'rogue' localisation - - Writing direction - - Where it's easy, be agnostic - - We don't design or test explicitly for different writing directions (only ltr) -- Date and time - - date formats ISO 8601 - - time zones, DST - - explicit timezone - - on provisioning, set server/host timezone to UTC+0 - - docker images: configure to explicitly set timezone to UTC+0 (part of init logic in base image) - - & logging - - Always log date/time with timezone included - - Aim for using a single time zone across servers and applications - - Date/time format: configure [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) - +- Application configuration + - Default locale + - Make locale configurable (?)Determining locale for client + - Respect browser setting + - User override (through UI) + - Don't use location for this!! +- Character set + - on provisioning, set server/host default encoding to UTF-8 + - docker images: configure default encoding to UTF-8 + - Applications: use UTF-8 explicitly +- Multilingual interfaces + - Does the interface have to be multilingual? + - Only if content is also available in other languages + - \[insert link to articles about developer assumptions\] + - UI testing + - Very exotic Non-latin characters and diacritics (umlauts) + - Strings with variables inserted (order, split) + - Tests forms, error messages, generated strings + - Also check: + - numerical values (thousands and decimal separators) + - dates - pay attention to different renderings (long, short, month name, day of the week) + - Manual test with browser + - Set browser to non-standard language/locale + - Use platform's framework + - Do it from the start + - Use this consistently + - Don't use more different methods for defining string resources than necessary + - Gotchas + - {find online documentation for this} + - text direction; plural/singular; complex formatting (printf vs string concatenation) + - Aligning application, frameworks/libraries and content localisation + - Check that e.g. widgets don't do 'rogue' localisation + - Writing direction + - Where it's easy, be agnostic + - We don't design or test explicitly for different writing directions (only ltr) +- Date and time + - date formats ISO 8601 + - time zones, DST + - explicit timezone + - on provisioning, set server/host timezone to UTC+0 + - docker images: configure to explicitly set timezone to UTC+0 (part of init logic in base image) + - & logging + - Always log date/time with timezone included + - Aim for using a single time zone across servers and applications + - Date/time format: configure [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) diff --git a/docs/stack/bash.md b/docs/stack/bash.md index 500760d..ca59d6d 100644 --- a/docs/stack/bash.md +++ b/docs/stack/bash.md @@ -11,7 +11,7 @@ Bash [^BASH] if possible. * 👉 Any shell script `SHOULD` always be written in bash, using the following shebang: -``` +```bash #!/usr/bin/env bash ``` @@ -35,7 +35,7 @@ We leave it up to the developer / sysop to judge if and when a script becomes too long and too difficult to maintain. If implementing in Bash is not possible or considered not suitable it is possible to implement the task in a different language, preferably resulting in an executable -binary which runs out-of-the-box without the need to install a runtime +binary which runs out-of-the-box without the need to install a runtime environment. ## Dependencies @@ -44,8 +44,8 @@ Scripts can make use of external dependencies to function properly. It is important to be aware of any missing dependencies before executing the scripts. Installing dependencies automatically from a script can have an impact on other processes running in the same environment and thus should be -avoided where possible. The script should check for the availability of the -dependencies during runtime and inform the user on how to proceed in case some +avoided where possible. The script should check for the availability of the +dependencies during runtime and inform the user on how to proceed in case some dependency is missing. The use of subshells [^SUBSHELLS] is considered a good approach to isolate the @@ -75,8 +75,8 @@ Some important highlights from this guide: * Quote variables as `"${foo}"` instead of `$foo` and commands as `$(foo)` instead of `foo`. * Avoid `eval`. -* Write a `main` function for scripts longer than a few lines and/or other - functions and call it in the very end(i.e. last line) of the script, passing +* Write a `main` function for scripts longer than a few lines and/or other + functions and call it in the very end(i.e. last line) of the script, passing all parameters: `main "$@"`. * Calling scripts: use `bash script.sh` or `./script.sh` (not `sh script.sh`). @@ -94,7 +94,7 @@ Checking if a variable is set: * Just testing `-z ${var}` doesn’t fail for the empty string `""`. Instead use: -``` +```bash if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi ``` @@ -121,7 +121,7 @@ enabled on gitlab.com [^GITLAB] as follows: Example: -``` +```yaml variables: GIT_SUBMODULE_STRATEGY: recursive DOCKER_DRIVER: overlay2 @@ -145,7 +145,7 @@ shell-check: For github actions try this: -``` +```yaml name: Shell linting on: push: diff --git a/docs/stack/docker.md b/docs/stack/docker.md index 45b1775..e1f2f42 100644 --- a/docs/stack/docker.md +++ b/docs/stack/docker.md @@ -5,17 +5,17 @@ images. ## General -- [x] TODO: discussion on application centered images vs use of environment -image (e.g. tomcat) and deploy application @ compose level +- [x] TODO: discussion on application centered images vs use of environment + image (e.g. tomcat) and deploy application @ compose level - [ ] Reference to operational section(s) on Docker (compose) - [x] Docker version - [x] Docker compose version - [ ] Implementation of custom logic in compose project - - [ ] subcommands - - [ ] custom start/stop - - [ ] backup and restore + - [ ] subcommands + - [ ] custom start/stop + - [ ] backup and restore - [ ] Developing for use outside CLARIN infra context - - [ ] "bundle" control script submodule + - [ ] "bundle" control script submodule - [x] Name for projects/repositories -> image. TODO: discuss! - [x] Strategy for base images - [x] Strategy for application images @@ -32,17 +32,17 @@ For the CLARIN infrastructre we have created a set of base images, based on the [alpine linux](https://www.alpinelinux.org/) [docker image](https://hub.docker.com/_/alpine), to provide an environment where we can more easily deploy existing services. These environments provide a supervisord daemon as the main process. The -supervisord daemon [^SUPERVISORD] manages a couple of additional processes +supervisord daemon [^SUPERVISORD] manages a couple of additional processes aimed at streamlining integration into our infrastructure. These processes are: -* td-agent [^TDAGENT], to tag and manage log output in the single stdout stream +- td-agent [^TDAGENT], to tag and manage log output in the single stdout stream of the container. Typically applications such as nginx, postgres, tomcat, etc write multiple log files with different types of information. Td-agent allows us to tag each of these streams so that these can be identified in the single container stdout stream. -* cron [^CROND], a cron deamon to periodically run tasks inside the container. +- cron [^CROND], a cron deamon to periodically run tasks inside the container. This is used sparsely and might be removed at a later point in time. -* logrotate [^LOGROTATE], because we have processes running inside the container +- logrotate [^LOGROTATE], because we have processes running inside the container that writes log data to files, we use the logrotate daemon to be able to ensure log files are properly rotated and cleaned. @@ -50,8 +50,8 @@ aimed at streamlining integration into our infrastructure. These processes are: We are currently supporting the following versions: -* Docker engine version `20.10.x`. -* Docker compose yaml version `3.1`. +- Docker engine version `20.10.x`. +- Docker compose yaml version `3.1`. `TODO` Provide a link to the operational docker guidelines. @@ -60,33 +60,32 @@ We are currently supporting the following versions: #### Base images Any image providing some environment intended to be used by other images is -considered a base image. +considered a base image. Naming convention: -``` +```bash docker---base ``` Where: -* `` provides and indication of the underlying base image, typically +- `` provides and indication of the underlying base image, typically `alpine` for our base images. -* ``: describes the main function of the image. +- ``: describes the main function of the image. -Example: `docker-alpine-supervisor-base` as the name for the supervisor base +Example: `docker-alpine-supervisor-base` as the name for the supervisor base image on alpine linux. Most important base images: -* [docker-alpine-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-base) - * [docker-alpine-supervisor-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-supervisor-base) - * [docker-alpine-supervisor-java-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-supervisor-java-base) - * [docker-alpine-supervisor-java-tomcat-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-supervisor-java-tomcat-base) - * [docker-alpine-fpm-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-fpm-base) - +- [docker-alpine-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-base) + - [docker-alpine-supervisor-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-supervisor-base) + - [docker-alpine-supervisor-java-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-supervisor-java-base) + - [docker-alpine-supervisor-java-tomcat-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-supervisor-java-tomcat-base) + - [docker-alpine-fpm-base](https://gitlab.com/CLARIN-ERIC/docker-alpine-fpm-base) -* 👉 When developing a new image, you `SHOULD` base you image on the +- 👉 When developing a new image, you `SHOULD` base you image on the `docker-alpine-supervisor-base` base image or any of its base image descendants in most cases. @@ -97,13 +96,13 @@ image. Naming convention: -``` +```bash docker- ``` Where: -* ``: describes the main function of the image. +- ``: describes the main function of the image. Example: `docker-aai-discovery` as the name for the discovery service frontend image. @@ -114,74 +113,73 @@ Containers started from images that go together to offer a functional service, e.g. a frontend, backend and a database, are typically grouped into deployable projects via [docker compose](https://docs.docker.com/compose/). -* 👉 (Compose) Projects are what we deploy and run on our infrastructure via the -CLARIN [deploy script](https://gitlab.com/CLARIN-ERIC/deploy-script). -* 👉 These projects are started and stopped via the CLARIN [control script](https://gitlab.com/CLARIN-ERIC/control-script). +- 👉 (Compose) Projects are what we deploy and run on our infrastructure via the + CLARIN [deploy script](https://gitlab.com/CLARIN-ERIC/deploy-script). +- 👉 These projects are started and stopped via the CLARIN [control script](https://gitlab.com/CLARIN-ERIC/control-script). ## Code style - [ ] Dockerfiles - - [ ] CLARIN docker best practices - - [ ] Use tag + digest for base image - - [ ] Differences from docker best practices - - https://docs.docker.com/develop/develop-images/dockerfile_best - -practices/ - - https://docs.docker.com/get-started/09_image_best/ - - [ ] Base images + - [ ] CLARIN docker best practices + - [ ] Use tag + digest for base image + - [ ] Differences from docker best practices + - + - + - [ ] Base images - [ ] For each main process - - [ ] Supervisord setup - - [ ] Fluentd setup - - [ ] See Logging - - [ ] Logrotate setup + - [ ] Supervisord setup + - [ ] Fluentd setup + - [ ] See Logging + - [ ] Logrotate setup - [ ] Default healthcheck - - [ ] How to customise + - [ ] How to customise - [ ] Entrypoint - - [ ] Supervisor base images - - [ ] Other cases + - [ ] Supervisor base images + - [ ] Other cases - [ ] Initialisation logic - [ ] ‘Core’ application directory - - [ ] Choice of directory for stand-alone applications - - [ ] If the environment or other context (e.g. tomcat) provides a - requirement or - - [ ] guideline, follow that + - [ ] Choice of directory for stand-alone applications + - [ ] If the environment or other context (e.g. tomcat) provides a + requirement or + - [ ] guideline, follow that - [ ] If the choice is arbitrary, recommended locations follow OS conventions (typically alpine) - [ ] for binaries - - [ ] /usr/local/bin + - [ ] /usr/local/bin - [ ] for application bundles?? - - [ ] last WORKDIR in Dockerfile must be set to this directory + - [ ] last WORKDIR in Dockerfile must be set to this directory - [ ] Compose projects - - [ ] .env file/variables - - [ ] Overlays - - [ ] Use cases - - [ ] When not to use -> when variables can do the trick - - [ ] Custom scripts should hide complexity - - [ ] Volumes & networks - - [ ] Internal & external + - [ ] .env file/variables + - [ ] Overlays + - [ ] Use cases + - [ ] When not to use -> when variables can do the trick + - [ ] Custom scripts should hide complexity + - [ ] Volumes & networks + - [ ] Internal & external ## Frameworks - [ ] Build script - - [ ] https://gitlab.com/CLARIN-ERIC/build-script + - [ ] - [ ] Testing - - [ ] images - - [ ] Build script --test argument with docker-compose - - [ ] compose projects - - [ ] test with ?? + - [ ] images + - [ ] Build script --test argument with docker-compose + - [ ] compose projects + - [ ] test with ?? ## Documentation -- [ ] Image project - - [ ] README - - [ ] Reference base image - - [ ] List the important application and configuration locations (paths) - inside the - - [ ] image - - [ ] List the user name(s) defined and used in the image +- [ ] Image project + - [ ] README + - [ ] Reference base image + - [ ] List the important application and configuration locations (paths) + inside the + - [ ] image + - [ ] List the user name(s) defined and used in the image ## Build tools & Continuous Integration - [ ] Describe our gitlab CI integration with hadolint - - [ ] Include examples + - [ ] Include examples - [ ] Gitlab Docker repository ## Testing tools @@ -198,10 +196,10 @@ application to work as the upstream server. This is because we want: 1. The upstreams to be uniform so that in the future we can deploy client / server authentication between the proxy and the upstreams in a standard way. -2. Non-standard webserver configurations that are specific to a certain +1. Non-standard webserver configurations that are specific to a certain applications (e.g. SNI), will be deployed in the application project itself. Avoiding split logic. -3. The application should respond to all their requests on the same upstream +1. The application should respond to all their requests on the same upstream port. Again, wherever possible making the central proxy configuration unaware of the need for different ports. @@ -212,7 +210,7 @@ nginx by default) There may be multiple nginx services in the same compose project as a result. One would be the dedicated proxy service. This is a desirable situation. -* [^SUPERVISORD] [supervisord website](http://supervisord.org/) -* [^TDAGENT] [td-agent / fluentd website](https://www.fluentd.org/download) -* [^CROND] [crond - Linux man page](https://linux.die.net/man/8/crond) -* [^LOGROTATE] [logrotate - Linux man page](https://linux.die.net/man/8/logrotate) +- [^SUPERVISORD] [supervisord website](http://supervisord.org/) +- [^TDAGENT] [td-agent / fluentd website](https://www.fluentd.org/download) +- [^CROND] [crond - Linux man page](https://linux.die.net/man/8/crond) +- [^LOGROTATE] [logrotate - Linux man page](https://linux.die.net/man/8/logrotate) diff --git a/docs/stack/javascript.md b/docs/stack/javascript.md index e69de29..34774ad 100644 --- a/docs/stack/javascript.md +++ b/docs/stack/javascript.md @@ -0,0 +1 @@ +# Javascript diff --git a/docs/stack/python.md b/docs/stack/python.md index e69de29..4193ef4 100644 --- a/docs/stack/python.md +++ b/docs/stack/python.md @@ -0,0 +1 @@ +# Python diff --git a/lint.sh b/lint.sh index d8d244b..19a0775 100755 --- a/lint.sh +++ b/lint.sh @@ -2,8 +2,5 @@ set -euo pipefail SCRIPT_DIR="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" -echo "Linting README" \ - && bash "${SCRIPT_DIR}/mdl.sh" 'README.md' \ - && echo "Linting docs" \ - && export WORKDIR="${SCRIPT_DIR}/docs" \ - && find "${WORKDIR}" -type f -name '*.md'| xargs bash "${SCRIPT_DIR}/mdl.sh" \ No newline at end of file +echo "Linting *.md files" \ + && find . -type f -name '*.md'| xargs bash "${SCRIPT_DIR}/mdl.sh" \ No newline at end of file