Skip to content

Commit

Permalink
docs: version selectors synchronization (#18260)
Browse files Browse the repository at this point in the history
* support vNN.x branches

* fetch versions

* update `versions.json` during releases

* trigger rebuilds on Netlify
  • Loading branch information
mdjermanovic committed Apr 4, 2024
1 parent e508800 commit 96607d0
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 99 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/rebuild-docs-sites.yml
@@ -0,0 +1,17 @@
name: Rebuild Docs Sites

on:
push:
branches: [main]
paths:
- 'docs/src/_data/versions.json'

jobs:
rebuild:
name: 'Trigger rebuild on Netlify'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: >
jq -r '.items | map(.branch) | join(",")' docs/src/_data/versions.json
| xargs -I{LIST} curl -X POST -d {} "${{ secrets.NETLIFY_DOCS_BUILD_HOOK }}?trigger_branch={{LIST}}"
74 changes: 72 additions & 2 deletions Makefile.js
Expand Up @@ -272,6 +272,73 @@ function publishSite() {
cd(currentDir);
}

/**
* Determines whether the given version is a prerelease.
* @param {string} version The version to check.
* @returns {boolean} `true` if it is a prerelease, `false` otherwise.
*/
function isPreRelease(version) {
return /[a-z]/u.test(version);
}

/**
* Updates docs/src/_data/versions.json
* @param {string} oldVersion Current version.
* @param {string} newVersion New version to be released.
* @returns {void}
*/
function updateVersions(oldVersion, newVersion) {
echo("Updating ESLint versions list in docs package");

const filePath = path.join(__dirname, "docs", "src", "_data", "versions.json");
const data = require(filePath);
const { items } = data;

const isOldVersionPrerelease = isPreRelease(oldVersion);
const isNewVersionPrerelease = isPreRelease(newVersion);

if (isOldVersionPrerelease) {
if (isNewVersionPrerelease) {

// prerelease -> prerelease. Just update the version.
items.find(item => item.branch === "next").version = newVersion;
} else {

// prerelease -> release. First, update the item for the previous latest version
const latestVersionItem = items.find(item => item.branch === "latest");
const latestVersion = latestVersionItem.version;
const versionBranch = `v${latestVersion.slice(0, latestVersion.indexOf("."))}.x`; // "v8.x", "v9.x", "v10.x" ...

latestVersionItem.branch = versionBranch;
latestVersionItem.path = `/docs/${versionBranch}/`;

// Then, replace the item for the prerelease with a new item for the new latest version
items.splice(items.findIndex(item => item.branch === "next"), 1, {
version: newVersion,
branch: "latest",
path: "/docs/latest/"
});

}
} else {
if (isNewVersionPrerelease) {

// release -> prerelease. Insert an item for the prerelease.
items.splice(1, 0, {
version: newVersion,
branch: "next",
path: "/docs/next/"
});
} else {

// release -> release. Just update the version.
items.find(item => item.branch === "latest").version = newVersion;
}
}

fs.writeFileSync(filePath, `${JSON.stringify(data, null, 4)}\n`);
}

/**
* Updates the changelog, bumps the version number in package.json, creates a local git commit and tag,
* and generates the site in an adjacent `website` folder.
Expand All @@ -280,6 +347,8 @@ function publishSite() {
* @returns {void}
*/
function generateRelease(prereleaseId) {
const oldVersion = require("./package.json").version;

ReleaseOps.generateRelease(prereleaseId);
const releaseInfo = JSON.parse(cat(".eslint-release-info.json"));

Expand All @@ -295,6 +364,8 @@ function generateRelease(prereleaseId) {
docsPackage.version = releaseInfo.version;
fs.writeFileSync(docsPackagePath, `${JSON.stringify(docsPackage, null, 4)}\n`);

updateVersions(oldVersion, releaseInfo.version);

echo("Updating commit with docs data");
exec("git add docs/ && git commit --amend --no-edit");
exec(`git tag -a -f v${releaseInfo.version} -m ${releaseInfo.version}`);
Expand All @@ -308,13 +379,12 @@ function generateRelease(prereleaseId) {
function publishRelease() {
ReleaseOps.publishRelease();
const releaseInfo = JSON.parse(cat(".eslint-release-info.json"));
const isPreRelease = /[a-z]/u.test(releaseInfo.version);

/*
* for a pre-release, push to the "next" branch to trigger docs deploy
* for a release, push to the "latest" branch to trigger docs deploy
*/
if (isPreRelease) {
if (isPreRelease(releaseInfo.version)) {
exec("git push origin HEAD:next -f");
} else {
exec("git push origin HEAD:latest -f");
Expand Down
2 changes: 2 additions & 0 deletions docs/.eleventy.js
Expand Up @@ -44,6 +44,8 @@ module.exports = function(eleventyConfig) {
pathPrefix = "/docs/latest/";
} else if (process.env.BRANCH === "next") {
pathPrefix = "/docs/next/";
} else if (process.env.BRANCH && /^v\d+\.x$/u.test(process.env.BRANCH)) {
pathPrefix = `/docs/${process.env.BRANCH}/`; // `/docs/v8.x/`, `/docs/v9.x/`, `/docs/v10.x/` ...
}

//------------------------------------------------------------------------------
Expand Down
4 changes: 1 addition & 3 deletions docs/src/_data/config.json
@@ -1,5 +1,3 @@
{
"lang": "en",
"version": "8.57.0",
"showNextVersion": true
"lang": "en"
}
32 changes: 0 additions & 32 deletions docs/src/_data/eslintNextVersion.js

This file was deleted.

35 changes: 0 additions & 35 deletions docs/src/_data/eslintVersion.js

This file was deleted.

75 changes: 75 additions & 0 deletions docs/src/_data/eslintVersions.js
@@ -0,0 +1,75 @@
/**
* @fileoverview Data for version selectors
* @author Milos Djermanovic
*/

//-----------------------------------------------------------------------------
// Requirements
//-----------------------------------------------------------------------------

const eleventyFetch = require("@11ty/eleventy-fetch");

//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------

module.exports = async function() {

const thisBranch = process.env.BRANCH;
const thisVersion = require("../../package.json").version;

// Fetch the current list of ESLint versions from the `main` branch on GitHub
const url = "https://raw.githubusercontent.com/eslint/eslint/main/docs/src/_data/versions.json";

const data = await eleventyFetch(url, {
duration: "1d", // Cache for local development. Netlify does not keep this cache and will therefore always fetch from GitHub.
type: "json"
});

const { items } = data;

// For initial commit purpose only
if (items.length === 0) {
const localData = require("./versions.json");
items.push(...localData.items);
}

let foundItemForThisBranch = false;

for (const item of items) {
const isItemForThisBranch = item.branch === thisBranch;

foundItemForThisBranch ||= isItemForThisBranch;

const isNumberVersion = /^\d/.test(item.version); // `false` for HEAD

if (isNumberVersion) {

// Make sure the version is correct
if (isItemForThisBranch) {
item.version = thisVersion;
}

item.display = `v${item.version}`;
} else {
item.display = item.version;
}

if (isItemForThisBranch) {
item.selected = true;
}
}

// Add an empty item if this is not a production branch
if (!foundItemForThisBranch) {
items.unshift({
version: "",
branch: "",
display: "",
path: "",
selected: true
})
}

return data;
}
15 changes: 15 additions & 0 deletions docs/src/_data/versions.json
@@ -1,4 +1,19 @@
{
"items": [
{
"version": "HEAD",
"branch": "main",
"path": "/docs/head/"
},
{
"version": "9.0.0-rc.0",
"branch": "next",
"path": "/docs/next/"
},
{
"version": "8.57.0",
"branch": "latest",
"path": "/docs/latest/"
}
]
}
12 changes: 2 additions & 10 deletions docs/src/_includes/components/nav-version-switcher.html
Expand Up @@ -12,16 +12,8 @@
<span class="label__text">Version</span>
</label>
<select name="version selector" id="nav-version-select" aria-describedby="nav-version-infobox" class="c-custom-select switcher__select auto-switcher">
<option value="HEAD" data-url="/docs/head/" {% if HEAD %}selected{% endif %}>HEAD</option>
{% if config.showNextVersion == true %}
<option value="{{ eslintNextVersion }}" data-url="/docs/next/" {% if GIT_BRANCH == "next" %}selected{% endif %}>v{{ eslintNextVersion }}</option>
{% endif %}
<option value="{{ eslintVersion }}" data-url="/docs/latest/" {% if GIT_BRANCH == "latest" %}selected{% endif %}>v{{ eslintVersion }}</option>
{% for version in versions.items %}
<option value="{{ version.number }}"
data-url="{{ version.url }}">
v{{ version.number }}
</option>
{% for item in eslintVersions.items %}
<option value="{{ item.version }}" data-url="{{ item.path }}" {% if item.selected %}selected{% endif %}>{{ item.display }}</option>
{% endfor %}
</select>
</div>
Expand Down
12 changes: 2 additions & 10 deletions docs/src/_includes/components/version-switcher.html
Expand Up @@ -12,16 +12,8 @@
<span class="label__text">Version</span>
</label>
<select name="version selector" id="version-select" aria-describedby="version-infobox" class="c-custom-select switcher__select auto-switcher">
<option value="HEAD" data-url="/docs/head/" {% if HEAD %}selected{% endif %}>HEAD</option>
{% if config.showNextVersion == true %}
<option value="{{ eslintNextVersion }}" data-url="/docs/next/" {% if GIT_BRANCH=="next" %}selected{% endif %}>v{{ eslintNextVersion }}</option>
{% endif %}
<option value="{{ eslintVersion }}" data-url="/docs/latest/" {% if GIT_BRANCH == "latest" %}selected{% endif %}>v{{ eslintVersion }}</option>
{% for version in versions.items %}
<option value="{{ version.number }}"
data-url="{{ version.url }}">
v{{ version.number }}
</option>
{% for item in eslintVersions.items %}
<option value="{{ item.version }}" data-url="{{ item.path }}" {% if item.selected %}selected{% endif %}>{{ item.display }}</option>
{% endfor %}
</select>
</div>
Expand Down
9 changes: 2 additions & 7 deletions docs/src/_includes/partials/versions-list.html
@@ -1,10 +1,5 @@
<ul class="versions-list">
<li><a href="/docs/head/" {% if HEAD %} data-current="true" {% endif %}>HEAD</a></li>
{% if config.showNextVersion == true %}
<li><a href="/docs/next/" {% if GIT_BRANCH == "next" %} data-current="true" {% endif %}>v{{ eslintNextVersion }}</a></li>
{% endif %}
<li><a href="/docs/latest/" {% if GIT_BRANCH == "latest" %} data-current="true" {% endif %}>v{{ eslintVersion }}</a></li>
{%- for version in versions.items -%}
<li><a href="{{ version.url }}">v{{ version.number }}</a></li>
{% for item in eslintVersions.items %}
<li><a href="{{ item.path }}" {% if item.selected %} data-current="true" {% endif %}>{{ item.display }}</a></li>
{%- endfor -%}
</ul>

0 comments on commit 96607d0

Please sign in to comment.