Skip to content

Latest commit

 

History

History
1001 lines (721 loc) · 46.1 KB

contributing.adoc

File metadata and controls

1001 lines (721 loc) · 46.1 KB

Contributing

You’re Invited!

In the spirit of open source software, everyone is welcome to contribute to this project!

We believe strongly that developing software in the open produces the best outcome. In order for that to work, the project relies on your support. We have big goals for the project and we rely on a variety of talent to achieve those goals.

The best way to get involved is to just show up and make yourself heard. We pride ourselves on having a very friendly and encouraging culture.

Whether you’re a user, writer, designer, developer, architect, devops, system administrator, advocate, project manager, or just someone with an idea about how to improve the project, we welcome your participation. In return, you’ll get to use better software that we built together as a community and a great sense of pride for having been a part of making it.

We want your choice to participate in the Antora project to be the start of an exciting and rewarding journey. From all of us to you, welcome!

Code of Conduct

The Antora project and its project spaces are governed by our Code of Conduct. By participating, you’re agreeing to honor this code. Let’s work together to make this a welcoming, professional, inclusive, and safe environment for everyone.

Project Host

This project is hosted on GitLab under the Antora organization. This is the official home of the project. All development, project and issue management, and continuous integration is done here.

Permissions

You do not need a GitLab.com account to browse the issues and merge requests, read the source code and documentation, or view the CI results. However, you do need a GitLab.com account to file an issue and/or submit a merge request.

Have something to report?

Do you have an idea? Have you found an error?

Antora is an issue-driven project.

If you have an idea for an improvement or have discovered an error or omission, head over to the issue tracker. Review the list of issues to check if someone has already filed an issue about that subject. If an issue already exists, we welcome you to join the conversation. If an issue doesn’t exist, please don’t hesitate to create a new one.

If you want to help complete an issue by contributing code, documentation, or other enhancements, review our contribution workflow, then submit a merge request (MR) for review. However, please wait until we have agreed on what change to make before submitting an MR. This avoids the discussion of the change getting lost and saves maintainers from having to address MRs that aren’t relevant.

When thinking about how to contribute, please know that while merge requests are welcome, they aren’t the first thing that’s needed. In fact, submitting a merge request (without prior discussion) can often slow down progress on an issue because it requires the maintainers to stop, review it, and reconcile it with the proposed design. What we need more than anything else is help with the requirements and design, which often means making decisions in response to open questions. Making those decisions is the exceptionally hard part. Once that’s done, writing the code becomes straightforward. It’s either something the maintainers can do or it can serve as an opportunity for someone in the community to contribute code (without the aforementioned disruption).

Contribution Workflow

Since Antora is an issue-driven project, a merge request (MR) should always be linked to an open issue.

Note
One exception to this rule is if you’re submitting copy edits to the documentation. If you’re fixing grammar or typos that don’t otherwise change the focus of the content, you can submit an MR directly.
  1. Review the issue tracker to see if we’re already discussing your idea or problem.

    • If you don’t see an issue that fits your scenario, then you may create a new one.

  2. Discuss what change to make to resolve the issue in the issue comments.

    • Please don’t submit an MR before there is an agreement on what change should be made.

  3. If you’d like to submit code, documentation or other enhancements for an issue, review the following information first.

  4. Fork the project and name your branch after its issue.

  5. Write, code, tinker, and have fun!

    • Don’t forget to lint and test your code.

  6. When you’re ready for feedback, open a MR.

    • On the MR form, you must check the box Allow commits from members who can merge to the target branch. The MR cannot be accepted unless this box is checked. If you forget, you can fix it by clicking the Edit button on the MR page.

Fork, Branch, Commit, and Merge Request Rules

