diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..38edc225e1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,193 @@ +# To trigger the workflow, tag sources and push +# git tag -a v1.13.1 -m "version 1.13.1" +# to tag old revision: +# git tag -a v1.13.0-beta.1 2112766 -m "version 1.13.0-beta.1" +# git tag -a v1.13.0 f87090b -m "version 1.13.0" +# git push --tags +name: Release + +on: + workflow_dispatch: + push: + tags: + - v* + paths-ignore: + - ".github/**" + - "**/*.md" + +jobs: + lint_build_test: + name: Build, Lint and Test + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Use Node.js 10 x64 + uses: actions/setup-node@v2 + with: + node-version: 10 + architecture: x64 + registry-url: 'https://registry.npmjs.org' + + - name: Install + run: yarn install --frozen-lockfile + + - name: Validate version tag + run: | + node build\version-utils.js validate-latest-tag + + - name: Prepare + id: prepare + run: | + $LatestVersionTag=$(node build\version-utils.js latest-version-tag) + echo "Latest version tag=$LatestVersionTag" + echo "::set-output name=version_tag::$LatestVersionTag" + + - name: Ensure correct revision + run: | + git checkout tags/${{ steps.prepare.outputs.version_tag }} + + - name: Lint + run: | + yarn run lint + yarn run lint-docs + yarn run lint-css + + - name: Test + run: | + yarn run test-flow + yarn run test-unit + yarn run test-render + yarn run test-query + yarn run test-expressions + + release: + name: Release + runs-on: ubuntu-latest + needs: lint_build_test + defaults: + run: + shell: bash + steps: + + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Use Node.js 10 x64 + uses: actions/setup-node@v2 + with: + node-version: 10 + architecture: x64 + registry-url: 'https://registry.npmjs.org' + + - name: Install + run: yarn install --frozen-lockfile + + - name: Validate version tag + run: | + build/version-utils.js validate-latest-tag + + - name: Prepare release + id: prepare_release + run: | + echo ::set-output name=version_tag::$( build/version-utils.js latest-version-tag) + echo ::set-output name=version::$( build/version-utils.js version-from-tags) + echo ::set-output name=release_type::$( build/version-utils.js version-type ) + + - name: Ensure correct revision + run: | + git checkout tags/${{ steps.prepare_release.outputs.version_tag }} + + - name: Build + run: | + yarn run build-prod-min + yarn run build-css + + - name: Create Archive + run: | + zip -r dist dist + + - name: Build Release Notes + id: release_notes + if: ${{ steps.prepare_release.outputs.release_type == 'regular' }} + run: | + RELEASE_NOTES_PATH="${PWD}/release_notes.txt" + ./build/release-notes.js > ${RELEASE_NOTES_PATH} + echo ::set-output name=release_notes::${RELEASE_NOTES_PATH} + + - name: Create GitHub Release (regular) + id: create_regular_release + if: ${{ steps.prepare_release.outputs.release_type == 'regular' }} + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.prepare_release.outputs.version_tag }} + release_name: ${{steps.prepare_release.outputs.version_tag }} + body_path: ${{ steps.release_notes.outputs.release_notes }} + draft: false + prerelease: false + + - name: Upload GitHub Release Assets (regular) + if: ${{ steps.prepare_release.outputs.release_type == 'regular' }} + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_regular_release.outputs.upload_url }} + asset_path: ./dist.zip + asset_name: dist.zip + asset_content_type: application/zip + + - name: Create GitHub Release (prerelease) + id: create_prerelease + if: ${{ steps.prepare_release.outputs.release_type == 'prerelease' }} + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.prepare_release.outputs.version_tag }} + release_name: ${{steps.prepare_release.outputs.version_tag }} + draft: false + prerelease: true + + - name: Upload GitHub Release Assets (prerelease) + uses: actions/upload-release-asset@v1 + if: ${{ steps.prepare_release.outputs.release_type == 'prerelease' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_prerelease.outputs.upload_url }} + asset_path: ./dist.zip + asset_name: dist.zip + asset_content_type: application/zip + + - name: Clean up + if: ${{ steps.prepare_release.outputs.release_type == 'regular' }} + run: | + rm -f ${{ steps.prepare_release.outputs.release_notes }} + + - name: Update NPM Package Version + run: | + yarn version --non-interactive --no-git-tag-version --new-version ${{ steps.prepare_release.outputs.version }} + + - name: Commit & Push updated version + run: | + git add package.json + if [[ -n "$(git status --porcelain)" ]]; then + git config --local user.email "maplibre@noreply.maplibre.org" + git config --local user.name "MapLibre" + git commit -m "Version Bump" + git push origin HEAD:main + else + echo "no changes"; + fi + - name: Publish NPM package + run: | + yarn publish --non-interactive + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + diff --git a/CHANGELOG.md b/CHANGELOG.md index 66ca9e5db3..94b6e7c164 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,30 @@ -## maplibre-gl-js 1.13.0 +## main + +### Features and improvements + +- Add new stuff here + +### 🐞 Bug fixes + +- Add fixed bugs here + +## 1.14.0 + +### Features and improvements + +- New logo ### 🐞 Bug fixes -- Fix a bug where mapbox-gl-js is no longer licensed as open source, but we owe immeasurable gratitude to Mapbox for releasing all their initial code to the community under BSD-3 license.``` +- Rename SVGs mapboxgl-ctrl-*.svg to maplibregl (#85) +- fix ImageSource not working in FF/Safari (#87) +- Update HTML debug files to use MapLibre in titles (#84) +- fix CI checksize job to use maplibre name (#86) +- Move output files from mapbox.* to maplibre.* (#75) +- Remove mapbox specifics and branding from .github (#64) +- Fix a bug where mapbox-gl-js is no longer licensed as open source, but we owe immeasurable gratitude to Mapbox for releasing all their initial code to the community under BSD-3 license. -## mapbox-gl-js 1.13.0 +## 1.13.0 ### ✨ Features and improvements diff --git a/build/diff-tarball.js b/build/diff-tarball.js index f868437be1..b3f2500f93 100644 --- a/build/diff-tarball.js +++ b/build/diff-tarball.js @@ -5,7 +5,13 @@ npmContent('maplibre-gl').then(function(last_version_files) { packlist({ path: '.' }).then(function(new_version_files) { new_version_files = new_version_files.map(file => file.replace(/\/\/+/g, '/')); let diff_new = new_version_files.filter(x => !last_version_files.includes(x)); - let diff_last = last_version_files.filter(x => !new_version_files.includes(x)); + + // excludes folder names which caused this script + // to fail with message: xx files are about to be deleted in the new tarball + // i.e. src/ui was reported but src/ui/anchor.js, src/ui/camera.js, etc are included indeed + let diff_last = last_version_files + .filter(x => !new_version_files.includes(x) && !new_version_files.some(y => y.startsWith(x))); + console.log(`${diff_new.length} files are about to be added in the new tarball`) diff_new.forEach(file => { console.log('+', file); @@ -14,5 +20,9 @@ npmContent('maplibre-gl').then(function(last_version_files) { diff_last.forEach(file => { console.log('-', file); }); + + if (diff_new.length > 0 || diff_last.length > 0) { + console.log('\x1b[31m%s\x1b[0m', 'Number of files in tarball will change!'); + } }); }); diff --git a/build/release-notes.js b/build/release-notes.js new file mode 100755 index 0000000000..365c03f0b8 --- /dev/null +++ b/build/release-notes.js @@ -0,0 +1,73 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const execSync = require('child_process').execSync; +const ejs = require('ejs'); +const _ = require('lodash'); +const semver = require('semver'); + +const changelogPath = 'CHANGELOG.md'; +const changelog = fs.readFileSync(changelogPath, 'utf8'); + +let currentVersion = execSync('git describe --tags --match=v*.*.* --abbrev=0') + .toString() + .trim() + .replace('v', ''); + +let gitTags = execSync('git tag --list v*.*.*') + .toString() + .split('\n') + .map(function(tag) { + tag = tag.replace('v', '').trim(); + return semver.clean(tag); + }); +let previousVersion = semver.maxSatisfying(gitTags, "<" + currentVersion, { includePrerelease: false }); + +/* + Parse the raw changelog text and split it into individual releases. + + This regular expression: + - Matches lines starting with "## x.x.x". + - Groups the version number. + - Skips the (optional) release date. + - Groups the changelog content. + - Ends when another "## x.x.x" is found. +*/ +const regex = /^## (\d+\.\d+\.\d+).*?\n(.+?)(?=\n^## \d+\.\d+\.\d+.*?\n)/gms; + +let releaseNotes = []; +// eslint-disable-next-line no-cond-assign +while (match = regex.exec(changelog)) { + releaseNotes.push({ + 'version': match[1], + 'changelog': match[2].trim(), + }); +} + +/* + Match the current tag with the most appropriate release notes. +*/ +const versionsInReleaseNotes = _.map(releaseNotes, 'version'); +const bestReleaseNotesForCurrentVersion = semver.minSatisfying(versionsInReleaseNotes, ">=" + currentVersion); +const currentReleaseNotes = _.find(releaseNotes, { version: bestReleaseNotesForCurrentVersion }); + +if (!currentReleaseNotes) { + console.error('Could not find a release section satisfying %s in %s — did you forget to rename the "main" section to %s?', currentVersion, changelogPath, currentVersion.split("-")[0]); + process.exit(1); // eslint-disable-line no-process-exit +} + +/* + Fill and print the release notes template. +*/ +let templatedReleaseNotes; + +templatedReleaseNotes = ejs.render(fs.readFileSync('build/release-notes.md.ejs', 'utf8'), { + 'CURRENTVERSION': currentVersion, + 'PREVIOUSVERSION': previousVersion, + 'CHANGELOG': currentReleaseNotes.changelog, + 'isPrerelease': semver.prerelease(currentVersion) +}); +templatedReleaseNotes = templatedReleaseNotes.trimEnd(); + +// eslint-disable-next-line eol-last +process.stdout.write(templatedReleaseNotes); \ No newline at end of file diff --git a/build/release-notes.md.ejs b/build/release-notes.md.ejs new file mode 100644 index 0000000000..22b5db961b --- /dev/null +++ b/build/release-notes.md.ejs @@ -0,0 +1,8 @@ +https://github.com/maplibre/maplibre-gl-js +[Changes](https://github.com/maplibre/maplibre-gl-js/compare/v<%-PREVIOUSVERSION%>...v<%-CURRENTVERSION%>) since [MapLibre GL JS v<%-PREVIOUSVERSION%>](https://github.com/maplibre/releases/tag/v<%-PREVIOUSVERSION%>): + +<%-CHANGELOG-%> + +<% if (isPrerelease) { %> +Pre-release version +<% } -%> \ No newline at end of file diff --git a/build/version-utils.js b/build/version-utils.js new file mode 100755 index 0000000000..5f5c1bf9cf --- /dev/null +++ b/build/version-utils.js @@ -0,0 +1,72 @@ +#!/usr/bin/env node + +const execSync = require('child_process').execSync; +const semver = require('semver'); + +const args = process.argv.slice(2); + +function latestVersionTag() { + const latestVersionTag = execSync('git describe --tags --match=v*.*.* --abbrev=0') + .toString() + .trim(); + return latestVersionTag; +} + +function latestFromTags() { + const currentVersion = execSync('git describe --tags --match=v*.*.* --abbrev=0') + .toString() + .trim() + .replace(/^v/, ''); + return currentVersion; +} + +function listTags() { + let gitTags = execSync('git log --no-walk --tags --pretty=format:%S') + .toString() + .split('\n') + .reduce((filtered, tag) => { + const parsed = semver.valid(tag.replace(/^v/, '')); + if (parsed) { + filtered.push(parsed); + } + return filtered; + }, []); + return gitTags; +} + +switch (args[0]) { + case 'list-version-tags': + console.log(listTags().join("\n")); + break; + case 'version-type': + if (semver.prerelease(latestFromTags())) { + console.log("prerelease"); + } else { + console.log("regular"); + } + break; + case 'latest-version-tag': + console.log(latestVersionTag()); + break; + case 'version-from-tags': + console.log(latestFromTags()); + break; + case 'validate-latest-tag': + const tags = listTags(); + if (tags && tags.length > 1) { + const current = tags[0]; + const previous = tags[1]; + if (semver.gt(current, previous)) { + console.log(`valid version tag current=${current}, previous=${previous}`); + } else { + console.log(`invalid - latest tag must contain greater version than previous one (current=${current}, previous=${previous})`); + process.exit(1); // eslint-disable-line no-process-exit + } + } else { + console.log("valid"); + } + break; + default: + console.log('Unknown command.'); + break; +} diff --git a/package.json b/package.json index c33db69445..72c73e717b 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "json-stringify-pretty-compact": "^2.0.0", "jsonwebtoken": "^8.3.0", "list-npm-contents": "^1.0.2", + "lodash": "^4.17.19", "lodash.template": "^4.5.0", "mapbox-gl-styles": "^2.0.2", "mock-geolocation": "^1.0.11", @@ -105,6 +106,7 @@ "rollup-plugin-terser": "^5.1.2", "rollup-plugin-unassert": "^0.3.0", "selenium-webdriver": "^4.0.0-alpha.5", + "semver": "^5.5.0", "shuffle-seed": "^1.1.6", "sinon": "^7.3.2", "source-map-explorer": "^2.5.1", @@ -144,7 +146,7 @@ "start-tests": "run-p build-token watch-css watch-query start-server", "start-bench": "run-p build-token watch-benchmarks start-server", "start-release": "run-s build-token build-prod-min build-css print-release-url start-server", - "diff-tarball": "cross-env build/run-node build/diff-tarball && echo \"Please confirm the above is correct [y/n]? \"; read answer; if [ \"$answer\" = \"${answer#[Yy]}\" ]; then false; fi", + "diff-tarball": "cross-env build/run-node build/diff-tarball", "prepare-publish": "git clean -fdx && yarn install", "lint": "eslint --cache --ignore-path .gitignore src test bench build debug/*.html", "lint-docs": "documentation lint src/index.js", diff --git a/test/ignores.json b/test/ignores.json index 0501676a32..c4db1cd793 100644 --- a/test/ignores.json +++ b/test/ignores.json @@ -27,5 +27,8 @@ "render-tests/icon-text-fit/text-variable-anchor-tile-map-mode": "skip - mapbox-gl-js does not support tile-mode", "render-tests/text-variable-anchor/all-anchors-labels-priority-tile-map-mode": "skip - mapbox-gl-js does not support tile-mode", "render-tests/fill-extrusion-pattern/1.5x-on-1x-add-image": "skip - non-deterministic on AMD graphics cards", - "render-tests/text-variable-anchor/avoid-edges-tile-map-mode": "skip - mapbox-gl-js does not support tile-mode" + "render-tests/text-variable-anchor/avoid-edges-tile-map-mode": "skip - mapbox-gl-js does not support tile-mode", + "render-tests/extent/1024-symbol": "skip - MapLibre 1.13.1 baseline", + "render-tests/icon-text-fit/enlargen-both": "skip - MapLibre 1.13.1 baseline", + "render-tests/line-dasharray/case/round": "skip - MapLibre 1.13.1 baseline" } diff --git a/yarn.lock b/yarn.lock index 2eaface568..247e402c6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6671,6 +6671,11 @@ lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.19: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + lodash@^4.17.20: version "4.17.20" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"