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

changelogs converted #4702

Closed
wants to merge 2 commits into from
Closed

Conversation

halkeye
Copy link
Member

@halkeye halkeye commented Nov 8, 2021

Specifically @timja as release master

Note:
weekly.yaml is indented by 2 spaces, not sure why, but stuck with convention

Added via - found the right line in vim, then :r! the command below.

node convertChangelogStable2.mjs ./content/_partials/changelog-old.html | sed -e 's/^/  /'
node convertChangelogStable2.mjs ./content/_partials/changelog-stable.html

Script (not in commit message this time):

/*
 * Converts https://github.com/jenkins-infra/jenkins.io/blob/master/content/_partials/changelog-stable.html which is a bunch of html4
 * to structured yaml like https://github.com/jenkins-infra/jenkins.io/blob/master/content/_data/changelogs/lts.yml
 */
import YAML from 'yaml';
import fs from 'fs';
import cheerio from 'cheerio';

let releases = [];
const $ = cheerio.load(fs.readFileSync(process.argv.slice(2)[0]).toString().replace(/<h4/g, '<h3').replace(/<\/h4/g, '</h3'));

const machineVersion = (version) => {
    const padArrayEnd = (arr, len, padding) => {
        return arr.concat(Array(len - arr.length).fill(padding));
    }
    // make sure the version has 3 parts and 5 length (just in case)
    // so 1.2.3 and 1.2 sort right
    // 2.29 => 00002_00029_00000
    // 2.290 => 00002_00290_00000
    return padArrayEnd(version.split('.'), 3, 0).map(val => val.toString().padStart(5, "0")).join("_");
}


