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

chore(ci): add release pipeline and documentation #508

Merged
merged 17 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
47 changes: 47 additions & 0 deletions .github/actions/bump-manifest-version.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// @ts-check
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-console */
sidvishnoi marked this conversation as resolved.
Show resolved Hide resolved
const fs = require("node:fs/promises");

/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */
module.exports = async ({ core }) => {
const manifestPath = "./src/manifest.json";
const manifestFile = await fs.readFile(manifestPath, "utf8");
const manifest = JSON.parse(manifestFile);
/**@type {string} */
const existingVersion = manifest.version;

const bumpType = /** @type {BumpType} */ (process.env.INPUT_VERSION);
if (!bumpType) {
throw new Error("Missing bump type");
}

const version = bumpVersion(existingVersion, bumpType).join(".");

console.log({ existingVersion, bumpType, version });

manifest.version = version;
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
core.setOutput("version", version);
};

/**
* @typedef {'build' | 'patch' | 'minor'} BumpType
* @param {string} existingVersion
* @param {BumpType} type
* @return {[major: number, minor: number, patch: number, build: number]}
*/
function bumpVersion(existingVersion, type) {
const [major, minor, patch, build] = existingVersion.split(".").map(Number);

switch (type) {
case "build":
return [major, minor, patch, build + 1];
case "patch":
return [major, minor, patch + 1, 0];
case "minor":
return [major, minor + 1, 0, 0];
default:
throw new Error("Unknown bump type: " + type);
}
}
52 changes: 52 additions & 0 deletions .github/workflows/bump-manifest-version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Bump Manifest Version

on:
workflow_dispatch:
inputs:
version:
description: "Version to bump to"
required: true
default: "build"
type: choice
options:
- build
- patch
- minor

permissions:
contents: write
pull-requests: write

jobs:
bump-version:
name: Bump version
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with: { node-version-file: ".nvmrc" }

- name: Bump version
id: bump
uses: actions/github-script@v7
env:
INPUT_VERSION: ${{ github.event.inputs.version }}
with:
script: |
const script = require('./.github/actions/bump-manifest-version.cjs')
await script({ github, context, core })

- name: Create pull request
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "chore: release version ${{ steps.bump.outputs.version }}"
title: "chore: release version ${{ steps.bump.outputs.version }}"
body: |
Bump extension version to ${{ steps.bump.outputs.version }}
branch: preview/${{ steps.bump.outputs.version }}
labels: preview

85 changes: 85 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Web Monetization Extension Release Pipeline

Two channels of the extensions will be maintained:

- Preview
- Stable

A separate Nightly release channel will be available via GitHub releases (without publishing to stores).

## Extension versioning

Web extensions do not follow SEMVER. The version string consists of 1 to 4 numbers separated by dots, for example, 1.2.3.4 (major.minor.patch.build). This is essentially SEMVER but with an additional build number, but does not support the alpha, beta or other suffixes.

### Major version bump

A major version bump (2.0.0.0) signifies the start of a block of product features.

Before the extension is available first on the Stable channel, we only increase the build number (2.0.0.x) when publishing to the Preview channel. After that, we follow SEMVER (2.x.y).

### Minor version bump

New features and enhancements will be released under a minor version bump.

### Patch version bump

Bug fixes, performance and small updates will be released under a patch version bump.

### Build version bump

The build version bump should only happen when starting the work on a new major version. Once a major version (e.g. v1) goes into maintenance mode, the extension major version is bumped to 2.0.0.0. Until the new major version is made available on the Stable channel, only build number should be incremented.

Multiple "build" version bumps can be made available in the Preview channel. e.g. we can have 2.0.0.1, 2.0.0.2, ..., 2.0.0.90 in the Preview channel before we make it available in the Stable channel.

Note: When the new major version is going to be available in the Stable channel, it will have the last published version as in the Preview channel (i.e. the first Stable channel build could be 2.0.0.90, not necessarily 2.0.0 or 2.0.1).

## Nightly

The Nightly version will be built every day at 12AM UTC and it will be added to GitHub releases with the tag nightly.

Nightly releases will correspond to the latest commit in the main branch of the repository at the time of the build. The tag reference will get updated on every release (rolling tags). Whenever a new release is happening, the previous one gets deleted first.

### Versioning for the Nightly build

On every action run, the workflow will update the following properties in the manifest:

- `version`: will be set to the current date in `YYYY.M.D` format (note: not `YYYY.MM.DD` as we cannot have zero as prefix in these numbers)
- `version_name`: will be set to `Nightly YYYY.M.D ({short_commit_hash})`

### Release Artifacts:

Artifacts follow the name: `nightly-{browser}-{version}.zip`, e.g. `nightly-chrome-2024.7.13.zip`, `nightly-edge-2024.7.13.zip`, `nightly-firefox-2024.7.13.zip`

## Preview

The Preview version represents a release candidate on the main branch. They are less stable than the Stable version.

Releases are triggered manually (via GitHub Actions), and can have a minor/patch/build version bump.

Once a new development stage starts for a new major version and we start publishing it to the Preview channel, we will not be able to push an older version to the Preview channel - they will only be available in GitHub. But the releases for the older version are to be promoted to Stable immediately.

### Release Artifacts:

Artifacts follow the name `preview-{browser}-{version}.zip`, e.g. `preview-chrome-1.0.4.zip`, `preview-edge-2.0.0.12.zip`, `preview-firefox-2.1.1.zip`

## Release

Some of the releases from the Preview channel (that are considered stable enough) are **promoted** to the Stable channel.

Release promotions are triggered manually (via GitHub Actions).

### Release artifacts:

Artifacts follow the name `{browser}-{version}.zip`, e.g. `chrome-1.0.4.zip`, `edge-2.0.0.12.zip`, `firefox-2.1.1.zip`.

---

## Branching strategy

Whenever a major version goes into maintenance mode, `v{major}.x` is branched-off main (e.g. when we work at v2, we split a `v1.x` branch from main, and then main will correspond to `v2.x`). The maintenance branch will mostly receive bug fixes and security updates. Changes to the build process must be back-ported to maintenance branches, to keep workflows consistent.

We primarily work over the main branch. For the maintenance of previous major versions, PRs can be sent to the `v{major}.x` branch. If some commits in main need to be available on earlier major versions as well, they can be back-ported (after being merged into main) by sending a PR with the other major branch (e.g. `v1.x`) as base.

### Pull requests

When there's a commit that needs to be back-ported, the PR corresponding to that commit should have a needs backport label. Once back-ported, the label should be removed (or replaced with back-ported).
Loading