To contribute to the project:

  1. Fork the project. We do not accept merge requests that do not come from a dedicated branch in a fork.

  2. Create a dedicated branch in your fork for your changes. Name the branch after the issue number it fixes along with a short textual hint.

    Here’s an example of a branch name for issue #2, which was to initiate the Gulp build:

    issue-2-init-gulp-build

    If you’re only working on docs, then add docs/ to the beginning of the branch name. Here’s an example of a branch name for issue #168, which was to write documentation for the sitemap generation:

    docs/issue-168-document-sitemap

    The docs/ prefix tells the CI server not to run the test suite.

  3. In the issue tracker, label the issue as [Progress] Preparing Change and make sure you’re assigned to it so that the rest of the team knows you’re working on it. If the issue is already assigned but not labeled as being worked on feel free to reassign it to yourself.

  4. Make your changes.

    1. Use as many commits as you think are necessary, but each commit should consist of a logical change.

    2. Write tests to verify each change.

    3. If not already present, add yourself to the list of contributors in the package.json file for the package you’re modifying.

  5. Write concise but explicit commit messages. Write the commit message as though the person reading it cannot see the code change.

    1. Write the message in lowercase and imperative tense.

    2. Put the subject on the first line of the commit message (required).

    3. Separate the subject line from the body using a blank line.

    4. The body lines should be structured as an unordered list (Markdown syntax).

    5. In each body line, succinctly identify an important change and/or explain why the change was made (optional).

      rename component descriptor filename to antora.yml
      
      - rename component descriptor from docs-component.yml to antora.yml
      - promote component descriptor filename to a constant
  6. Prior to submitting a MR, rebase your branch against the main branch, then push the branch to your fork.

  7. Create an MR from your branch (using the URL shown in the terminal when you push).

    1. Begin the title of the MR with the issue it resolves followed by a restatement of the issue.

      resolves #2 initialize gulp build
    2. If you’re still working on your branch and want feedback on it before it is complete, start the MR with WIP (e.g., WIP: resolves #2 initialize gulp build). When the MR is ready for final review, you can remove WIP: from the MR title using the button in the interface.

    3. In some select cases, the implementation of an issue might be broken up into separate commits if they can be tested and work in isolation. This is why only the MR subject mentions the issue being resolved and not the subject of the commit.

  8. In the issue tracker, mark the issue as [Progress] In Review.

  9. Your MR must pass the CI pipeline. If it fails, update your MR once you’ve corrected any problems.

  10. A project member will be assigned to your MR and review it.

    1. During review, a project member may request changes to your MR, either in a comment on the MR or the associated issue.

    2. Checkout the MR approval guidelines if you want to see how your MR will be evaluated.

  11. Append a new commit or rewrite an existing commit, depending on what you think is most appropriate, if you need to incorporate changes into your MR after you’ve pushed it.

  12. When your MR is approved, a project member will merge it using a merge commit with semi-linear history.

    1. The maintainer may decide to squash review commits, or request for you to do so. Only original work is guaranteed to be preserved in the commit history.

Coding Requirements and Workflow

  1. Set up your development workspace.

  2. Review any applicable architecture guidebooks.

  3. Make sure your work is consistent with any relevant ADRs.

  4. Make sure you’ve forked the project and named your branch after the issue you’re working on.

  5. Add your code and tests.

    1. Make sure your code adheres to the JavaScript standard style and the custom project styles.

    2. Make sure your tests adhere to the test requirements.

  6. Update the API documentation.

  7. Update the applicable architecture guidebooks if your code significantly changes a package’s inputs, outputs or primary functionality.

  8. Run the test suite (which also lints the code) and correct any errors.

  9. Commit your changes.

  10. Run prettier.

    Warning
    The format script will modify your files, so be sure to commit your changes before running it so you can review and rollback if necessary.
  11. Commit any formatting changes completed by prettier.

  12. Push to your fork and open a merge request.

Documentation requirements

  1. Generally, imitate the style and formatting of what’s already written. This list is by no means exhaustive.

  2. Follow the one sentence per line or “ventilated prose” formatting.

  3. Paths should be formatted with [.path]_antora.yml_

  4. Reserved words should be formatted with [.term]*versionless component*

  5. Quotes should generally be "`smart quotes`"

Architecture Decisions Records

Significant project and technology decisions are outlined in our architecture decision records (ADRs).

The ADRs are numbered in the order they were proposed.

A new ADR should be proposed prior to adding, removing, upgrading or significantly changing software dependencies, frameworks, tools, environments, infrastructure, or CI, CD, and release processes. A new ADR should also be proposed when considering major administrative, resource, and scope changes to the Antora organization.

Component Architecture Guidebooks

Each Antora component has an architecture guidebook. A guidebook provides an overview of why the component is important and why it’s structured as it is. It outlines:

  • the problem a component solves

  • its high-level functionality

  • its inputs and outputs

  • important code, API, and data model requirements

  • the consequences of the functions and requirements on the Antora pipeline

Before contributing to a component, make sure you are familiar with its guidebook. If you make a significant modification to a package, you should also update the guidebook if applicable.

Code structure and style expectations

We read code more than we edit it, so it’s important to have consistency throughout the code base.

Antora’s JavaScript code must adhere to the JavaScript Standard Style. We’ve modified a few of the standard style rules (e.g., max-len) and added some custom ones (e.g., comma-dangle, arrow-parens). The style rules are enforced using eslint with a tailored StandardJS profile. The code is formatted using prettier, which applies fixes for the standard style rules as well as a few of its own.

eslint and prettier

You can find a list of rules on the standard JS site. We don’t use the StandardJS command line tool. We use its rules and configuration through ESLint. There are text editor plugins for ESLint that you can use, if that’s what you prefer. We have modified some of the standard rules and added custom rules, which are documented in .eslintrc.

While not enforced by eslint yet, your code should also comply with the following rules:

  • Use SCREAMING_SNAKE_CASE for constant names (not any const declaration, but rather a formal constant).

  • Keep all require declarations together at the top of the file (no blank lines), and sort them alphabetically, unless there’s a reason they can’t be.

  • Functions should be defined using the function keyword in main code and using const with a function shorthand const fn = () ⇒ {} in tests.

  • Functions should be defined at the top of the source file and exports at the bottom.

When you build Antora, it will automatically lint (i.e., style check) your JavaScript code.

If you ever want to run the linter separately, you can use the following npm script:

$ npm run lint

While ESLint checks for syntax, it doesn’t cover all the aesthetics of a code style. We employ prettier to automatically format the code. Run prettier after you commit all your code changes as the format script will modify your files.

To run prettier, enter the following npm script:

$ npm run format

Paths

Paths, including both virtual file paths and filesystem paths, have to be handled carefully in Antora. This section describes what you need to know.

In the virtual file catalog, all files have POSIX paths, which are independent of the platform on which Antora is running. A POSIX (aka Unix-style) path is a path that uses forward slashes to separate directories and descends from a single root (no drive letter) (e.g., path/to/file.adoc). They basically look the same as URL paths (the part after the domain).

Only when interfacing with the filesystem (input and output) can the path be platform dependent. We use a virtual file object (currently Vinyl) to move files between the physical and virtual filesystem. When reading a file from the physical filesystem into the virtual filesystem, it’s always necessary to “posixify” the path (convert backslashes to forward slashes if the platform’s path separator is backslash). When writing a file to the physical filesystem, the path should be converted from a virtual path using Node’s path module.

Important
When assigning a POSIX path to a virtual (Vinyl) file, use history.push instead of path = to circumvent platform-specific normalization. We eventually want to remove the need for this workaround.

To help make the distinction between virtual and physical paths in the code clear, we’ve introduced a convention.

When working with path calculations that pertain to virtual files as well as URLs, we must always use the path.posix module. This module exposes the POSIX-specific path operations regardless of the platform on which Antora is running. The path.posix module should always be imported to the symbol path:

const { posix: path } = require('path')

When working with physical files (i.e., interfacing with the filesystem), we must always use the default path module. This module provides platform-specific path operations (e.g., is aware of drive letters in Windows, can transparently convert POSIX paths to Windows paths when appropriate, etc). The default path module should always be imported to the symbol ospath:

const ospath = require('path')

Following this practice ensure it’s easy to tell from anywhere in the code whether the path is real (and thus platform-dependent) or virtual (and thus POSIX).

Additional style and performance rules

Please adhere to the following style and performance rules which are not currently enforced by the linter.

  • Store regular expressions in constants using the suffix _RX.

  • Use the spread operator to convert an Iterator (or similar) to an Array (e.g., [...map.values()]).

    • Do not use Array.from since its performance is abysmal in Node.js 10.

  • Use the Array constructor + Array#fill + Array#map to populate a new fixed-length array (e.g., Array(10).fill(undefined).map(() => <logic>))

    • Do not use Array.from since its performance is abysmal in Node.js 10.

  • Use the spread syntax to combine arrays instead of Array#concat (e.g., [...accum, value] or [...current, ...more]).

    • The spread syntax is substantially faster across all versions of Node.js.

    • It’s also clearer when you’re adding a single value versus combining arrays.

    • Always make sure the spread operator is used on the first argument.

  • Use Object.assign to duplicate an object or combine objects (e.g., Object.assign({}, object) or Object.assign({}, more, { key: 'val' }).

    • The performance of the spread operator on objects has degraded significantly in Node.js 12.

    • Keep in mind that Object.assign modifies the first argument.

    • Place the new object first to reduce the number of arguments, but only do so if the object to append doesn’t have those properties.

    • Prefer object spread in the test suite.

  • Avoid the use of the spread syntax during assignment (const { prop, ...rest } = obj) to delete properties, unless it’s executed very few times.

  • If reducer function can be run in parallel, append to copy of the accumulator object instead of modifying it.

    • Appending to a copy of the accumulator is an order of magnitude slower, so it’s best to do it only when required.

  • Prefer using the second argument of then() to define a rejection handler instead of a chained catch() (though this is not always possible)

  • Use ~str.indexOf(c) instead of str.includes(c).

  • Use str.charAt() === c instead of str.startsWith(c)

  • Use str.charAt(str.length - 1) === c instead of str.endsWith(c).

  • Use str.substr instead of str.slice for chopping off leading or trailing characters.

  • Use str.substr(0, str.length - 1) instead of str.substr(-1)

  • Use String() to convert a primitive to a string (e.g., String(1))

  • Use .toString() to convert a Buffer to a string (e.g., buff.toString())

  • Use ++ instead of += 1 (style rule only)

  • Use v.indexOf() < 0 instead of !~v.indexOf() (style rule only)

  • Use err instead of e for the error variable, using an optional prefix (e.g., cloneErr).

  • If a function is not declared as async, but can return a Promise, always return a Promise (or else it is not guaranteed to response to .then)

    • It’s best to mark functions that return a Promise as async just to be sure.

  • Only throw Error and derivatives of Error such as TypeError and user-defined objects that extend Error. Although JavaScript can throw any type of object, using Error and derivatives of Error is considered a best practice. Using any other type of value will not generate a stack trace and makes handling errors more difficult.

Test structure and coverage expectations

Tests should mirror the structure of the application code to make it easy for developers to find the tests that correspond to the application code. That means each package should have a test/ folder adjacent to the lib/ folder and the test file names should match the file with the function under test.

If you need to add a new test to the suite, you can use a test in one of the packages as a reference (e.g., packages/file-publisher/test/publish-files-test.js). Those tests already follow the structure of the project and demonstrate how to use mocha, chai, and the numerous helpers provided by the test harness.

Apart from the classic chai assertions, several plugins are enabled. You’ll find the documentation for their APIs here:

  • chai-spies to create and test spies on callbacks

  • chai-fs to assert files and directory structures

  • chai-cheerio to assert HTML structures (though Antora has its own implementation)

  • dirty-chai (more like clean chai) to allow all terminal assertions to end with ()

Here are a few rules when writing tests and assertions:

  • Name the test file using the -test.js file extension.

  • Always require test-utils, importing at least the expect function.

  • Require any functions under test using the corresponding module name / path, not a relative path (npm will resolve them).

  • Use describe to group tests into categories.

  • You can use the await keyword in any test or before/after function, as long as you add async to the function declaration.

  • Use BDD-style assertions (e.g., expect(actual).to.have.property('foo')).

  • All assertions should be a function call (e.g., to.be.true()), not a terminal expression (e.g., to.be.true).

  • When creating a negated assertion, please write it as .to.not instead of .not.to (e.g., expect(actual).to.not.have.property('bar')).

    • To help you remember, the assertion should always begin with .to.

  • Use .equal instead of .eql to compare strings (e.g., expect(actual).to.equal('foo')).

    • expect#equal is a strict === comparison

  • Use .eql to compare arrays and objects (e.g., expect(actual).to.equal(['a', 'b', 'c'])).

    • expect#eql compares each item in the array or object, not the instance itself

    • expect#equal always fails on two different array or object instances

  • If the expected result is used many times, consider using a variable named expected.

  • If you need to set up mock/spy objects for several tests, consider using beforeEach().

    • beforeEach() is most useful when it’s used to setup spies (the call counts get reset for each test).

    • Giving a name to a spy makes things easy in test logs.

  • Place fixtures in the fixtures/ subdirectory of the test folder.

  • Use trapAsyncError to trap an expected Error of an async function so you can assert it using .to.throw(message).

You can run the whole test suite manually or continuously. You can also select individual tests to run.

Project Organization

Antora is a Node.js project organized as a set of Node.js packages that are published to the npm registry at npmjs.com. Node.js is a JavaScript runtime based on the V8 JavaScript engine. A Node.js package is a folder tree described by a package.json file.

This section describes the organization of the project at a high level so you know where to look for files.

Project Structure

Here are some of the files and directories you will see when developing this project:

docs/         (1)
node_modules/ (2)
packages/     (3)
  asciidoc-loader/
  cli/
  content-aggregator/ (4)
    devdocs/
      architecture-guidebook.adoc
    lib/
    node_modules/ (2)
    test/
    package.json (5)
  content-classifier/
  document-converter/
  navigation-builder/
  ...
package.json  (6)
package-lock.json (7)
  1. The end user documentation for Antora.

  2. A local installation of Node.js modules used for the development of this project.

  3. Discrete software components (i.e., packages) that make up Antora core.

  4. The main code, test code, and architecture documentation for the content aggregator component. Developer documentation for each software component lives alongside the code.

  5. Defines project information and runtime and development library dependencies for the content aggregator component.

  6. Defines project information, build dependencies, and run scripts.

  7. Tracks the version of resolved dependencies to ensure builds are reproducible.

Development Workspace Setup

This section gives you all the information you need to set up your development workspace and begin hacking on the code.

Prerequisites

In order to obtain the source code, run the test suite, and launch Antora, you’ll need the following prerequisites:

  • git

  • Node.js / npm

  • Development libraries (e.g., a C compiler)

The following sections describe the prerequisites in detail and provide resources with additional instructions about how to install them.

git

The source code of the project is hosted in a git repository. The first software you’ll need on your machine is git (command: git). You’ll use git to obtain the source code and push updates to it.

First, check if you have git installed.

$ git --version

If not, download and install the git package for your system.

Although Antora doesn’t use git at runtime, git is used in the test suite to provide a local git server for testing interactions with remote repositories.

Node.js / npm

Antora is built on Node.js (“Node”) (command: node). To work with the project, you must have Node.js installed on your machine. The Node.js installation also provides npm (command: npm), which you’ll use to install additional Node.js modules.

To see which version of Node.js you have installed, open a terminal and type:

$ node -v

If node -v doesn’t return any information, you don’t yet have Node.js installed.

The minimum required version of Node.js is 12.21.0, as indicated in package.json. However, we recommend using the active LTS release (currently Node.js 16). These are also the recommended versions of Node.js for development.

Why Node.js 12 and above?

Antora tracks the Node.js release schedule. This ensures maximum compatibility with dependencies and ensures you always receive the latest security updates. It also means Antora can leverage the latest and greatest features of ECMAScript to deliver the best features and performance.

If you don’t yet have Node.js installed, or the version of Node.js you have isn’t Node.js 12 or greater, we strongly recommend using nvm (Node Version Manager) to manage your Node.js installations. Follow the nvm installation instructions to set up nvm on your machine.

Tip
Many CI environments use nvm to install the version of Node.js used for the build job. By using nvm, you can closely align your setup with the environment that is used to generate and publish the production site.

Once you’ve installed nvm, open a new terminal and install Node.js 16 using:

$ nvm install 16

The above command will install the latest version of Node.js 16.

If you already have other Node.js versions installed, you can configure Node.js 16 as the default for any new terminal.

$ nvm alias default 16

You can skip this step if you didn’t previously have any Node.js versions installed because nvm install automatically adds the default alias to the first version of Node.js you install.

Verify the version of Node.js you have selected using:

$ node -v

You should also be able to run npm:

$ npm -v

This project uses npm (command: npm) to manage various tasks, such as test, lint, format, etc. These tasks are defined in package.json. You can list the available scripts by running npm run without any arguments:

$ npm run

The rest of the software you need is installable from Node.js (specifically npm).

Development Libraries

Some Node.js packages require development libraries, such as a C compiler, to be available on your machine. It’s very likely you already have these libraries. If for some reason you don’t, you can return to this section to satisfy this prerequisite.

If you’re using Linux, install the base build tools package by executing the command below that cooresponds to your Linux distribution.

  • Fedora: dnf install @development-tools

  • Debian/Ubuntu: apt-get install build-essential

  • Arch Linux: pacman -S base-devel

  • Alpine Linux: apk add g++ make

  • RHEL: yum install gcc-c++ make

If your using macOS, you’ll need the Xcode command line tools. You can trigger installation using the following command:

$ xcode-select --install

If you’re on Windows, there’s usually nothing you need to install.

Obtain the Source Code

The next step is to obtain the source code of the project, which you’ll do by cloning the git repository. Remember to fork the repository.

Clone the source repository using:

$ git clone https://gitlab.com/antora/antora.git &&
  cd "`basename $_`"

You can copy and paste the above command directly into your terminal. The command will clone the repository, then switch to the newly created project folder.

Install Dependencies

Initializing the project means downloading and installing the dependencies (i.e., the required software) for the project. That’s the job of npm.

Important

You must have at least npm 8 to install the development dependencies for Antora. If you don’t have npm 8, install it into the project using:

$ mv package.json package~.json && mv package-lock.json package-lock~.json
  npm i --no-package-lock --no-save --no-audit npm@$(node -p 'require("./package~.json").devDependencies.npm')
  rm -f node_modules/.package-lock.json
  mv package~.json package.json && mv package-lock~.json package-lock.json

You can use the version of npm installed in the project by adding npx in front of any npm command. For example:

$ npx npm i

To avoid having to do this, build Antora using Node.js 16 (or better), which ships with at least npm 8.

In your terminal, execute the following command from the root folder of the project:

$ npm i

The command i is shorthand for install. The install command uses dependency information defined in package.json and package-lock.lock to resolve dependencies, which npm then installs inside the project under the node_modules/ folder (and, in some cases, under the node_modules/ folder inside each package).

After pulling the latest source, you may need to update the dependencies. It’s best to start with a fresh slate by removing the previously install dependencies, then installing them again. To do so, run the following commands in sequence:

$ rm -rf node_modules packages/*/node_modules
  npm i
Note
If you run into problems while installing dependencies, return to Development Libraries.
Note
It’s a good idea to run npm i each time after you run git pull to make sure your dependencies are up to date. Running an npm script such as npm run build does not install any updated dependencies.

Build the Project

To build Antora, which means running all the primary tasks, use:

$ npm run build

To see a list of all available npm scripts, run:

$ npm run

These commands are covered in the sections that follow.

Run the Test Suite

This project uses mocha to run the tests and the assertion library chai. Mocha is configured in .mocharc.js. The build script is automatically configured to lint your JavaScript code, which it does once all the tests pass.

To run the test suite, use:

$ npm run build
Tip

Tests use the Internet to query gitlab.com to download the default UI. By default, Mocha fails any test that takes more than 2 seconds to complete. To increase the timeout (up to 30 seconds), set the CI variable:

$ CI=true npm run build

If you want to generate a coverage report when running the tests (enabled by default in CI), run the coverage script instead:

$ npm run coverage

A coverage report shows the lines, statements, and branches that the tests exercise. The report is generated by istanbul using the nyc command line tool. You can view the coverage report by opening the HTML file reports/lcov-report/index.html in your browser.

Tip

To clear the coverage report and related cache files from a previous run, use:

$ rm -rf reports .nyc_output node_modules/.cache/nyc

If you don’t want the lint script to run when running tests, call the test lifecycle script directly:

$ npm test
Tip
The command npm test is a shorthand for npm run test and can be further abbreviated as npm t.

If you want to run the linter separately, use the following npm script:

$ npm run lint

You can run the test suite for a single package by passing the name of the package to the --package flag:

$ npm test --package ui-loader

You can include the linter as well:

$ npm build --package ui-loader

This filter works for all npm scripts.

If you’re working on tests or refactoring the code under test, you can run the test suite continuously by adding the --watch option:

$ npm test --watch

You may want to combine the --watch option with the package filter to limit the tests to only the package you’re working on:

$ npm test --package ui-loader --watch

This command runs the test suite each time you save the test or the code under test.

You can pass additional options directly to the mocha command by placing them after the -- separator. We can use this, for instance, to specify which files to watch:

$ npm test --package ui-loader --watch -- --watch-files='packages/ui-loader/lib/ui-catalog.js'

Run npx mocha --help to discover other options.

Select or Skip Tests

You can run select tests by appending .only to the describe and/or it method calls (e.g., it.only(). You can read more about this feature in the mocha documentation.

You can skip tests by appending .skip to the describe and/or it method calls (e.g., describe.skip()). You can read more about this feature in the mocha documentation.

Run prettier

Prettier is run by the format script. The format script isn’t (yet) run as part of the CI pipeline, so you’ll need to run it manually. But don’t forget to run the format script before you submit a merge request!

To run prettier on your code, execute the following npm script:

$ npm run format

You should run prettier after you commit all your code changes. The format script will modify your files in place. If you still have changes to make to the code, this formatting can make that tedious. By committing your code first, then running prettier and committing those changes as a separate commit, it’ll be easier to rollback the changes if you need to.

Run the development version

After fixing critical bugs or implementing your wonderful new feature, you’ll probably want to test out your local Antora version on your projects. The code in packages is already set up to be run from source. When you ran npm i to install the dependencies, it set up a bin stub from node_modules/.bin/antora to packages/cli/bin/antora.

Therefore, the most convenient way to run your development code is to use the local bin stub:

$ npx --offline antora /path/to/your/antora-playbook.yml

which is equivalent to running:

$ ./node_modules/.bin/antora /path/to/your/antora-playbook.yml
Tip

It might be convenient to turn this script location into an alias so you can execute the development version of Antora from any directory:

$ alias antora-dev=$HOME/projects/antora/node_modules/.bin/antora

Then you can run:

$ antora-dev /path/to/your/antora-playbook.yml

You can instruct your shell to register this alias automatically by defining it in your shell profile (e.g., $HOME/.bash_profile).

Install a prerelease version

If you want to test the most release prerelease version which has been published to the npm registry, you need to refer to the keyword testing when installing a package. Otherwise, the npm command (or yarn command) will not pick up the prerelease.

If you install packages globally using the npm i -g command, append @testing to the name of each package:

$ npm i -g @antora/cli@testing @antora/site-generator@testing

If you install packages from package.json using the npm command, use the keyword testing as the version for each entry:

"@antora/cli": "testing",
"@antora/site-generator": "testing",

Once install, you can run Antora in the normal way.

Alternately, you can use the exact version of the prerelease (e.g., 3.0.0-alpha.7) in place of the testing keyword.

For more detailed instructions for how to install a prerelease, refer to the installation guide, then switch to the prerelease version.

Continuous Integration

Both the linter and the test suite are run in a continuous integration (CI) environment on every commit to the main branch and on every merge request. A merge request cannot be merged unless the CI pipeline succeeds.

The CI pipeline is run in the GitLab CI environment using the node:12 docker image. The pipeline consists of the following stages:

  • .pre

    • lint

  • test

These stages, as well as any global configuration settings, are defined in the .gitlab-ci.yml file at the root of the project. The CI pipeline essentially boils down to these three commands:

  • npm i

  • npm run lint

  • npm test (or npm run coverage)

You can view the results of the pipelines on the pipelines dashboard.

Skip the CI Pipeline

If you need to make a change to the repository without triggering the CI pipeline, add [skip ci] to the end of your last commit message. For example:

fix typo in README [skip ci]

This flag is reserved for small, non-software changes, as suggested by the example.

Develop with Docker

After installing Docker, copy the Dockerfile below to a new folder (to limit the build context). The Dockerfile uses the most recent version of Ubuntu.

Note
The instructions below are based on linux and have not been tested on other platforms. It assumes your user id is 1000 (check from command line using id -u). If not, the Dockerfile below should be adjusted.
FROM ubuntu:latest

# to allow sourcing of nvm environment scripts
SHELL ["/bin/bash", "-c"]

RUN apt-get update && apt-get install -y \
      curl \
      git \
    && apt-get -y autoclean

RUN groupadd node \
    && useradd -m -u 1000 -g node node # create user as part of node group with home directory

USER node

ENV NVM_DIR "/home/node/.nvm"
ENV NODE_VERSION 12.18.4

RUN mkdir $NVM_DIR \
    && curl --silent -o- "https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh" | bash \
    && source $NVM_DIR/nvm.sh \
    && nvm install $NODE_VERSION \
    && nvm alias default $NODE_VERSION \
    && nvm use default

ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH

RUN cd $HOME \
    && git clone https://gitlab.com/antora/antora \
    && cd "$(basename "$_")" \
    && npm i # install packages

WORKDIR /home/node/antora

CMD ["bash"]

To build the image use

$ docker build --no-cache -t antora-my-dev:latest .

Now to run a bash console in the container use

$ docker run -it antora-my-dev bash
node@bcb6b82c8224:~/antora$

You now have a development environment! You may use e.g. npm run build as described previously.

Develop from a host machine

If you want to run tests within a container when editing code from a host machine, you may wish to share the code between the container and the host.

However Docker intentionally disallows mounting from the container to the host because it breaks container portability. For the sake of development, we can work around this:

  1. run a container

    $ docker run --name dev01 -it antora-my-dev bash
    node@bcb6b82c8224:~/antora$
  2. transfer data from the container to the host. In another terminal window:

    $ docker cp dev01:/home/node/antora antora
  3. exit the first terminal window (by typing exit in the bash console) and start a new container with the bind mount for the data from the host to the container:

    $ docker run -it --mount type=bind,source=$(pwd)/antora,destination=/home/node/antora antora-my-dev bash

The antora folder on the host machine can now be opened for development.

To restart the development environment, execute the command described in the 3rd step above from the working folder.

Project Maintainers

The project maintainers are responsible for:

  • managing organization and project permissions

  • managing the community and code of conduct

  • setting ADR statuses

  • merging requests into the main branch

  • managing and releasing the pipeline

Merge Request Review and Approval Guidelines

Each merge request is assigned at least one reviewer. The reviewer is responsible for making sure the MR meets the project and issue criteria, for answering questions the contributor may have regarding the MR, and for suggesting ways the MR can be improved if necessary.

The MR should not be approved if:

  • there was no agreement about what change to make in the linked issue

  • it fails the CI pipeline

  • it doesn’t meet the project’s workflow, code, test or documentation requirements

  • it doesn’t meet the acceptance criteria of its associated issue

If the MR needs to be modified, notify the contributor and add helpful information to the MR or the issue. Once the contributor has modified the MR, evaluate it again.

When the MR meets the project and issue criteria, it can be merged into the main branch. When the branch is ready to be merged into the main branch:

  • Rebase the MR if necessary.

  • Modify the commit message(s) if necessary.

  • Check remove source branch.

  • Don’t squash the commits, except in especially messy-weird situations.

    • The maintainer only guarantees to preserve the original work in the MR.

  • Modify the default merge commit message; it should only contain two lines.

    • The first line should specify the merge number.

    • The second line should be the MR subject submitted by the contributor. For example:

      merge !46
      
      resolves #59 configure lerna and npm workspaces
  • Press Merge.