Skip to content
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
185 changes: 97 additions & 88 deletions .github/workflows/test-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,68 +13,77 @@ on:
- "v[0-9]+.[0-9]+.[0-9]+-**"
pull_request: {}

permissions:
id-token: write # Required for npm trusted publishing (OIDC)
contents: write # Required for creating GitHub releases

jobs:
lint:
if: contains(github.event.head_commit.message, '[skip ci]') == false

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [16.x]
node-version: [24]

steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Checkout code
uses: actions/checkout@v7

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
- name: Enable Corepack
shell: bash
run: corepack enable

- name: Install dependencies
run: yarn install --immutable
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'

- name: Create a clean build
run: yarn run build
- name: Install dependencies
run: yarn install --immutable

- name: Run linters
run: yarn run lint
- name: Create a clean build
run: yarn run build

- name: Run linters
run: yarn run lint

# ===================

# Runs unit tests on all supported node versions and OSes
unit-tests:
if: contains(github.event.head_commit.message, '[skip ci]') == false

runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
node-version: [22, 24]
os: [ubuntu-latest]

steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Checkout code
uses: actions/checkout@v7

- name: Enable Corepack
shell: bash
run: corepack enable

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'

- name: Install dependencies
run: yarn install --immutable
- name: Install dependencies
run: yarn install --immutable

# Compilation is necessary, or the tests won't run
- name: Compile TypeScript code
run: yarn run build
# Compilation is necessary, or the tests won't run
- name: Compile TypeScript code
run: yarn run build

- name: Run component tests
# Allow zero tests for now until we have some
run: yarn run test:ci --passWithNoTests
env:
CI: true
- name: Run component tests
# Allow zero tests for now until we have some
run: yarn run test:ci --passWithNoTests
env:
CI: true

# ===================

Expand All @@ -83,7 +92,6 @@ jobs:
# Trigger this step only when a commit on any branch is tagged with a version number
if: |
github.actor == 'AlCalzone' &&
contains(github.event.head_commit.message, '[skip ci]') == false &&
github.event_name == 'push' &&
startsWith(github.ref, 'refs/tags/v')

Expand All @@ -92,56 +100,57 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
node-version: [24]

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'

