diff --git a/README.md b/README.md new file mode 100644 index 0000000..250d21c --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# Changesets Release Action + +This action for [Changesets](https://github.com/atlassian/changesets) creates a pull request with all of the package versions updated and changelogs updated and when there are new changesets on master, the PR will be updated. When you're ready, you can merge the pull request and you can either publish the packages to npm manually or setup the action to do it for you. + +## Usage + +### Without Publishing + +Create a file at `.github/workflows/release.yml` with the following content. + +```yml +name: Release + +on: + push: + branches: + - master + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@master + + - name: Setup Node.js 10.x + uses: actions/setup-node@master + with: + version: 10.x + + - name: Install Yarn + run: npm install --global yarn + + - name: Install Dependencies + run: yarn + + - name: Create Pull Request or Publish to npm + uses: changesets/action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +### With Publishing + +Before you can setup this action with publishing, you'll need to have an [npm token](https://docs.npmjs.com/creating-and-viewing-authentication-tokens) that can publish the packages in the repo you're setting up the action for and doesn't have 2FA on publish enabled(2FA on auth can be enabled). You'll also need to [add it as a secret on your GitHub repo](https://help.github.com/en/articles/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables) with the name `NPM_TOKEN`. Once you've done that, you can create a file at `.github/workflows/release.yml` with the following content. + +```yml +name: Release + +on: + push: + branches: + - master + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@master + + - name: Setup Node.js 10.x + uses: actions/setup-node@master + with: + version: 10.x + + - name: Install Yarn + run: npm install --global yarn + + - name: Install Dependencies + run: yarn + + - name: "Create Pull Request or Publish to npm" + uses: changesets/action@master + with: + # The --otp=1 is to get around a bug in changesets + # It will be fixed in Changesets 2 + publish: yarn release --otp=1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} +``` diff --git a/dist/index.js b/dist/index.js index a641809..6bcd550 100644 --- a/dist/index.js +++ b/dist/index.js @@ -985,5 +985,5 @@ function e(e){return Array.isArray(e)?e:[e]}const t=/^\s+$/,r=/^\\!/,i=/^\\#/,s= },{"array-union":"iMRL","glob":"R9Ja","fast-glob":"qwKf","dir-glob":"MgqK","./gitignore":"Rx5v"}],"kAcF":[function(require,module,exports) { "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var e=t(require("fs-extra")),a=t(require("path")),r=t(require("globby"));function t(e){return e&&e.__esModule?e:{default:e}}async function s(t={}){const s=t.cwd||process.cwd(),o=t.tools||["yarn","bolt"],n=await e.default.readFile(a.default.join(s,"package.json"),"utf-8").then(JSON.parse);let l;if(o.includes("yarn")&&n.workspaces?Array.isArray(n.workspaces)?l=n.workspaces:n.workspaces.packages&&(l=n.workspaces.packages):o.includes("bolt")&&n.bolt&&n.bolt.workspaces&&(l=n.bolt.workspaces),!l)return o.includes("root")?[{config:n,dir:s,name:n.name}]:null;const i=await(0,r.default)(l,{cwd:s,onlyDirectories:!0,absolute:!0,expandDirectories:!1});let c=[];const u=await Promise.all(i.sort().filter(r=>e.default.existsSync(a.default.join(r,"package.json"))).map(async r=>e.default.readFile(a.default.join(r,"package.json"),"utf8").then(e=>{const t=JSON.parse(e);return t.name||c.push(a.default.relative(s,a.default.join(r,"package.json"))),{config:t,name:t.name,dir:r}})));if(0!==c.length)throw c.sort(),new Error(`The following package.jsons are missing the "name" field:\n${c.join("\n")}`);return u}var o=s;exports.default=o; },{"fs-extra":"wFa+","globby":"e8e8"}],"7QCb":[function(require,module,exports) { -"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function t(t){for(var r=1;r{o+=e.toString()},stderr:e=>{a+=e.toString()}}},r)),stdout:o,stderr:a}}function b(e,t){let n,r,o=l.default().use(u.default).parse(e),a=o.children;for(let i=0;i{let e=process.env.GITHUB_TOKEN;if(!e)return void a.setFailed("Please add the GITHUB_TOKEN to the changesets action");let n=`${s.context.repo.owner}/${s.context.repo.repo}`;const r=new s.GitHub(e);let o=r.repos.get(s.context.repo).then(e=>e.data.default_branch);console.log("setting git user"),await i.exec("git",["config","--global","user.name",'"github-actions[bot]"']),await i.exec("git",["config","--global","user.email",'"github-actions[bot]@users.noreply.github.com"']),console.log("setting GitHub credentials"),await c.default.writeFile(`${process.env.HOME}/.netrc`,`machine github.com\nlogin github-actions[bot]\npassword ${e}`);let l=await o;if(s.context.ref.replace("refs/heads/","")!==l)return void a.setFailed(`The changesets action should only run on ${l} but it's running on ${s.context.ref.replace("refs/heads/","")}, please change your GitHub actions config to only run the Changesets action on ${l}`);let u=c.default.readdirSync(`${process.cwd()}/.changeset`).some(e=>"config.js"!==e&&"README.md"!==e),d=a.getInput("publish");if(!u&&!d)return void console.log("No changesets found");if(!u&&d){console.log("No changesets found, attempting to publish any unpublished packages to npm");let e=await f.default({tools:["bolt","yarn","root"]});if(!e)return a.setFailed("Could not find workspaces");let n=new Map(e.map(e=>[e.name,e]));c.default.writeFileSync(`${process.env.HOME}/.npmrc`,`//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}`);let[o,...u]=d.split(/\s+/),g=await p(o,u);await i.exec("git",["push","origin",`HEAD:${l}`,"--follow-tags"]);let w=/New tag:\s+(@[^\/]+\/[^@]+|[^\/]+)@([^\s]+)/,m=[];for(let t of g.stdout.split("\n")){let e=t.match(w);if(null===e)continue;let r=e[1],o=n.get(r);if(void 0===o)return a.setFailed("Workspace not found for "+r+". This is probably a bug in the action, please open an issue");m.push(o)}return void(await Promise.all(m.map(async e=>{try{let o=h.default.join(e.dir,"CHANGELOG.md"),i=b(await c.default.readFile(o,"utf8"),e.config.version);if(!i)return a.setFailed(`Could not find changelog entry for ${e.name}@${e.config.version}`);await r.repos.createRelease(t({tag_name:`${e.name}@${e.config.version}`,body:i,prerelease:e.config.version.includes("-")},s.context.repo))}catch(n){if("ENOENT"!==n.code)throw n}})))}let{stderr:g}=await p("git",["checkout","changeset-release"],{ignoreReturnCode:!0}),w=!g.toString().includes("Switched to a new branch 'changeset-release'");w&&await i.exec("git",["checkout","-b","changeset-release"]);let m=w;if(!m){console.log("checking if new changesets should be added");const e=(await p("git",["merge-base","changeset-release",s.context.sha])).stdout.trim();m=(await p("git",["diff","--name-only",`${e}...${s.context.sha}`])).stdout.trim().includes(".changeset"),console.log("checked if new changesets should be added "+m)}if(m){await i.exec("git",["reset","--hard",s.context.sha]),await i.exec("yarn",["changeset","bump"]),await i.exec("git",["add","."]),await i.exec("git",["commit","-m","Version Packages"]),await i.exec("git",["push","origin","changeset-release","--force"]);let e=`repo:${n}+state:open+head:changeset-release+base:${l}`,o=await r.search.issuesAndPullRequests({q:e});console.log(JSON.stringify(o.data,null,2)),0===o.data.items.length?(console.log("creating pull request"),await r.pulls.create(t({base:l,head:"changeset-release",title:"Version Packages"},s.context.repo))):console.log("pull request found")}else console.log("no new changesets")})().catch(e=>{console.error(e),a.setFailed(e.message)}); +"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,a)}return n}function t(t){for(var a=1;a{r+=e.toString()},stderr:e=>{o+=e.toString()}}},a)),stdout:r,stderr:o}}function b(e,t){let n,a,r=c.default().use(u.default).parse(e),o=r.children;for(let i=0;i{let e=process.env.GITHUB_TOKEN;if(!e)return void o.setFailed("Please add the GITHUB_TOKEN to the changesets action");let n=`${s.context.repo.owner}/${s.context.repo.repo}`;const a=new s.GitHub(e);let r=a.repos.get(s.context.repo).then(e=>e.data.default_branch);console.log("setting git user"),await i.exec("git",["config","--global","user.name",'"github-actions[bot]"']),await i.exec("git",["config","--global","user.email",'"github-actions[bot]@users.noreply.github.com"']),console.log("setting GitHub credentials"),await l.default.writeFile(`${process.env.HOME}/.netrc`,`machine github.com\nlogin github-actions[bot]\npassword ${e}`);let c=await r;if(s.context.ref.replace("refs/heads/","")!==c)return void o.setFailed(`The changesets action should only run on ${c} but it's running on ${s.context.ref.replace("refs/heads/","")}, please change your GitHub actions config to only run the Changesets action on ${c}`);let u=l.default.readdirSync(`${process.cwd()}/.changeset`).some(e=>"config.js"!==e&&"README.md"!==e),d=o.getInput("publish");if(!u&&!d)return void console.log("No changesets found");if(!u&&d){console.log("No changesets found, attempting to publish any unpublished packages to npm");let e=await f.default({tools:["bolt","yarn","root"]});if(!e)return o.setFailed("Could not find workspaces");let n=new Map(e.map(e=>[e.name,e]));l.default.writeFileSync(`${process.env.HOME}/.npmrc`,`//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}`);let[r,...u]=d.split(/\s+/),g=await p(r,u);await i.exec("git",["push","origin",`HEAD:${c}`,"--follow-tags"]);let w=/New tag:\s+(@[^\/]+\/[^@]+|[^\/]+)@([^\s]+)/,m=[];for(let t of g.stdout.split("\n")){let e=t.match(w);if(null===e)continue;let a=e[1],r=n.get(a);if(void 0===r)return o.setFailed("Workspace not found for "+a+". This is probably a bug in the action, please open an issue");m.push(r)}return void(await Promise.all(m.map(async e=>{try{let r=h.default.join(e.dir,"CHANGELOG.md"),i=b(await l.default.readFile(r,"utf8"),e.config.version);if(!i)return o.setFailed(`Could not find changelog entry for ${e.name}@${e.config.version}`);await a.repos.createRelease(t({tag_name:`${e.name}@${e.config.version}`,body:i,prerelease:e.config.version.includes("-")},s.context.repo))}catch(n){if("ENOENT"!==n.code)throw n}})))}let{stderr:g}=await p("git",["checkout","changeset-release"],{ignoreReturnCode:!0}),w=!g.toString().includes("Switched to a new branch 'changeset-release'");w&&await i.exec("git",["checkout","-b","changeset-release"]);let m=w;if(!m){console.log("checking if new changesets should be added");const e=(await p("git",["merge-base","changeset-release",s.context.sha])).stdout.trim();m=(await p("git",["diff","--name-only",`${e}...${s.context.sha}`])).stdout.trim().includes(".changeset"),console.log("checked if new changesets should be added "+m)}if(m){await i.exec("git",["reset","--hard",s.context.sha]);let e=await p("yarn",["changeset","bump"]),r=`repo:${n}+state:open+head:changeset-release+base:${c}`,o=a.search.issuesAndPullRequests({q:r}),u=(async()=>{let t=/Updated file (.+)/,n=[];for(let a of e.stdout.split("\n")){let e=a.match(t);null!==e&&n.push(e[1])}return"Hey!!\n\nThis PR was automatically opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or \n\n# Changes\n"+(await Promise.all(n.map(async e=>{let[t,n]=await Promise.all([l.default.readJson(h.default.join(h.default.dirname(e),"package.json")),l.default.readFile(e,"utf8")]),a=b(n,t.version);return`## ${t.name}@${t.version}\n`+a}))).join("\n ")})();await i.exec("git",["add","."]),await i.exec("git",["commit","-m","Version Packages"]),await i.exec("git",["push","origin","changeset-release","--force"]);let d=await o;console.log(JSON.stringify(d.data,null,2)),0===d.data.items.length?(console.log("creating pull request"),await a.pulls.create(t({base:c,head:"changeset-release",title:"Version Packages",body:await u},s.context.repo))):(a.pulls.update(t({pull_number:d.data.items[0].number,body:await u},s.context.repo)),console.log("pull request found"))}else console.log("no new changesets")})().catch(e=>{console.error(e),o.setFailed(e.message)}); },{"@actions/core":"4FTV","@actions/exec":"utFe","@actions/github":"8Dol","fs-extra":"JTJ9","unified":"EJQW","remark-parse":"+8Y3","remark-stringify":"eCnT","mdast-util-to-string":"ljHw","get-workspaces":"kAcF"}]},{},["7QCb"], null) \ No newline at end of file