Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add versioning to docs #711

Merged
merged 8 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ on:
push:
branches:
- master
# release branches have names like 0.8.x, 0.9.x, ...
- '[0-9]+.[0-9]+.x'
# At this day, GitHub doesn't support YAML anchors, d'oh!
paths:
- 'docs/**'
Expand Down Expand Up @@ -69,12 +71,15 @@ jobs:
python3 -m pip install -r ./requirements_docs.txt

- name: Build docs website
# this runs on every PR to ensure the docs build is sane, these docs
# won't be published
if: github.event_name == 'pull_request'
run: task docs:build

- name: Deploy
# publish docs only when PR is merged on master
- name: Publish docs
# determine docs version for the commit pushed and publish accordingly using Mike
if: github.event_name == 'push'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
env:
REMOTE: https://x-access-token:${{secrets.GITHUB_TOKEN}}@github.com/${{github.repository}}.git

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An unwanted blank line maybe?

run: python docs/build.py
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ venv
.DS_Store

# Mkdocs
/site/
/public/
/docsgen/arduino-cli
/docs/rpc/*.md
/docs/commands/*.md
/docs/commands/*.md
12 changes: 12 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ tasks:
cmds:
- mkdocs build -s

docs:publish:
desc: Use Mike to build and push versioned docs
deps:
- docs:gen:commands
- docs:gen:protobuf
cmds:
- mike deploy -r {{.DOCS_REMOTE}} {{.DOCS_VERSION}} {{.DOCS_ALIAS}}

docs:serve:
desc: Run documentation website locally
deps:
Expand Down Expand Up @@ -126,3 +134,7 @@ vars:
GOLINTBIN:
sh: go list -f {{"{{"}}".Target{{"}}"}}" golang.org/x/lint/golint
GOLINTFLAGS: "-min_confidence 0.8 -set_exit_status"
# docs versioning
DOCS_VERSION: dev
DOCS_ALIAS: ""
DOCS_REMOTE: "origin"
126 changes: 126 additions & 0 deletions docs/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# This file is part of arduino-cli.

# Copyright 2020 ARDUINO SA (http://www.arduino.cc/)

# This software is released under the GNU General Public License version 3,
# which covers the main part of arduino-cli.
# The terms of this license can be found at:
# https://www.gnu.org/licenses/gpl-3.0.en.html

# You can be released from the requirements of the above licenses by purchasing
# a commercial license. Buying such a license is mandatory if you want to
# modify or otherwise use the software for commercial activities involving the
# Arduino software without disclosing the source code of your own applications.
# To purchase a commercial license, send an email to [email protected].
import os
import sys
import re
import unittest
import subprocess

import semver
from git import Repo


class TestScript(unittest.TestCase):
def test_get_docs_version(self):
ver, alias = get_docs_version("master", [])
self.assertEqual(ver, "dev")
self.assertEqual(alias, "")

release_names = ["1.4.x", "0.13.x"]
ver, alias = get_docs_version("0.13.x", release_names)
self.assertEqual(ver, "0.13")
self.assertEqual(alias, "")
ver, alias = get_docs_version("1.4.x", release_names)
self.assertEqual(ver, "1.4")
self.assertEqual(alias, "latest")

ver, alias = get_docs_version("0.1.x", [])
self.assertIsNone(ver)
self.assertIsNone(alias)


def get_docs_version(ref_name, release_branches):
if ref_name == "master":
return "dev", ""

if ref_name in release_branches:
# if version is latest, add an alias
alias = "latest" if ref_name == release_branches[0] else ""
# strip `.x` suffix from the branch name to get the version: 0.3.x -> 0.3
return ref_name[:-2], alias

return None, None


def get_rel_branch_names(blist):
"""Get the names of the release branches, sorted from newest to older.

Only process remote refs so we're sure to get all of them and clean up the
name so that we have a list of strings like 0.6.x, 0.7.x, ...
"""
pattern = re.compile(r"origin/(\d+\.\d+\.x)")
names = []
for b in blist:
res = pattern.search(b.name)
if res is not None:
names.append(res.group(1))

# Since sorting is stable, first sort by major...
names = sorted(names, key=lambda x: int(x.split(".")[0]), reverse=True)
# ...then by minor
return sorted(names, key=lambda x: int(x.split(".")[1]), reverse=True)


def main(repo_dir):
# Git remote must be set to publish docs
remote = os.environ.get("REMOTE")
if not remote:
print("REMOTE env var must be set to publish, running dry mode")

# Get current repo
repo = Repo(repo_dir)

# Get the list of release branch names
rel_br_names = get_rel_branch_names(repo.refs)

# Deduce docs version from current branch. Use the 'latest' alias if
# version is the most recent
docs_version, alias = get_docs_version(repo.active_branch.name, rel_br_names)
if docs_version is None:
print(
f"Can't get version from current branch '{repo.active_branch}', skip docs generation"
)
return 0

args = [
"task",
"docs:publish",
f"DOCS_REMOTE={remote}",
f"DOCS_VERSION={docs_version}",
f"DOCS_ALIAS={alias}",
]
if remote:
subprocess.run(args, shell=True, check=True, cwd=repo_dir)
else:
print(" ".join(args))

return 0


# Usage:
#
# To run the tests:
# $python build.py test
#
# To run the script (must be run from within the repo tree):
# $python build.py
#
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "test":
unittest.main(argv=[""], exit=False)
sys.exit(0)

here = os.path.dirname(os.path.realpath(__file__))
sys.exit(main(os.path.join(here, "..")))
5 changes: 5 additions & 0 deletions docs/css/version-select.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@media only screen and (max-width:76.1875em) {
#version-selector {
padding: .6rem .8rem;
}
}
50 changes: 50 additions & 0 deletions docs/js/version-select.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
window.addEventListener("DOMContentLoaded", function() {
// This is a bit hacky. Figure out the base URL from a known CSS file the
// template refers to...
var ex = new RegExp("/?assets/fonts/material-icons.css$");
var sheet = document.querySelector('link[href$="material-icons.css"]');

var REL_BASE_URL = sheet.getAttribute("href").replace(ex, "");
var ABS_BASE_URL = sheet.href.replace(ex, "");
var CURRENT_VERSION = ABS_BASE_URL.split("/").pop();

function makeSelect(options, selected) {
var select = document.createElement("select");
select.classList.add("form-control");

options.forEach(function(i) {
var option = new Option(i.text, i.value, undefined,
i.value === selected);
select.add(option);
});

return select;
}

var xhr = new XMLHttpRequest();
xhr.open("GET", REL_BASE_URL + "/../versions.json");
xhr.onload = function() {
var versions = JSON.parse(this.responseText);

var realVersion = versions.find(function(i) {
return i.version === CURRENT_VERSION ||
i.aliases.includes(CURRENT_VERSION);
}).version;

var select = makeSelect(versions.map(function(i) {
return {text: i.title, value: i.version};
}), realVersion);
select.addEventListener("change", function(event) {
window.location.href = REL_BASE_URL + "/../" + this.value;
});

var container = document.createElement("div");
container.id = "version-selector";
container.className = "md-nav__item";
container.appendChild(select);

var sidebar = document.querySelector(".md-nav--primary > .md-nav__list");
sidebar.parentNode.insertBefore(container, sidebar);
};
xhr.send();
});
16 changes: 9 additions & 7 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@ site_url: https://arduino.github.io/arduino-cli/
# Repository
repo_name: arduino/arduino-cli
repo_url: https://github.com/arduino/arduino-cli
edit_uri: ""
edit_uri: ''

# Copyright
copyright: 'Copyright 2020 ARDUINO SA (http://www.arduino.cc/)'

# Configuration
site_dir: public
edit_uri: ""
copyright: Copyright 2020 ARDUINO SA (http://www.arduino.cc/)

# Theme
theme:
Expand Down Expand Up @@ -57,7 +53,7 @@ markdown_extensions:

# Navigation
nav:
- Documentation Home: 'index.md'
- Documentation Home: index.md
- installation.md
- getting-started.md
- CONTRIBUTING.md
Expand Down Expand Up @@ -108,3 +104,9 @@ nav:
- library-specification.md
- platform-specification.md
- package_index.json specification: package_index_json-specification.md

extra_css:
- css/version-select.css

extra_javascript:
- js/version-select.js
6 changes: 4 additions & 2 deletions requirements_docs.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
mkdocs
mkdocs-material
mkdocs<1.2
mkdocs-material<5
mike
gitpython