- name: Extract the version and commit body from the tag
id: extract_release
# The body may be multiline, therefore we need to escape some characters
run: |
VERSION="${{ github.ref }}"
VERSION=${VERSION##*/v}
echo "::set-output name=VERSION::$VERSION"
BODY=$(git show -s --format=%b)
BODY="${BODY//'%'/'%25'}"
BODY="${BODY//$'\n'/'%0A'}"
BODY="${BODY//$'\r'/'%0D'}"
echo "::set-output name=BODY::$BODY"
if [[ $VERSION == *"-"* ]] ; then
echo "::set-output name=TAG::--tag next"
fi

- name: Install dependencies
run: yarn install --immutable

- name: Create a clean build
run: yarn run build

- name: Publish packages to npm
env:
TAG: ${{ steps.extract_release.outputs.TAG }}
run: |
yarn config set npmAuthToken "${{ secrets.NPM_TOKEN }}"
yarn npm whoami
yarn workspaces foreach -vti --no-private npm publish --tolerate-republish $TAG

- name: Create Github Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release v${{ steps.extract_release.outputs.VERSION }}
draft: false
# Prerelease versions create prereleases on Github
prerelease: ${{ contains(steps.extract_release.outputs.VERSION, '-') }}
body: ${{ steps.extract_release.outputs.BODY }}
- name: Checkout code
uses: actions/checkout@v7

- name: Enable Corepack
shell: bash
run: corepack enable

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'

- name: Extract the version and commit body from the tag
id: extract_release
# The body may be multiline, therefore newlines and % need to be escaped
run: |
VERSION="${{ github.ref }}"
VERSION=${VERSION##*/v}
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
EOF=$(od -An -N6 -x /dev/urandom | tr -d ' ')
BODY=$(git show -s --format=%b)
echo "BODY<<$EOF" >> $GITHUB_OUTPUT
echo "$BODY" >> $GITHUB_OUTPUT
echo "$EOF" >> $GITHUB_OUTPUT
if [[ $VERSION == *"-"* ]] ; then
echo "TAG=--tag next" >> $GITHUB_OUTPUT
fi

- name: Install dependencies
run: yarn install --immutable

- name: Create a clean build
run: yarn run build

- name: Publish packages to npm
env:
TAG: ${{ steps.extract_release.outputs.TAG }}
run: yarn workspaces foreach --all -vti --no-private npm publish --tolerate-republish $TAG

- name: Create Github Release
uses: softprops/action-gh-release@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
name: Release v${{ steps.extract_release.outputs.VERSION }}
draft: false
# Prerelease versions create prereleases on Github
prerelease: ${{ contains(steps.extract_release.outputs.VERSION, '-') }}
body: ${{ steps.extract_release.outputs.BODY }}
9 changes: 7 additions & 2 deletions .yarn/plugins/@yarnpkg/plugin-changed.cjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
/* eslint-disable */
//prettier-ignore
module.exports = {
name: "@yarnpkg/plugin-changed",
factory: function (require) {
var plugin;(()=>{"use strict";var e={d:(t,o)=>{for(var n in o)e.o(o,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:o[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{default:()=>f});const o=require("@yarnpkg/cli"),n=require("clipanion"),r=require("@yarnpkg/core");function a(e){const{project:t}=e,o=new Set;return function e({manifest:n}){for(const a of r.Manifest.hardDependencies)for(const r of n.getForScope(a).values()){const n=t.tryWorkspaceByDescriptor(r);n&&!o.has(n)&&(o.add(n),e(n))}}(e),[...o]}function s(e){const t=new Set;for(const o of e.project.workspaces){a(o).some(t=>r.structUtils.areLocatorsEqual(t.locator,e.locator))&&t.add(o)}return[...t]}var i=function(e,t,o,n){var r,a=arguments.length,s=a<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,o):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,n);else for(var i=e.length-1;i>=0;i--)(r=e[i])&&(s=(a<3?r(s):a>3?r(t,o,s):r(t,o))||s);return a>3&&s&&Object.defineProperty(t,o,s),s};class c extends o.BaseCommand{async listWorkspaces(e){const{stdout:t}=await r.execUtils.execvp("git",["diff","--name-only",...this.gitRange?[this.gitRange]:[]],{cwd:e.cwd,strict:!0}),o=function(e,t){const o=new Set;for(const n of e.workspaces){if(t.some(e=>e.startsWith(n.relativeCwd))&&!o.has(n)){o.add(n);for(const e of s(n))o.add(e)}}return[...o]}(e,t.split(/\r?\n/)),n=this.include||[],a=this.exclude||[];return o.filter(e=>{const t=r.structUtils.stringifyIdent(e.locator);if(t){if(n.length&&!n.includes(t))return!1;if(a.length&&a.includes(t))return!1}return!0})}}i([n.Command.String("--git-range")],c.prototype,"gitRange",void 0),i([n.Command.Array("--include")],c.prototype,"include",void 0),i([n.Command.Array("--exclude")],c.prototype,"exclude",void 0);var d=function(e,t,o,n){var r,a=arguments.length,s=a<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,o):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,n);else for(var i=e.length-1;i>=0;i--)(r=e[i])&&(s=(a<3?r(s):a>3?r(t,o,s):r(t,o))||s);return a>3&&s&&Object.defineProperty(t,o,s),s};class l extends c{constructor(){super(...arguments),this.json=!1}async execute(){const e=await r.Configuration.find(this.context.cwd,this.context.plugins),{project:t,workspace:n}=await r.Project.find(e,this.context.cwd);if(!n)throw new o.WorkspaceRequiredError(t.cwd,this.context.cwd);return(await r.StreamReport.start({configuration:e,json:this.json,stdout:this.context.stdout},async e=>{const o=await this.listWorkspaces(t);for(const t of o)e.reportInfo(null,t.relativeCwd),e.reportJson({name:t.manifest.name?r.structUtils.stringifyIdent(t.manifest.name):null,location:t.relativeCwd})})).exitCode()}}l.usage=n.Command.Usage({description:"List changed workspaces and their dependents",details:"\n If the `--json` flag is set the output will follow a JSON-stream output also known as NDJSON (https://github.com/ndjson/ndjson-spec).\n ",examples:[["Find changed files within a Git range","yarn changed list --git-range 93a9ed8..4ef2c61"],["Include or exclude workspaces","yarn changed list --include @foo/a --exclude @foo/b"]]}),d([n.Command.Boolean("--json")],l.prototype,"json",void 0),d([n.Command.Path("changed","list")],l.prototype,"execute",null);var p=function(e,t,o,n){var r,a=arguments.length,s=a<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,o):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,n);else for(var i=e.length-1;i>=0;i--)(r=e[i])&&(s=(a<3?r(s):a>3?r(t,o,s):r(t,o))||s);return a>3&&s&&Object.defineProperty(t,o,s),s};class u extends c{constructor(){super(...arguments),this.args=[],this.verbose=!1,this.parallel=!1,this.interlaced=!1,this.topological=!1}async execute(){const e=await r.Configuration.find(this.context.cwd,this.context.plugins),{project:t,workspace:n}=await r.Project.find(e,this.context.cwd);if(!n)throw new o.WorkspaceRequiredError(t.cwd,this.context.cwd);const a=await this.listWorkspaces(t);if(!a.length){return(await r.StreamReport.start({configuration:e,stdout:this.context.stdout},async e=>{e.reportInfo(null,"No workspaces changed")})).exitCode()}return this.cli.run(["workspaces","foreach",...a.reduce((e,t)=>[...e,"--include",r.structUtils.stringifyIdent(t.locator)],[]),...this.verbose?["--verbose"]:[],...this.parallel?["--parallel"]:[],...this.interlaced?["--interlaced"]:[],...this.topological?["--topological"]:[],...this.jobs?["--jobs",""+this.jobs]:[],this.commandName,...this.args],{cwd:t.cwd})}}u.usage=n.Command.Usage({description:"Run a command on changed workspaces and their dependents",details:"\n This command will run a given sub-command on changed workspaces and workspaces depends on them.\n\n Check the documentation for `yarn workspace foreach` for more details.\n ",examples:[["Run build scripts on changed workspaces","yarn changed foreach run build"],["Find changed files within a Git range","yarn changed foreach --git-range 93a9ed8..4ef2c61 run build"]]}),p([n.Command.String()],u.prototype,"commandName",void 0),p([n.Command.Proxy()],u.prototype,"args",void 0),p([n.Command.Boolean("-v,--verbose")],u.prototype,"verbose",void 0),p([n.Command.Boolean("-p,--parallel")],u.prototype,"parallel",void 0),p([n.Command.Boolean("-i,--interlaced")],u.prototype,"interlaced",void 0),p([n.Command.Boolean("-t,--topological")],u.prototype,"topological",void 0),p([n.Command.String("-j,--jobs")],u.prototype,"jobs",void 0),p([n.Command.Path("changed","foreach")],u.prototype,"execute",null);const f={commands:[l,u]};plugin=t})();
"use strict";var plugin=(()=>{var b=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var i=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(o,e)=>(typeof require<"u"?require:o)[e]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var N=(t,o)=>{for(var e in o)b(t,e,{get:o[e],enumerable:!0})},O=(t,o,e,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of I(o))!U.call(t,s)&&s!==e&&b(t,s,{get:()=>o[s],enumerable:!(r=R(o,s))||r.enumerable});return t};var q=t=>O(b({},"__esModule",{value:!0}),t);var J={};N(J,{default:()=>E});var B=i("@yarnpkg/cli"),g=i("clipanion"),w=i("@yarnpkg/core");var P=i("@yarnpkg/core");var v=i("@yarnpkg/core");function W(t){let{project:o}=t,e=new Set;function r({manifest:s}){for(let c of v.Manifest.hardDependencies)for(let l of s.getForScope(c).values()){let n=o.tryWorkspaceByDescriptor(l);n&&!e.has(n)&&(e.add(n),r(n))}}return r(t),[...e]}function y(t){let o=new Set;for(let e of t.project.workspaces)W(e).some(s=>P.structUtils.areLocatorsEqual(s.anchoredLocator,t.anchoredLocator))&&o.add(e);return[...o]}function j(t,o){let e=new Set;for(let r of t.workspaces)if(o.some(c=>c.startsWith(r.relativeCwd))&&!e.has(r)){e.add(r);for(let c of y(r))e.add(c)}return[...e]}var m=class extends B.BaseCommand{constructor(){super(...arguments);this.gitRange=g.Option.String("--git-range");this.cached=g.Option.Boolean("--cached",!1);this.include=g.Option.Array("--include");this.exclude=g.Option.Array("--exclude")}async listWorkspaces(e){let{stdout:r}=await w.execUtils.execvp("git",["diff","--name-only",...this.cached?["--cached"]:[],...this.gitRange?[this.gitRange]:[]],{cwd:e.cwd,strict:!0}),s=r.split(/\r?\n/),c=j(e,s),l=this.include||[],n=this.exclude||[];return c.filter(h=>{let x=w.structUtils.stringifyIdent(h.anchoredLocator);return!(x&&(l.length&&!l.includes(x)||n.length&&n.includes(x)))})}};var k=i("clipanion"),d=i("@yarnpkg/core"),S=i("@yarnpkg/cli"),f=class extends m{constructor(){super(...arguments);this.json=k.Option.Boolean("--json",!1)}async execute(){let e=await d.Configuration.find(this.context.cwd,this.context.plugins),{project:r,workspace:s}=await d.Project.find(e,this.context.cwd);if(!s)throw new S.WorkspaceRequiredError(r.cwd,this.context.cwd);return(await d.StreamReport.start({configuration:e,json:this.json,stdout:this.context.stdout},async l=>{let n=await this.listWorkspaces(r);for(let h of n)l.reportInfo(null,h.relativeCwd),l.reportJson({name:h.manifest.name?d.structUtils.stringifyIdent(h.manifest.name):null,location:h.relativeCwd})})).exitCode()}};f.usage=k.Command.Usage({description:"List changed workspaces and their dependents",details:"\n If the `--json` flag is set the output will follow a JSON-stream output also known as NDJSON (https://github.com/ndjson/ndjson-spec).\n ",examples:[["Find changed files within a Git range","yarn changed list --git-range 93a9ed8..4ef2c61"],["Include or exclude workspaces","yarn changed list --include @foo/a --exclude @foo/b"]]}),f.paths=[["changed","list"]];var a=i("clipanion"),p=i("@yarnpkg/core"),D=i("@yarnpkg/cli"),u=class extends m{constructor(){super(...arguments);this.commandName=a.Option.String();this.args=a.Option.Proxy();this.verbose=a.Option.Boolean("-v,--verbose",!1);this.parallel=a.Option.Boolean("-p,--parallel",!1);this.interlaced=a.Option.Boolean("-i,--interlaced",!1);this.topological=a.Option.Boolean("-t,--topological",!1);this.all=a.Option.Boolean("-A,--all",!1);this.recursive=a.Option.Boolean("-R,--recursive",!1);this.worktree=a.Option.Boolean("-W,--worktree",!1);this.jobs=a.Option.String("-j,--jobs")}async execute(){let e=await p.Configuration.find(this.context.cwd,this.context.plugins),{project:r,workspace:s}=await p.Project.find(e,this.context.cwd);if(!s)throw new D.WorkspaceRequiredError(r.cwd,this.context.cwd);let c=await this.listWorkspaces(r);return c.length?this.cli.run(["workspaces","foreach",...c.reduce((l,n)=>[...l,"--include",p.structUtils.stringifyIdent(n.anchoredLocator)],[]),...this.verbose?["--verbose"]:[],...this.parallel?["--parallel"]:[],...this.interlaced?["--interlaced"]:[],...this.topological?["--topological"]:[],...this.all?["--all"]:[],...this.recursive?["--recursive"]:[],...this.worktree?["--worktree"]:[],...this.jobs?["--jobs",`${this.jobs}`]:[],this.commandName,...this.args],{cwd:r.cwd}):(await p.StreamReport.start({configuration:e,stdout:this.context.stdout},async n=>{n.reportInfo(null,"No workspaces changed")})).exitCode()}};u.usage=a.Command.Usage({description:"Run a command on changed workspaces and their dependents",details:`
This command will run a given sub-command on changed workspaces and workspaces depends on them.

Check the documentation for \`yarn workspace foreach\` for more details.
`,examples:[["Run build scripts on changed workspaces","yarn changed foreach run build"],["Find changed files within a Git range","yarn changed foreach --git-range 93a9ed8..4ef2c61 run build"]]}),u.paths=[["changed","foreach"]];var A={commands:[f,u]},E=A;return q(J);})();
return plugin;
}
};
};
Loading