Update documentation site and init command (#879)

This commit is contained in:
Elizabeth Craig 2023-05-17 22:34:20 -07:00 коммит произвёл GitHub
Родитель 8eb91797c1
Коммит bf0cf61ec5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 524 добавлений и 191 удалений

4
.github/workflows/release.yml поставляемый
Просмотреть файл

@ -59,9 +59,9 @@ jobs:
# Add a token to the remote URL for auth during release
git remote set-url origin "https://$REPO_PAT@github.com/$GITHUB_REPOSITORY"
yarn release -y -n $NPM_AUTHTOKEN
yarn release -y -n "$NPM_AUTHTOKEN"
env:
NPM_AUTHTOKEN: ${{ secrets.npm_authtoken }}
NPM_AUTHTOKEN: ${{ secrets.NPM_AUTHTOKEN }}
REPO_PAT: ${{ secrets.REPO_PAT }}
- name: Update docs

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Make init more robust",
"packageName": "beachball",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Add comments on BeachballOptions and sort default options",
"packageName": "beachball",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -8,8 +8,14 @@ category: doc
Bumps versions locally without publishing to the remote git repo or npm registry. This command will also generate changelogs.
This is the same logic that is used by the publish command, so it is a good practice to bump things locally to see what kind of changes are going to be done before those changes are published to the npm registry and the remote git repo. Since this affects files locally only, it is up to you to synchronize the package versions in the remote git repo as well as the npm registry.
This is the same logic that is used by the `publish` command, so it's a good practice to bump things locally to see what kind of changes will be made before those changes are published to the npm registry and the remote git repo.
Since this affects files locally only, it's up to you to synchronize the package versions in the remote git repo as well as the npm registry after running this command. (Or if you were using it for testing, simply revert the local changes and run `beachball publish`.)
```bash
$ beachball bump
```
### Options
See the [options page](./options).

Просмотреть файл

@ -6,30 +6,34 @@ category: doc
# `change`
This command walks you through a couple of questions and will generate the appropriate [change file](../concepts/change-files) in the `/change` directory. The generated file will be checked into the repo automatically for you. One of the niceties of using this utility to generate change files is that it will [check](./check) whether or not you even need a change file or not. Also, it will try to pull in recent commit messages to speed up change file generation.
This command walks you through a couple of questions and will generate the appropriate [change file](../concepts/change-files) in the `/change` directory. The generated file will be committed automatically.
One of the niceties of using this utility to generate change files is that it will [check](./check) whether or not you even need a change file. Also, it will load recent commit messages to ease change file generation.
```bash
$ beachball change
```
### Uncommitted Files
### Options
When you have changes that are not committed yet (i.e. `git status` reports changes), then `beachball change` will warn you about these:
See the [options page](./options).
```bash
### Walkthrough
If you have changes that are not committed yet (i.e. `git status` reports changes), then `beachball change` will warn you about these:
```
$ beachball change
Defaults to "origin/master"
There are uncommitted changes in your repository. Please commit these files first:
- a-new-file
```
Make sure to commit _all_ changes before proceeding with the `change` command
Make sure to commit _all_ changes before proceeding with the `change` command.
### Walking Through the Form
Now we'll commit the changes we made and run `beachball change` again:
Let's move on. We will commit the changes we made and re-run `beachball change` again:
```bash
```
$ beachball change
Defaults to "origin/master"
Checking for changes against "origin/master"
@ -39,7 +43,11 @@ Please describe the changes for: single
adding a new file
```
It'll ask for a description of the change. This can be any text, but it is also very convenient that `beachball` will look for recent commit messages for you to choose as the description. These descriptions will be collated into a changelog when the change is published by `beachball publish`.
First, it will ask for a **description** of the change. You can enter any text, but `beachball` will also provide a list of recent commit messages to choose from.
> Tip: These descriptions will be collated into a changelog when the change is published by `beachball publish`, so think about how to describe your change in a way that's helpful and relevant for consumers of the package.
Next, the form will ask for a change **type**. This should be chosen based on [semantic versioning rules](https://semver.org/) because it determines how to update the package version. If the change doesn't affect the published package at all (e.g. you just updated some comments), choose `none`.
```bash
? Change type - Use arrow-keys. Return to submit.
@ -48,5 +56,3 @@ It'll ask for a description of the change. This can be any text, but it is also
None - this change does not affect the published package in any way.
Major - major feature; breaking changes.
```
The form will ask you about a change type. This is the answer that will ultimately determine whether to update the version of the package by major, minor or patch. You can even pick "none" if you don't intend for this change to affect the version of the package (e.g. fixing a README.md typo).

Просмотреть файл

@ -6,50 +6,28 @@ category: doc
# `check`
It is useful to enforce that [change files](./concepts/change-files) are checked in for each PR before they enter the target branch. In this way, all changes are captured and would affect semver appropriately. To check to make sure all changes are captured in change files, simply run:
It's recommended to enforce that [change files](../concepts/change-files) are included with each PR. This way, all changes are captured and affect semver appropriately.
To ensure that all changes are captured in change files, simply run:
```bash
$ beachball check
```
This command also checks for various types of misconfigurations that would result in problems when attempting to publish.
This command also checks for misconfigurations that would result in problems when attempting to publish.
### Where Should Check Be Run?
### Options
See the [options page](./options).
### Where should `check` be run?
#### As a step in the PR review gate
Add a step `yarn checkchange` in your PR validation build, where `checkchange` is defined in `package.json` as `beachball check` (with any appropriate options).
Note that in GitHub action workflows, you **must** specify `fetch-depth: 0` in the `checkout` option. You can see a full example in [beachball's own PR workflow](https://github.com/microsoft/beachball/blob/master/.github/workflows/pr.yml).
```yaml
jobs:
build:
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node.js 12
uses: actions/setup-node@v1
with:
node-version: 12
- yarn
- yarn checkchange
# build/test steps as appropriate
```
Another example, for Travis CI:
```yaml
language: node_js
node_js:
- '12'
script:
- yarn
- yarn checkchange
# build/test steps as appropriate
```
See the [change files page](../concepts/change-files#validating-change-files) for how to set this up.
#### As git hook (optional)
For a reference of git hooks, take a look at [this documentation](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). It is recommended to place this hook as a pre-push.
For a reference about git hooks, take a look at [this documentation](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). This hook would typically be run pre-push.
While running `beachball check` before push may seem appealing, it has some downsides: it will substantially slow down running `git push` and could be annoying when pushing work-in-progress changes to remote branches. Our experience with repos enabling this hook is that it's often quickly removed due to developer feedback.

Просмотреть файл

@ -6,19 +6,41 @@ category: doc
# `publish`
Publishing automates all the bumping and synchronizing of package versions in git remotes as well as the npm registry. The steps taken by the publish command are designed to be run so that it minimizes the chances of failure by doing validation upfront.
Publishing automates all the bumping and synchronizing of package versions in the git remote as well as the npm registry.
By publishing, it'll perform the following tasks:
### Options
1. Validate that there are no local changes
2. Validate that the versions to be bumped are in fact available in the npm registry
3. Bumps the package versions
4. Generate package changelog files
5. Revert all these changes
6. Fetch latest git changes on the remote target branch
7. Perform the exact same thing in steps 3 & 4
8. Push these changes back to the remote target branch
See the [options page](./options).
It might be surprising that `beachball publish` does so many steps, especially the step about reverting changes! In most version bumping systems that automates git repo version with npm registry, they assume that the source code is fresh by the time they push the changes back to the git repository. This is almost never the case when the build takes more than a few minutes! So, `beachball` fetches latest before we push back to the target branch. In large systems, it has been observed that without the git fetch, it becomes a source of conflict.
### Algorithm
All the options for publish are documented in the CLI [options](./options) page
The `publish` command is designed to run steps in an order that minimizes the chances of mid-publish failure by doing validation upfront.
`beachball publish` performs the following steps:
1. Validate that options and change files are valid
2. Bump and publish to npm (unless disabled):
1. Bump the package versions locally
2. Generate the changelog files (unless disabled)
3. Delete change files locally (unless disabled)
4. Validate that nothing to be published depends on a private package
5. Publish packages to npm in topological order based on the dependency graph (to reduce the chances that if there's a failure partway through, a published package might require unpublished versions)
3. Bump and push to git (unless bumping or pushing is disabled):
1. Revert any previous changes (from the publish step)
2. Merge the latest changes from the remote branch to avoid merge conflicts (unless fetching is disabled)
3. Bump the versions locally
4. Generate the changelog files (unless disabled)
5. Delete change files locally (unless disabled)
6. Commit the changes
7. Create git tags for new package versions (unless disabled)
8. Push the changes and tags
It might be surprising that `beachball publish` does so many steps, especially the step about reverting changes! In most version bumping systems that automate syncing the git repo and npm registry, they assume that the source code is still fresh once it's time to push changes back to the git repository. This is rarely the case for large repos with many developers. So, `beachball` fetches the latest changes before pushing back to the target branch to avoid merge conflicts.
### Example CI workflow
See the [CI integration page](../concepts/ci-integration) details and examples for how to run `beachball publish` in CI.
### Recovering from failed publish
If the `publish` command fails partway through, after some versions have been published to the registry, you'll need to run [`beachball sync`](./sync) and commit the changes.

Просмотреть файл

@ -10,14 +10,16 @@ Synchronizes the local version number of each package to the current version of
By default, the local version will only be updated if it's **older** than the version the specified `dist-tag` points to. Use `--force` to override this behavior.
#### Options
After syncing, be sure to commit and push the changes.
### Options
In addition to the options below, certain [common options](./options) also apply.
##### `--force`
#### `--force`
Force the sync command to skip the version comparison and use the version in the registry as is.
##### `--tag, -t`
#### `--tag, -t`
Sync with the version this `dist-tag` points to. Defaults to the tag from repo, group, or package level beachball configs if present.
Sync with the version this `dist-tag` points to. Defaults to the tag from repo, group, or package level beachball configs if present, falling back to `latest`.

Просмотреть файл

@ -8,7 +8,7 @@ category: doc
Bumping a single package is a simple task of just looking up a change file for its change type and using semver to bump the version according to what that change type is.
Things get a bit more complicated when we introduce the concepts of version groups and dependent package bumping. For the sake of describing this algorithm, we can take look at the following graph:
Things get a bit more complicated when we introduce the concepts of version groups and dependent package bumping. For the sake of describing this algorithm, we can take a look at the following graph:
```mermaid
graph TD
@ -22,7 +22,7 @@ graph TD
end
```
### Dependent Version Bumping
### Dependent version bumping
In the above example, the `app` package is dependent on `fooLib`. Let's assume that the developer has created a `minor` change inside `fooLib`. By default, `beachball` will also bump `app` with a `patch` change type, like this:
@ -54,7 +54,7 @@ To modify what the dependent package bumped change type would be (e.g. making `a
}
```
### Grouped Bumping
### Grouped bumping
In the above example, `fooUtils`, `styleUtils`, `dateUtils` all belong to a `utils` group. Whenever one of those packages get bumped, the entire group would get bumped by the same change type. We can illustrate it like so:
@ -75,4 +75,4 @@ graph TD
dateUtils -. minor .->dateUtilsNext
```
> NOTE: the group get bumped together even if it is part of a dependent package bump. In other words, package bumps propagate their changes via dependent package bump as well as group package bumps
> NOTE: the group get bumped together even if it is part of a dependent package bump. In other words, package bumps propagate their changes via dependent package bumps as well as group package bumps.

Просмотреть файл

@ -6,37 +6,78 @@ category: doc
# Change Files
There are <a href="https://semantic-release.gitbook.io/semantic-release/" target="_blank">very popular</a> and excellent packages available which manage package versioning already. Beachball works differently: `beachball` does \_not\_ rely on commit messages for determining the next semantic version. Rather, it uses something called a "change file".
There are <a href="https://semantic-release.gitbook.io/semantic-release/" target="_blank">very popular</a> and excellent packages available which manage package versioning based on commit messages. `beachball` works differently, using something called a **change file**.
### What is a Change File?
## What is a change file?
After you have made some commits, you are ready to create a change file. A change file is generated for you by `beachball`. `beachball` uses the change file to determine how to bump versions in your package.
To generate a change file, you run this command:
```bash
$ beachball change # could leave out "change" command since it is the default
```
It will ask you to put in a description and a change type. Don't worry though, `beachball` is nice and will find recent commit messages if you would rather describe your changes based on something you already typed! The type of change you specify will influence how `beachball` will bump your version.
After you've answered those questions, a change file is created and commited in your branch under `/change` that looks like this:
Change files are generated by the `beachball change` command and live under the `/change` folder. They look something like this:
```json
{
"comment": "Upgrading React to 16.8.x to use hooks",
"type": "minor",
"packageName": "my-amazing-app",
"email": "me@me.me",
"commit": "b785112c03f063b71d936ff052470817019267d4",
"date": "2019-06-20T22:54:59.172Z"
"email": "me@me.me"
}
```
If you have some existing change file for this package, `beachball` will assume you're still working on the same feature and will skip the dialog.
`beachball` then uses the change files during publishing to determine how to bump package versions, and what content should be in the changelog.
### Working with the change file
The advantage of using `.json` files rather than commit messages is that it's very easy to see visual diffs of these files in a PR, so reviewers can verify that the change type and message are correct.
`beachball` uses change files to indicate change type for a very good reason. File diffs work wonderfully well in all PR systems. These tools are well suited to visualize file diffs and allows a chance for reviewers to review what is written in a change file.
For example, a reviewer might remind the author that a certain new API has been introduced and that the change ought to be a minor. The author can then modify the change file without having to amend history of a commit!
For example, a reviewer might remind the author that a certain new API has been introduced and that the change ought to be a minor. The author can then modify the change file without having to ammend history of a commit!
## Generating a change file
After making some commits, it's time to create a change file. Change files are generated with the `beachball change` command. (In a monorepo, this should only be run at the repo root.)
Assuming you've defined the `change` wrapper script suggested on the [installation page](../overview/installation), run one of the following commands:
```bash
# for npm
$ npm run change
# for yarn
$ yarn change
```
If you don't already have a change file for this branch and package, it will ask you to enter a description and a change type (in a monorepo, it will ask for each changed package).
- For the **description**, `beachball` will provide a list of recent commit messages to choose from, or you can type a custom message.
- Choose the correct **type** using [semantic versioning rules](https://semver.org/).
After you've answered those questions, a change file similar to the example above is created and committed in your branch under `/change`.
If you prefer, you can specify the change type and message on the command line. (In a monorepo, the specified type and message will be used for all changed packages.)
```bash
# for npm
$ npm run change -- --type minor --message "Upgrading React to 16.8.x to use hooks"
# for yarn
$ yarn change --type minor --message "Upgrading React to 16.8.x to use hooks"
```
## Validating change files
Your PR build should include a step that calls `beachball check` to validate that change files are included.
Assuming you've defined the `checkchange` wrapper script suggested on the [installation page](../overview/installation), add a step to your PR build as follows.
```yml
# For GitHub Actions:
### With npm:
- run: npm run checkchange
### With yarn:
- run: yarn checkchange
# For Azure Pipelines:
### With npm:
- script: npm run checkchange
### With yarn:
- script: yarn checkchange
```
An alternative if desired is to define a separate required workflow/pipeline which skips the main install step and only runs `npx beachball check`. This has the advantage of providing faster validation and not blocking the main PR build (and hiding any later build/test/lint errors) simply for missing change files.
To prevent change files from being required for changes that will never affect the published package (such as tests, snapshots, or certain config files), use the [`ignorePatterns` option](../overview/configuration#options).
> Note: In the past, it was necessary to check out the repo's whole history for `beachball check` to work properly (such as setting `fetch-depth: 0` in `actions/checkout` for GitHub workflows). This should no longer be needed because if `beachball` detects a shallow clone, it will automatically fetch more history, and exit with an error if the current branch and target branch don't appear to share history.

Просмотреть файл

@ -6,46 +6,196 @@ category: doc
# CI Integration
For the repository and package owners who want to automate the bumping of versions based on change files with `beachball`, you'll need to provide some information for your Continuous Integration (CI) systems. These one-time setup steps will be unique for different CI system naturally, but the general idea remain the same. `beachball publish` needs write access to with are the git repo and npm registry.
There are two parts to CI integration with `beachball`:
### Git Authentication
1. [Add a PR build step](./change-files#validating-change-files) to call `beachball check` to validate that change files are included.
2. Add a release build step to call `beachball publish` to publish to npm and push back to git (this page).
There are several ways to authenticate against a git repository. Here's one way to do so with a personal token. Put this in your publishing build scripts:
To automate the bumping of package versions based on change files, you'll need to configure your release workflow/pipeline so that `beachball publish` has write access to the git repo and npm registry. The exact steps will vary between CI systems, but general concepts as well as steps for some common setups are outlined below.
```bash
git config user.email "someone@example.com"
git config user.name "someone"
git remote set-url origin https://$(user):$(pat)@github.com/someuser/someproject.git
```
## Authentication
> Note: never check in your credentials into a git repository! Simply use the "secret variable" feature to pass in the PAT here.
Automated publishing from a GitHub repo to the public npm registry (`registry.npmjs.org`) typically uses personal access tokens for authentication. These tokens are stored as secrets in your CI system. You should ensure that these secrets are only available to release builds.
These commands will give the git user a name and email. Also, the last command will set a different URL for the git remote named "origin". If you have SSH key pairs setup, you would not need to run that last line in your scripts.
For Azure DevOps repos publishing to a private registry, there are other possible approaches (such as using a service account with credentials stored in a key vault) which are not currently covered by these docs.
### NPM Authentication
### Generating tokens
To publish to a npm registry, you'll need to have access to the write-enabled access token. npm registry has [documentation](https://docs.npmjs.com/creating-and-viewing-authentication-tokens) on how to create automation tokens. Pass this token into the command line:
#### npm token
```
beachball publish -n SOME_AUTH_TOKEN
```
If publishing to the public npm registry (`registry.npmjs.org`), [create a granular access token](https://docs.npmjs.com/creating-and-viewing-access-tokens#creating-granular-access-tokens-on-the-website) with write access to only the relevant package(s) and/or scope(s). Classic automation tokens are not recommended due to their overly broad permissions.
A common requirement is to be able to publish to a private registry other than npmjs.org. You can also customize the registry URL by passing in one additional parameter:
#### GitHub token
```
beachball publish -n SOME_AUTH_TOKEN -r http://SOME_REGISTRY_URL/
```
You should use [branch protection](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule) for your `main`/`master` branch, but this creates some difficulties for pushing changes back during automated publishing.
### package.json script
The main way to allow `beachball` to push back to a repo with branch protections is by using a [classic personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#personal-access-tokens-classic) with `repo` permissions. (If the repo is part of an organization that uses SAML single sign-on (SSO), be sure to [authorize the token for SSO access](https://docs.github.com/en/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on).) Since classic PATs have broad permissions, they must only be accessible to release builds—[instructions below](#storing-tokens).
It's recommended to encapsulate any custom options in a `package.json` script:
An alternative approach is creating a classic PAT with a "machine user" account. Create a new account with an alternate email or [subaddress](https://en.wikipedia.org/wiki/Email_address#Subaddressing) (`+` address), give it contributor permissions to only this repo, and add it under "Restrict who can push to matching branches" in the branch protection rule.
(It's unclear if/when branch policy bypass support will be added for [fine-grained PATs](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-fine-grained-personal-access-token); it's been [requested](https://github.com/community/community/discussions/36441?sort=top#discussioncomment-4602435) by users with no response and doesn't seem to be on the [public roadmap](https://github.com/orgs/github/projects/4247/views/1). The [built-in `GITHUB_TOKEN`](https://docs.github.com/en/actions/security-guides/automatic-token-authentication) won't work for the same reason.)
### Storing tokens
<h4 id="secrets-github-actions">GitHub Actions</h3>
To restrict secret access to appropriate branches, use an **[environment](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment)**. (The docs for environments focus on cloud deployments or resources, but environments can also be used only for secret storage.)
1. [Create an environment](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#creating-an-environment).
2. Restrict [deployment branches](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-branches) to "Selected branches" and add a rule to allow only your release branch(es) (often `main`/`master`).
3. [Add secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-an-environment) for the npm and GitHub tokens.
4. To [use the environment](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#using-an-environment), add a key `environment: your-env-name` in your release workflow job. (Full example below.)
<h4 id="secrets-azure-pipelines">Azure Pipelines</h3>
There are a couple of options here:
- Use [secret variables in your release pipeline](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#secret-variables).
- Use [secrets in a variable group](https://learn.microsoft.com/en-us/azure/devops/pipelines/library/variable-groups?view=azure-devops&tabs=classic), which can optionally be linked to a key vault. Ensure that this variable group is only accessible to your release pipeline.
## Setting options for publishing
If you're passing any custom options besides the npm token to `beachball publish`, it's recommended to set them in either the `beachball` config (if they don't interfere with other commands), or a `package.json` script (if specific to `publish`).
For example, the following script could be used for publishing public scoped packages:
```json
{
"scripts": {
"publish:beachball": "beachball publish -n $(npm.token)"
"release": "beachball publish --access public"
}
}
```
Then inside the CI script, simply call `yarn publish:beachball` or `npm run publish:beachball`.
If you're publishing to a private feed, `registry` should be set in the overall `beachball` config, since it's also used by the `sync` command. For example, if your beachball config is in the root `package.json` (or it works the same in a config file):
```json
{
"beachball": {
"registry": "https://pkgs.dev.azure.com/some-org/_packaging/some-feed/npm/registry/"
}
}
```
## Publishing
The exact publishing setup will vary depending on your CI setup, but the overall steps are as follows:
1. Ensure the git user name and email are set, or git will reject the commit. Somewhere in your pipeline:
```bash
git config user.name "someone"
git config user.email "someone@example.com"
```
2. Set up git authentication. This could use tokens (covered below), SSH keys, or some other non-interactive method.
3. Set up npm authentication. This could use tokens passed on the command line (covered below), tokens set in `.npmrc`, or some other method.
4. Run `beachball publish`!
### GitHub repo + GitHub Actions
Here's a sample setup for publishing from a GitHub repo using GitHub actions. The environment, secret, and script names can be modified as you prefer.
This sample assumes the following:
- An environment called `release` (set up [as described above](#secrets-github-actions)) with the following secrets:
- `REPO_PAT`: A GitHub classic personal access token with admin access ([as described above](#generating-a-github-token))
- `NPM_TOKEN`: An npm token with write access to the package(s) and/or scope(s), such as a [fine-grained token for public npm](#generating-an-npm-token)
- A repo root `package.json` script `release` which runs `beachball publish`
- The build is running on a Linux/Mac agent. (This could be easily adapted to a Windows agent with different syntax in the commands.)
Note that in GitHub Actions, it's easiest to set up authentication if you set `persist-credentials: false` when checking out code.
```yml
# Example trigger configurations (choose one or more, or another setup)
# on:
# # Release on push to main
# push:
# branches: [main]
# # Release daily (see https://crontab-generator.org/ for help with schedules)
# schedule:
# - cron: '0 8 * * *'
# # Release on manual trigger (can be used alone or with other options)
# workflow_dispatch:
environment: release
# Variable syntax below assumes Linux/Mac but could be easily adapted to Windows
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
with:
# Prevent the action from storing credentials in a way that's hard to override
persist-credentials: false
# ... Other steps to prepare for publishing (install, build, test, etc) ...
# Set the name, email, and URL with PAT
- name: Set git credentials
run: |
git config user.name "someone"
git config user.email "someone@example.com"
git remote set-url origin "https://$REPO_PAT@github.com/your-org/your-repo"
env:
REPO_PAT: ${{ secrets.REPO_PAT }}
# Pass the token on the command line for publishing
- name: Publish
run: npm run release -- --token "$NPM_TOKEN"
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
```
### GitHub repo + Azure Pipelines
Here's a sample setup for publishing from a GitHub repo using Azure Pipelines. The environment, secret, and script names can be modified as you prefer.
This sample assumes the following:
- A variable group called `Beachball secrets` (set up [as described above](#secrets-azure-pipelines)) with the following secrets:
- `GITHUB_PAT`: A GitHub classic personal access token with admin access ([as described above](#generating-a-github-token))
- `NPM_TOKEN`: An npm token with write access to the package(s) and/or scope(s), such as a [fine-grained token for public npm](#generating-an-npm-token)
- A repo root `package.json` script `release` which runs `beachball publish`
- The build is running on a Linux/Mac agent. (This could be easily adapted to a Windows agent with different syntax in the commands.)
```yml
# Example trigger configurations (choose one or more, or another setup)
#
# # Release on push to main
# trigger: [main]
#
# # Release on a schedule
# # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?tabs=yaml&view=azure-devops#supported-cron-syntax
# schedules:
# - cron: '0 8 * * *'
# branches:
# include: [main]
# This group should only be accessible to the release pipeline
variables:
- group: Beachball secrets
# Variable syntax below assumes Linux/Mac but could be easily adapted to Windows
pool:
vmImage: ubuntu-latest
steps:
# ... Other steps to set up repo and prepare for publishing (install, build, test, etc) ...
# Set the name, email, and URL with PAT
- script: |
git config user.name "someone"
git config user.email "someone@example.com"
git remote set-url origin "https://$(REPO_PAT)@github.com/your-org/your-repo"
name: Set git credentials
# Pass the token on the command line for publishing
- script: npm run release -- --token "$(NPM_TOKEN)"
name: Publish
```
### Azure Repos + Azure Pipelines
This should be very similar to the GitHub version, aside from possibly the authentication method. You could potentially use personal access tokens for git and npm feed authentication (similar to above), or other methods are available which aren't currently covered here.
If you're publishing to a private Azure Artifacts npm feed, be sure to set `registry` in the `beachball` config [as described above](#setting-options-for-publishing).

Просмотреть файл

@ -13,20 +13,18 @@ There are two types of configurations:
1. repository config
2. package config
## Configuration Files
## Configuration files
Each type of configuration can be specified one of several ways. The configuration of beachball is provided by [`cosmiconfig`](https://github.com/davidtheclark/cosmiconfig), therefore, you can specify configuration in different kinds of files (and even as CLI arguments).
`beachball` uses [`cosmiconfig`](https://github.com/davidtheclark/cosmiconfig) to read its configuration, so you can specify configuration in several ways (in addition to CLI arguments).
- `beachball` key inside `package.json`
- .beachballrc
- .beachballrc.json
- beachball.config.js
> Be consistent! We encourage you to use the same convention within the same monorepo! When in doubt, just use `beachball.config.js`.
- `"beachball"` key inside `package.json`
- `.beachballrc`
- `.beachballrc.json`
- `beachball.config.js`
### `beachball.config.js`
By far the most flexible of these is, of course, the type of configuration written in JavaScript (exposed as a CommonJS module). We'll concentrate on this type of configuration.
In many cases, you'll want to use a JavaScript config file (written as a CommonJS module), since this is the most flexible and allows comments.
```js
module.exports = {
@ -36,7 +34,7 @@ module.exports = {
}
```
You can place these in either the root of a repo or within a package like so (package config overrides the repo configuration where applicable). For example:
Config files can be placed in either the root of a repo and/or within individual packages (package config overrides the repo config where applicable). For example:
```
packages/
@ -51,6 +49,8 @@ package.json
beachball.config.js
```
It's also common to have a repo-level `beachball.config.js` and any individual package overrides (if they're simple) in the `"beachball"` key in the package's `package.json`.
## Options
For the latest full list of supported options, see `RepoOptions` [in this file](https://github.com/microsoft/beachball/blob/master/src/types/BeachballOptions.ts).

Просмотреть файл

@ -6,11 +6,17 @@ category: doc
# Getting Started
Javascript ecosystem moves fast. It moves so fast that sometimes the tools need to catch up to it. One of the reasons that this particular ecosystem is so vibrant and agile is in its ability to share code via npm packages. This has led to an explosion of versions of packages in the npm registries. These days, we have public and private registries. Developers also have to keep their git repos in sync with the npm registry versions... what a hassle!
## Why Beachball?
### Beachball Workflow
The JavaScript ecosystem moves fast. One reason that this ecosystem is so vibrant and agile is its ability to share code via npm packages. Developers publishing npm packages have to keep track of what's changed in their code to determine how to bump versions, then make sure the versions in their git repo stay in sync with the npm registry...what a hassle!
First off, a ~~picture~~ diagram is worth a thousand words, so here it is:
`beachball` helps streamline this process. As developers make PRs, it helps track the types and details of changes being made. Then when it's time to publish a new version, `beachball` automates publishing version bumps to npm, generating changelogs, and syncing changes back to the git repo.
## Beachball workflow
`beachball` fits into your workflow without any extra configuration (by default).
For the workflow, a ~~picture~~ diagram is worth a thousand words, so here it is:
```mermaid
graph TB
@ -37,14 +43,20 @@ graph TB
end
```
### Brief Description of Workflow
**Inner loop:** When you've made some commits to your branch, simply run [`beachball change`](../cli/change) to generate change files.
Without any configuration, `beachball` fits into your workflow. When you have made some commits to your branch, simply fire up `beachball change` to generate change files. During PR review and feedback loops, your colleagues might remind you to modify your change file descriptions or change type. This then gets merged to the target branch (e.g. `master`). After this, `beachball publish` is either called by a continuous integration (CI) system or manually by a developer. When this is called, three things happen:
**Pull request:** The PR build runs [`beachball check`](../cli/check) to verify change files are included. Your colleagues can review the change file description and type, and easily propose changes if needed. The PR with change files then gets merged to the target branch (e.g. `main`).
1. All change files are deleted (more than one change file can be checked in before a single publish happens)
**Publish:** When it's time to release, [`beachball publish`](../cli/publish) is either called [by a continuous integration (CI) system](../concepts/ci-integration) or manually by a developer. This does three things:
1. All change files are deleted
2. Versions are bumped, checked in locally and pushed remotely
3. npm packages are published to a public or private registry
At that point, your repo is ready for the next change!
## Next steps
- [Install `beachball`](./installation)
- [Learn more about change files](../concepts/change-files)
- [Set up CI integration](../concepts/ci-integration)

Просмотреть файл

@ -6,25 +6,25 @@ category: doc
# Installation
There are two options to install `beachball`.
## CLI setup
### Option 1: no install
The primary way to use `beachball` is by installing it as a `devDependency` and configuring wrapper scripts. (You can also run `beachball` via `npx`.)
Thanks to `npx`, you can use `beachball` without any installation:
> Note: In a monorepo, `beachball` should be installed at and run from the repo root only.
```bash
npx beachball --help
```
### Automatic setup
### Option 2: Install and Run as NPM Scripts
Run `npx beachball init` to automatically run the steps outlined below.
To get started, place this in the `devDependencies` section of your `package.json`:
### Manual setup
To get started, install `beachball` as a `devDependency`:
```bash
npm install -D beachball
```
or for yarn users:
or for yarn users (add `-W` if in a monorepo):
```bash
yarn add -D beachball
@ -36,8 +36,30 @@ After that, add some scripts to call `beachball` commands:
{
"scripts": {
"change": "beachball change",
"check": "beachball check",
"beachball:publish": "beachball publish"
"checkchange": "beachball check",
"release": "beachball publish"
}
}
```
You should also ensure that a [`repository`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#repository) URL is set in your repo root `package.json` to help `beachball` figure out which remote to compare against when determining changes. For example:
```json
{
"repository": {
"type": "git",
"url": "https://github.com/your-org-name/your-repo-name.git"
}
}
```
## Local development workflow
After making and committing changes in a branch, run `npm run change` or `yarn change` to generate change files. See the [change files page](../concepts/change-files) for more details.
## CI integration
There are two parts to CI integration with `beachball`:
1. [Add a PR build step](../concepts/change-files#validating-change-files) to call `beachball check` to validate that change files are included.
2. [Add a release build step](../concepts/ci-integration) to call `beachball publish` to publish to npm and push back to git.

Просмотреть файл

@ -1,8 +1,17 @@
import { BeachballOptions } from '../types/BeachballOptions';
import * as fs from 'fs';
import * as fs from 'fs-extra';
import * as path from 'path';
import { findProjectRoot } from 'workspace-tools';
import { npm } from '../packageManager/npm';
import { PackageJson } from '../types/PackageInfo';
function errorExit(message: string) {
console.error(message);
console.log(
'You can still set up beachball manually by following the instructions here: https://microsoft.github.io/beachball/overview/getting-started.html'
);
process.exit(1);
}
export async function init(options: BeachballOptions) {
let root: string;
@ -15,22 +24,45 @@ export async function init(options: BeachballOptions) {
const packageJsonFilePath = path.join(root, 'package.json');
if (fs.existsSync(packageJsonFilePath)) {
const beachballInfo = JSON.parse(npm(['info', 'beachball', '--json']).stdout.toString());
const beachballVersion = beachballInfo['dist-tags'].latest;
if (!fs.existsSync(packageJsonFilePath)) {
errorExit(`Cannot find package.json at ${packageJsonFilePath}`);
}
const packageJson = JSON.parse(fs.readFileSync(packageJsonFilePath, 'utf-8'));
packageJson.devDependencies = packageJson.devDependencies ?? {};
packageJson.devDependencies.beachball = beachballVersion;
packageJson.scripts = packageJson.scripts ?? {};
packageJson.scripts.checkchange = 'beachball check';
packageJson.scripts.change = 'beachball change';
packageJson.scripts.release = 'beachball publish';
const npmResult = npm(['info', 'beachball', '--json']);
if (!npmResult.success) {
errorExit('Failed to retrieve beachball version from npm');
}
fs.writeFileSync(packageJsonFilePath, JSON.stringify(packageJson, null, 2));
let beachballVersion = '';
try {
const beachballInfo = JSON.parse(npmResult.stdout.toString());
beachballVersion = beachballInfo['dist-tags'].latest;
} catch (err) {
errorExit("Couldn't parse beachball version from npm");
}
console.log(
'beachball has been initialized, please run `yarn` or `npm install` to install beachball into your repo'
let packageJson = {} as PackageJson;
try {
packageJson = fs.readJSONSync(packageJsonFilePath, 'utf-8');
} catch (err) {
errorExit(`Failed to read package.json at ${packageJsonFilePath}`);
}
packageJson.devDependencies ??= {};
packageJson.devDependencies.beachball = beachballVersion;
packageJson.scripts ??= {};
packageJson.scripts.checkchange = 'beachball check';
packageJson.scripts.change = 'beachball change';
packageJson.scripts.release = 'beachball publish';
fs.writeFileSync(packageJsonFilePath, JSON.stringify(packageJson, null, 2));
if (!packageJson.repository) {
console.warn(
'Please add a "repository" field to your repo root package.json so beachball always ' +
'knows which remote to use when checking for changes.'
);
}
console.log('beachball has been initialized! Please run `yarn` or `npm install` to install beachball in your repo.');
}

Просмотреть файл

@ -3,33 +3,33 @@ import { BeachballOptions } from '../types/BeachballOptions';
export function getDefaultOptions() {
return {
access: 'restricted',
all: false,
authType: 'authtoken',
branch: 'origin/master',
bump: true,
bumpDeps: true,
canaryName: undefined,
changehint: 'Run "beachball change" to create a change file',
command: 'change',
defaultNpmTag: 'latest',
depth: undefined,
disallowedChangeTypes: null,
fetch: true,
generateChangelog: true,
gitTags: true,
gitTimeout: undefined,
message: '',
publish: true,
bumpDeps: true,
push: true,
registry: 'https://registry.npmjs.org/',
token: '',
gitTags: true,
tag: '',
yes: env.isCI,
access: 'restricted',
changehint: 'Run "beachball change" to create a change file',
type: null,
fetch: true,
version: false,
disallowedChangeTypes: null,
defaultNpmTag: 'latest',
scope: null,
retries: 3,
scope: null,
tag: '',
timeout: undefined,
gitTimeout: undefined,
bump: true,
canaryName: undefined,
generateChangelog: true,
depth: undefined,
token: '',
type: null,
version: false,
yes: env.isCI,
} as BeachballOptions;
}

Просмотреть файл

@ -61,7 +61,10 @@ export interface CliOptions
}
export interface RepoOptions {
/** access level for npm publish */
/**
* Access level for npm publish
* @default 'restricted'
*/
access: 'public' | 'restricted';
/**
* The target branch. In the repo or CLI config, this can be specified without a remote name
@ -69,45 +72,86 @@ export interface RepoOptions {
*
* (In the resolved config used internally, the remote name should *usually* be included,
* unless neither a remote name nor `package.json` `repository` was specified.)
* @default 'origin/master'
*/
branch: string;
/** Bump dependent packages during publish (bump A if A depends on B) */
/**
* Bump dependent packages during publish (bump A if A depends on B)
* @default true
*/
bumpDeps: boolean;
/** Options for customizing change file prompt. */
changeFilePrompt?: ChangeFilePromptOptions;
/** Prerelease prefix for packages that are specified to receive a prerelease bump */
/** Hint message for when change files are not detected but required */
/**
* Hint message for when change files are not detected but required
* @default 'Run "beachball change" to create a change file'
*/
changehint: string;
/** Options for customizing changelog rendering */
changelog?: ChangelogOptions;
/** The default dist-tag used for npm publish */
/**
* The default dist-tag used for npm publish
* @default 'latest'
*/
defaultNpmTag: string;
/** What change types are disallowed */
disallowedChangeTypes: ChangeType[] | null;
/** Fetch from remote before doing diff comparisons (default true) */
/**
* Fetch from remote before doing diff comparisons
* @default true
*/
fetch: boolean;
/** Whether to generate changelog files */
/**
* Whether to generate changelog files
* @default true
*/
generateChangelog: boolean;
/** Options for bumping package versions together */
groups?: VersionGroupOptions[];
/** Whether to create git tags for published packages (default true) */
/**
* Whether to create git tags for published packages
* @default true
*/
gitTags: boolean;
/** Custom pre/post publish actions */
hooks?: HooksOptions;
ignorePatterns?: string[];
message: string;
/** The directory to run beachball in (default `process.cwd()`) */
path: string;
prereleasePrefix?: string | null;
/** Ignore changes in these files (minimatch patterns; negations not supported) */
/** Whether to publish to the npm registry (default true) */
ignorePatterns?: string[];
/** For the `change` command, change message. For the `publish` command, commit message. */
message: string;
/**
* The directory to run beachball in
* @default process.cwd()
*/
path: string;
/** Prerelease prefix for packages that are specified to receive a prerelease bump */
prereleasePrefix?: string | null;
/**
* Whether to publish to the npm registry
* @default true
*/
publish: boolean;
/** Whether to push to the remote git branch when publishing (default true) */
/**
* Whether to push to the remote git branch when publishing
* @default true
*/
push: boolean;
/** Target npm registry for publishing */
/**
* Target npm registry for publishing
* @default 'https://registry.npmjs.org/'
*/
registry: string;
/** number of retries for a package publish before failing */
/**
* Number of retries for a package publish before failing
* @default 3
*/
retries: number;
/** Filters paths that beachball uses to find packages */
scope?: string[] | null;
/** npm dist-tag when publishing (default 'latest') */
/**
* npm dist-tag when publishing
* @default 'latest'
*/
tag: string;
/** Transformations for change files */
transform?: TransformOptions;
@ -130,6 +174,9 @@ export interface PackageOptions {
shouldPublish?: false | undefined;
}
/**
* Options for bumping package versions together.
*/
export interface VersionGroupOptions {
/** minimatch pattern (or array of minimatch) to detect which packages should be included in this group */
include: string | string[];

Просмотреть файл

@ -21,6 +21,7 @@ export interface PackageJson {
devDependencies?: PackageDeps;
peerDependencies?: PackageDeps;
private?: boolean;
scripts?: Record<string, string>;
beachball?: BeachballOptions;
/** Overrides applied during publishing */
publishConfig?: Pick<