-
Notifications
You must be signed in to change notification settings - Fork 875
[Release] Automate most manual steps #9419
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
Changes from all commits
65f07ec
5320ab3
efb7da0
88aa4e9
0588968
e583ecf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # Official release preparation script (pre-PR) | ||
| # | ||
| # Automates initial steps of the process: | ||
| # - Log out of npm | ||
| # - Checkout main, pull latest from upstream | ||
| # - Create a timestamped release branch | ||
| # - Build the release CLI | ||
| # - Run the release dry-run (interactive) | ||
| # - (User confirms in the interactive CLI) | ||
| # - Push the branch to origin and open a PR | ||
| # | ||
| # Usage: yarn release:prep | ||
| # | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| RED='\033[0;31m' | ||
| GREEN='\033[0;32m' | ||
| YELLOW='\033[0;33m' | ||
| BOLD='\033[1m' | ||
| RESET='\033[0m' | ||
|
|
||
| step() { | ||
| echo "" | ||
| echo -e "${GREEN}${BOLD}[$1]${RESET} $2" | ||
| } | ||
|
|
||
| warn() { | ||
| echo -e "${YELLOW}Warning:${RESET} $1" | ||
| } | ||
|
|
||
| error() { | ||
| echo -e "${RED}Error:${RESET} $1" >&2 | ||
| exit 1 | ||
| } | ||
|
|
||
| REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || error "Not inside a git repository" | ||
| cd "$REPO_ROOT" | ||
|
|
||
| PACKAGE_DIRS=(packages/eui packages/eui-theme-common packages/eui-theme-borealis packages/docusaurus-preset packages/docusaurus-theme packages/eslint-plugin) | ||
|
|
||
| git remote get-url upstream &>/dev/null || error "'upstream' remote not found. Please add it: git remote add upstream [email protected]:elastic/eui.git" | ||
|
|
||
| # Bail early if there are uncommitted changes | ||
| if [[ -n "$(git status --porcelain)" ]]; then | ||
| error "Working tree is dirty. Please commit or stash your changes before running this script." | ||
| fi | ||
|
|
||
| step "1/8" "Ensuring npm is not authenticated..." | ||
| npm logout 2>/dev/null || true | ||
| yarn npm logout 2>/dev/null || true | ||
|
|
||
| step "2/8" "Checking out main branch..." | ||
| git checkout main | ||
|
|
||
| step "3/8" "Pulling latest changes from upstream..." | ||
| git pull upstream main | ||
|
|
||
| BRANCH_NAME="release/$(date +%s)" | ||
| step "4/8" "Creating release branch: ${BOLD}${BRANCH_NAME}${RESET}" | ||
| git checkout -b "$BRANCH_NAME" | ||
|
|
||
| step "5/8" "Installing dependencies and building release CLI..." | ||
| yarn | ||
| yarn workspace @elastic/eui-release-cli run build | ||
|
|
||
| step "6/8" "Starting release process (dry-run)..." | ||
| echo "" | ||
| yarn release run official --dry-run --allow-custom --skip-auth-check --use-auth-token | ||
|
|
||
| # Check for uncommitted changes after the release CLI run | ||
| if [[ -n "$(git status --porcelain)" ]]; then | ||
| echo "" | ||
| warn "There are uncommitted changes in the working tree:" | ||
| git status --short | ||
| echo "" | ||
| read -r -p "Continue pushing without these changes? They won't be included in the PR. (y/N) " confirm | ||
| if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then | ||
| echo "" | ||
| echo "Stopped. Commit your changes and re-run from step 7 manually:" | ||
| echo " git push -u origin $BRANCH_NAME" | ||
| exit 0 | ||
| fi | ||
| fi | ||
|
|
||
| step "7/8" "Pushing branch to origin..." | ||
| git push -u origin "$BRANCH_NAME" | ||
|
|
||
| step "8/8" "Opening release PR..." | ||
|
|
||
| PR_TITLE_PARTS="" | ||
| PR_BODY_LINES="" | ||
|
|
||
| for pkg_dir in "${PACKAGE_DIRS[@]}"; do | ||
| pkg_json="${pkg_dir}/package.json" | ||
| [[ -f "$pkg_json" ]] || continue | ||
|
|
||
| new_version=$(node -p "require('./${pkg_json}').version") | ||
| old_version=$(git show "main:${pkg_json}" 2>/dev/null | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).version" 2>/dev/null || echo "") | ||
|
|
||
| if [[ -n "$old_version" && "$new_version" != "$old_version" ]]; then | ||
| pkg_name=$(node -p "require('./${pkg_json}').name") | ||
|
|
||
| if [[ -n "$PR_TITLE_PARTS" ]]; then | ||
| PR_TITLE_PARTS="${PR_TITLE_PARTS}, ${pkg_name} v${new_version}" | ||
| else | ||
| PR_TITLE_PARTS="${pkg_name} v${new_version}" | ||
| fi | ||
| PR_BODY_LINES="${PR_BODY_LINES}\n- \`${pkg_name}\` - v${old_version} → v${new_version}" | ||
| fi | ||
| done | ||
|
|
||
| if [[ -z "$PR_TITLE_PARTS" ]]; then | ||
| error "No changed package versions detected. Did the release dry-run update any versions?" | ||
| fi | ||
|
|
||
| PR_TITLE="Release: ${PR_TITLE_PARTS}" | ||
| PR_BODY="$(printf "Packages to release:\n${PR_BODY_LINES}")" | ||
|
|
||
| PR_URL=$(gh pr create \ | ||
| --title "$PR_TITLE" \ | ||
| --body "$PR_BODY" \ | ||
| --label "skip-changelog" \ | ||
| --label "release" \ | ||
| --base main) | ||
|
|
||
| echo "" | ||
| echo -e "${GREEN}${BOLD}Prep complete!${RESET}" | ||
| echo "" | ||
| echo -e " PR: ${BOLD}${PR_URL}${RESET}" | ||
| echo "" | ||
| echo -e " ${BOLD}After the PR is merged:${RESET}" | ||
| echo -e " yarn release:publish" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # Official release publish script (post-merge) | ||
| # | ||
| # Automates final steps of the process: | ||
| # - Detects the EUI version and changed workspaces | ||
| # - Tags the merge commit | ||
| # - Pushes the tag to upstream | ||
| # - Triggers the GitHub Actions release workflow | ||
| # - Creates a GitHub release | ||
| # | ||
| # Usage: yarn release:publish [merge-commit-sha] | ||
| # | ||
| # If no SHA is provided, defaults to HEAD on main. | ||
| # | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| RED='\033[0;31m' | ||
| GREEN='\033[0;32m' | ||
| YELLOW='\033[0;33m' | ||
| BOLD='\033[1m' | ||
| RESET='\033[0m' | ||
|
|
||
| step() { | ||
| echo "" | ||
| echo -e "${GREEN}${BOLD}[$1]${RESET} $2" | ||
| } | ||
|
|
||
| warn() { | ||
| echo -e "${YELLOW}Warning:${RESET} $1" | ||
| } | ||
|
|
||
| error() { | ||
| echo -e "${RED}Error:${RESET} $1" >&2 | ||
| exit 1 | ||
| } | ||
|
|
||
| REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || error "Not inside a git repository" | ||
| cd "$REPO_ROOT" | ||
|
|
||
| PACKAGE_DIRS=(packages/eui packages/eui-theme-common packages/eui-theme-borealis packages/docusaurus-preset packages/docusaurus-theme packages/eslint-plugin) | ||
|
|
||
| git remote get-url upstream &>/dev/null || error "'upstream' remote not found" | ||
|
|
||
| if [[ -n "$(git status --porcelain)" ]]; then | ||
| error "Working tree is dirty. Please commit or stash your changes before running this script." | ||
| fi | ||
|
|
||
| step "1/6" "Updating main branch..." | ||
| git checkout main | ||
| git pull upstream main | ||
| git fetch upstream --tags | ||
|
acstll marked this conversation as resolved.
|
||
|
|
||
| MERGE_SHA="${1:-$(git rev-parse HEAD)}" | ||
|
|
||
| step "2/6" "Detecting release details from ${BOLD}${MERGE_SHA:0:12}${RESET}..." | ||
|
|
||
| EUI_VERSION=$(git show "${MERGE_SHA}:packages/eui/package.json" | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).version") | ||
| TAG_NAME="v${EUI_VERSION}" | ||
|
|
||
| if git rev-parse "$TAG_NAME" &>/dev/null; then | ||
| error "Tag ${TAG_NAME} already exists. Has this release already been published?" | ||
| fi | ||
|
|
||
| PREV_TAG=$(git describe --tags --abbrev=0 "${MERGE_SHA}^" 2>/dev/null) || error "Could not find a previous release tag" | ||
|
|
||
| # Detect changed workspaces and collect changelog entries for the GitHub release | ||
| CHANGED_WORKSPACES="" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: You can now get it directly from
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's do so, and of course use the new |
||
| RELEASE_BODY="" | ||
|
|
||
| for pkg_dir in "${PACKAGE_DIRS[@]}"; do | ||
| pkg_json="${pkg_dir}/package.json" | ||
|
|
||
| git show "${MERGE_SHA}:${pkg_json}" &>/dev/null || continue | ||
|
|
||
| new_version=$(git show "${MERGE_SHA}:${pkg_json}" | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).version") | ||
| old_version=$(git show "${PREV_TAG}:${pkg_json}" 2>/dev/null | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).version" 2>/dev/null || echo "") | ||
|
|
||
| if [[ "$new_version" != "$old_version" ]]; then | ||
| pkg_name=$(git show "${MERGE_SHA}:${pkg_json}" | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).name") | ||
|
|
||
| if [[ -n "$CHANGED_WORKSPACES" ]]; then | ||
| CHANGED_WORKSPACES="${CHANGED_WORKSPACES},${pkg_name}" | ||
| else | ||
| CHANGED_WORKSPACES="${pkg_name}" | ||
| fi | ||
|
|
||
| # Extract changelog section for this version | ||
| changelog_file=$(ls -t "${pkg_dir}"/changelogs/CHANGELOG_*.md 2>/dev/null | head -1) | ||
| if [[ -n "$changelog_file" ]]; then | ||
| escaped_version="${new_version//./\\.}" | ||
| changelog_section=$(awk "/^## \[\`v${escaped_version}\`\]/{found=1; next} /^## \[/{if(found) exit} found" "$changelog_file") | ||
| if [[ -n "$changelog_section" ]]; then | ||
| RELEASE_BODY="${RELEASE_BODY}### \`${pkg_name}\` [v${new_version}](https://github.com/elastic/eui/blob/main/${changelog_file}) | ||
| ${changelog_section} | ||
| " | ||
|
acstll marked this conversation as resolved.
|
||
| fi | ||
| fi | ||
| fi | ||
| done | ||
|
|
||
| if [[ -z "$CHANGED_WORKSPACES" ]]; then | ||
| error "No changed workspaces detected. Are you sure the release PR was merged?" | ||
| fi | ||
|
|
||
| step "3/6" "Release summary" | ||
| echo "" | ||
| echo -e " Tag: ${BOLD}${TAG_NAME}${RESET}" | ||
| echo -e " Commit: ${BOLD}${MERGE_SHA:0:12}${RESET}" | ||
| echo -e " Previous tag: ${BOLD}${PREV_TAG}${RESET}" | ||
| echo -e " Workspaces: ${BOLD}${CHANGED_WORKSPACES}${RESET}" | ||
| echo "" | ||
| read -r -p "Proceed with tagging and triggering the release? (y/N) " confirm | ||
| if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then | ||
| echo "Aborted." | ||
| exit 0 | ||
| fi | ||
|
|
||
| step "4/6" "Creating and pushing tag ${BOLD}${TAG_NAME}${RESET}..." | ||
| git tag -a "$TAG_NAME" "$MERGE_SHA" -m "@elastic/eui ${TAG_NAME}" | ||
| git push upstream "$TAG_NAME" --no-verify | ||
|
|
||
| step "5/6" "Triggering release workflow..." | ||
| gh workflow run release.yml \ | ||
| --repo elastic/eui \ | ||
| -f release_ref="$MERGE_SHA" \ | ||
| -f type=official \ | ||
| -f workspaces="$CHANGED_WORKSPACES" \ | ||
| -f dry_run=false | ||
|
|
||
| step "6/6" "Creating GitHub release..." | ||
| gh release create "$TAG_NAME" \ | ||
| --repo elastic/eui \ | ||
| --title "$TAG_NAME" \ | ||
| --notes "$RELEASE_BODY" | ||
|
|
||
| echo "" | ||
| echo -e "${GREEN}${BOLD}Release triggered!${RESET}" | ||
| echo "" | ||
| echo -e " Release: ${BOLD}https://github.com/elastic/eui/releases/tag/${TAG_NAME}${RESET}" | ||
| echo -e " Workflow: ${BOLD}https://github.com/elastic/eui/actions/workflows/release.yml${RESET}" | ||
Uh oh!
There was an error while loading. Please reload this page.