let $node = $('h3:first')
while (1) {
    let tagName = null;
    try {tagName = $node.prop("tagName")} catch (e) {break;}

    if ($node.is('h3')) {
        const release = {
            version: $node.attr('id')?.replace('v', ''),
            changes: [],
        }
        if (!release.version) {
            "content/_data/changelogs/weekly.yml"
            release.version = $node.text().replace("What's new in ", '');
        }
        const versionMatches = $node.text().match(/\b([0-9.]+)\b/)
        if (versionMatches) {
            release.version = versionMatches[1]
        }
        const dateMatches = $node.text().match(/\((\d+)[-\/](\d+)[-\/](\d+)\)/)
        if (dateMatches) {
            release.date = `${dateMatches[1]}-${dateMatches[2]}-${dateMatches[3]}`;
        }
        releases.push(release);
    } else if ($node.is('div') || $node.is('p')) {
        const release = releases[releases.length - 1];
        const text = $node.find('strong').text().trim()
        if (text.match(/Changes from [0-9\.]+/)) {
            release.lts_predecessor = text.match(/Changes from ([0-9\.]+)/)[1];
        } else if (text.match(/No changes compared to [0-9\.]+/)) {
            release.lts_predecessor = text.match(/No changes compared to ([0-9\.]+)/)[1];
        } else if (text.match(/Notable changes since [0-9\.]+/)) {
            release.lts_baseline = text.match(/Notable changes since ([0-9\.]+)/)[1];
            release.lts_changes = []
        } else {
            release.banner = $node.prop('innerHTML').trim()
        }
    } else if ($node.is('ul')) {
        $node.find('li').each(function (_, elm) {
            const $elm = $(elm)
            const release = releases[releases.length - 1];
            const change = {
                type: $elm.attr('class'),
                message: '',
            }
            release[release.lts_changes ? 'lts_changes' : 'changes'].push(change)
            $elm.find('a[href^=https://issues.jenkins.io/browse/]').each(function (_, a) {
                const $a = $(a);
                const issueId = $a.text().match(/(\d+)/)[1]
                if (!change.references) {change.references = []}
                change.references.push({issue: parseInt(issueId.trim(), 10)})
                $a.remove();
            })
            $elm.find('a[href^=https://github.com/jenkinsci/jenkins/pull/]').each(function (_, a) {
                const $a = $(a);
                const pullId = $a.text().match(/(\d+)/)[1]
                if (!change.references) {change.references = []}
                change.references.push({pull: parseInt(pullId.trim(), 10)})
                $a.remove();
            })
            $elm.find('a[href^=https://jenkins.io]').each(function (_, a) {
                const $a = $(a);
                if (!change.references) {change.references = []}
                change.references.push({url: $a.prop('href'), title: $a.text().trim()})
                $a.remove();
            })
            change.message = (change.message + $elm.html())
                .replace(/\((\s|and|,)*/gm, '(') // clean up any ( junk
                .trim()
        })
    } else {
        console.log(tagName, $node.attr());
    }
    $node = $node.next()
}
const changeToYamlNode = (change) => {
    const changeNode = YAML.createNode({});
    if (change.type) {
        changeNode.add({key: 'type', 'value': change.type})
    }
    changeNode.add({key: 'message', 'value': change.message.replace(/\(\s*\)/g, '').split("\n").map(m => m.trim()).filter(Boolean).join("\n")})
    if (change.references) {
        changeNode.add({key: 'references', 'value': change.references})
    }
    return changeNode;
}
const doc = releases.sort((a, b) => machineVersion(a.version).localeCompare(machineVersion(b.version))).map(release => {
    const node = YAML.createNode({version: release.version})
    // do it this way so we control order and don't have nulls
    if (release.date) {
        node.add({key: 'date', value: release.date});
    }
    if (release.lts_predecessor) {
        node.add({key: 'lts_predecessor', value: release.lts_predecessor});
    }
    if (release.lts_baseline) {
        node.add({key: 'lts_baseline', value: release.lts_baseline});
    }
    if (release.lts_changes) {
        node.add({key: 'lts_changes', value: release.lts_changes.map(changeToYamlNode)})
    }
    if (release.changes) {
        node.add({key: 'changes', value: release.changes.map(changeToYamlNode)})
    }
    return node;
})

console.log(YAML.stringify(doc).trim())

@halkeye halkeye requested a review from a team as a code owner November 8, 2021 03:05
@probot-autolabeler probot-autolabeler bot added the changelog Jenkins changelogs label Nov 8, 2021
@halkeye
Copy link
Member Author

halkeye commented Nov 8, 2021

oh cool we style kbd (also i learned its a tag)
image

@halkeye
Copy link
Member Author

halkeye commented Nov 8, 2021

stable looks good, no bad data before it started
image

old has missing dates and stuff, changes don't have a type.
image

drat just noticed that it doesn't handle a couple reference links properly. I'll go back and fix them

@timja
Copy link
Member

timja commented Nov 8, 2021

Weekly changelog is updated via a script which will reformat the file every time it’s run

@halkeye
Copy link
Member Author

halkeye commented Nov 8, 2021

Yea i took a peek at that. I don't know why it's one level in. Top level should have 0 spaces but apparently it's fine as long as it's consistent

@halkeye
Copy link
Member Author

halkeye commented Nov 8, 2021

I'll go back and fix them

Btw I did fix the script and the output. I should be able to regenerate the pr if it ever conflicts

@timja
Copy link
Member

timja commented Nov 8, 2021

Hmm this makes the file even longer than before =/.

Its already a bit of a pain to edit and browsers can struggle with it, along with insane scrolling.
I just tried with the file, and browser was ok but I couldn't find a way to quickly get to the bottom, I scrolled for awhile and gave up.

Could we archive it in some way while still having it available?

@halkeye
Copy link
Member Author

halkeye commented Nov 8, 2021

My goal is to try and unify as much legacy and one off data into consistent machine parsible files.

Could easily move the 1x stuff to another file, especially if we don't even bother to render it. It's neat from a historical point of view but 20 year old versions are it super useful.

@timja
Copy link
Member

timja commented Nov 8, 2021

I think it would be good to archive 1.x at least, we could probably do more as well but can we see what that looks like?

Copy link
Contributor

@kwhetstone kwhetstone left a comment

Choose a reason for hiding this comment

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

LGTM

@github-actions github-actions bot added the unresolved-merge-conflict There is a merge conflict with the target branch. label Mar 7, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Mar 7, 2023

Please take a moment and address the merge conflicts of your pull request. Thanks!

@halkeye halkeye closed this Mar 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog Jenkins changelogs unresolved-merge-conflict There is a merge conflict with the target branch.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants