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

build: introduce trunk based development workflow #3177

Merged
merged 2 commits into from
Oct 28, 2024
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
62 changes: 62 additions & 0 deletions .github/workflows/maintenance-changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: cherry-pick changelog from release branch into default branch

on:
push:
tags: ['*.*']

permissions:
actions: write
issues: write

jobs:
cherry_pick:
runs-on: ubuntu-latest
outputs:
failed_release_version: ${{ steps.cherry_pick_error.outputs.failed_release_version }}
steps:
- name: Get token
id: get_token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.MAINTENANCE_APP_ID }}
private_key: ${{ secrets.MAINTENANCE_APP_PEM }}
- uses: actions/checkout@v4
with:
token: ${{ steps.get_token.outputs.app_token }}
fetch-depth: 0
- name: Get tag name
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Get commit for tag
run: echo "TAG_COMMIT=$(git rev-list -n 1 ${{ env.RELEASE_VERSION }})" >> $GITHUB_ENV
- name: Cherry-pick CHANGELOG.md into ${{ github.event.repository.default_branch }}
run: |
git config user.email "github-actions@github.com"
git config user.name "github-actions"
git checkout ${{ github.event.repository.default_branch }}
git show ${{ env.TAG_COMMIT }} -- CHANGELOG.md | git apply -
git commit -a -m "chore: update changelog"
git push
- name: Handling error
if: ${{ failure() }}
id: cherry_pick_error
run: echo "failed_release_version=$(echo ${{ env.RELEASE_VERSION }})" >> $GITHUB_OUTPUT

update_maintenance_issue:
runs-on: ubuntu-latest
needs: cherry_pick
if: always() && needs.cherry_pick.result == 'failure'
steps:
- run: echo ${{ needs.cherry_pick.outputs.failed_release_version }}
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
if: needs.cherry_pick.outputs.failed_release_version
with:
node-version-file: .nvmrc
- run: yarn install --frozen-lockfile --non-interactive
if: needs.cherry_pick.outputs.failed_release_version
- name: Update maintenance issue
if: needs.cherry_pick.outputs.failed_release_version
run: yarn ts-hooks scripts/update-maintenance-issue.ts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FAILED_RELEASE: ${{ needs.cherry_pick.outputs.failed_release_version }}
85 changes: 85 additions & 0 deletions .github/workflows/maintenance-cherry-pick.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: cherry-pick into target branches

on:
pull_request:
types: [closed]

permissions:
actions: write
issues: write

jobs:
# Check if labels exist before executing the next job.
# We cannot use `if` because the matrix is evaluated before the `if` statement.
check_labels:
runs-on: ubuntu-latest
if: ${{ join(github.event.pull_request.labels) != '' }}
steps:
- run: echo Labels are not empty, continuing

cherry_pick:
needs: [check_labels]
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true &&
github.event.pull_request.user.login != 'renovate[bot]'
outputs:
failed_branches: ${{ steps.update_failed_branches.outputs.failed_branches }}
strategy:
matrix:
label: ${{ github.event.pull_request.labels.*.name }}

steps:
- name: Get token
id: get_token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.MAINTENANCE_APP_ID }}
private_key: ${{ secrets.MAINTENANCE_APP_PEM }}
- name: Get branch name from label
id: branch_name
run: |
echo "branch=$(echo ${{ matrix.label }} | sed -n 's/target: \([0-9]*.x\).*/\1/p')" >> $GITHUB_OUTPUT

- uses: actions/checkout@v4
if: steps.branch_name.outputs.branch
with:
token: ${{ steps.get_token.outputs.app_token }}
fetch-depth: 0

- name: Cherry-pick changes into ${{ steps.branch_name.outputs.branch }}
if: steps.branch_name.outputs.branch
run: |
git checkout ${{ steps.branch_name.outputs.branch }}
git -c user.name="github-actions" -c user.email="github-actions@github.com" cherry-pick ${{ github.sha }}
git push

- name: Update failed branches
if: ${{ failure() }}
id: update_failed_branches
run: |
echo "failed_branches=$(echo ${{ steps.branch_name.outputs.branch }} ${{ steps.update_failed_branches.outputs.failed_branches}})" >> $GITHUB_OUTPUT

update_maintenance_issue:
runs-on: ubuntu-latest
needs: cherry_pick
if: always() && needs.cherry_pick.result == 'failure' &&
github.event.pull_request.user.login != 'renovate[bot]'

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
if: needs.cherry_pick.outputs.failed_branches
with:
node-version-file: .nvmrc

- run: yarn install --frozen-lockfile --non-interactive
if: needs.cherry_pick.outputs.failed_branches

- name: Update maintenance issue
if: needs.cherry_pick.outputs.failed_branches
run: yarn ts-hooks scripts/update-maintenance-issue.ts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.number }}
FAILED_BRANCHES: ${{ needs.cherry_pick.outputs.failed_branches }}
28 changes: 28 additions & 0 deletions .github/workflows/maintenance-tagging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Add or remove maintenance labels

on:
pull_request:
types: [opened, edited, labeled]
branches: [main] # target branch

env:
TARGET_RELEASE: 1.x

permissions:
pull-requests: write

jobs:
add_label:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login != 'renovate[bot]'
steps:
- name: Add target label
if: "${{ !contains(github.event.pull_request.body, 'BREAKING CHANGE:') && !contains(github.event.pull_request.labels.*.name, 'target: major') }}"
uses: actions-ecosystem/action-add-labels@v1
with:
labels: 'target: ${{ env.TARGET_RELEASE }}'
- name: Remove target label
if: "${{ contains(github.event.pull_request.body, 'BREAKING CHANGE:') || contains(github.event.pull_request.labels.*.name, 'target: major') }}"
uses: actions-ecosystem/action-remove-labels@v1
with:
labels: 'target: ${{ env.TARGET_RELEASE }}'
5 changes: 4 additions & 1 deletion .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Release Please
on:
push:
branches:
- main
- '*.x'

# Documentation:
# https://github.com/googleapis/release-please
Expand All @@ -26,6 +26,9 @@ jobs:
release-type: node
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
# The short ref name of the branch or tag that triggered
# the workflow run. For example, `main` or `1.x`
target-branch: ${{ github.ref_name }}
- name: Release Info
run: echo "$RELEASE_OUTPUT"
env:
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
"lit-analyzer": "2.0.3",
"madge": "8.0.0",
"npm-run-all2": "7.0.1",
"octokit": "4.0.2",
"playwright": "1.47.2",
"postcss": "8.4.47",
"prettier": "3.3.3",
Expand Down
1 change: 1 addition & 0 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"nvm": {
"enabled": false
},
"baseBranches": ["main", "1.x"],
"lockFileMaintenance": {
"schedule": ["before 7am on monday"],
"enabled": true
Expand Down
89 changes: 89 additions & 0 deletions scripts/update-maintenance-issue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { fileURLToPath } from 'url';

import { Octokit } from 'octokit';

const maintenanceIssueNumber = 3176;

const githubToken = process.env['GITHUB_TOKEN'];
const pullRequestNumber = parseInt(process.env['PR_NUMBER']!, 10);
const failedBranches = process.env['FAILED_BRANCHES']?.split(' ').join(', ');
const failedReleaseVersion = process.env['FAILED_RELEASE'];

const repoConfig = {
owner: 'sbb-design-systems',
repo: 'lyne-components',
};

const issuePath = {
...repoConfig,
issue_number: maintenanceIssueNumber,
};

const prPath = {
...repoConfig,
pull_number: pullRequestNumber,
};

class MaintenanceIssueUpdater {
public constructor(
private _octokit: Octokit,
private _now: Date,
) {}

public async run(): Promise<void> {
if (!failedBranches && !failedReleaseVersion) {
throw new Error(
`Unable to update maintenance issue.
Please either specify FAILED_BRANCHES or FAILED_RELEASE`,
);
}

const issue = await this._octokit.rest.issues.get(issuePath);

if (!issue.data.body) {
throw new Error('Could not load issue body');
}

const hint = '**Cherry-pick failed for the following pull requests / releases**';
const dateInfo = `${this._now.toISOString()}`;
let openTasks = this._extractOpenTasks(issue.data.body);
let newTask;

if (failedBranches) {
const pr = await this._octokit.rest.pulls.get(prPath);
if (!pr.data.title || !pr.data.html_url) {
throw new Error('Could not load pull request');
}

newTask = `- [ ] PR [${pr.data.title}](${pr.data.html_url}) could not be cherry-picked into branch ${failedBranches})`;
} else {
newTask = `- [ ] CHANGELOG.md could not be cherry-picked for release ${failedReleaseVersion}`;
}

openTasks = this._addNewTask(openTasks, newTask);

return this._octokit.rest.issues.update({
...issuePath,
body: `${hint}\n${openTasks.join('\n')}\n\n${dateInfo}`,
});
}

private _extractOpenTasks(issueBody: string = ''): string[] {
return issueBody.split('\n').filter((line) => line.startsWith('- [ ]'));
}

private _addNewTask(tasks: string[], newTask: string): string[] {
const newTasks = [newTask, ...tasks];
return [...new Set(newTasks)];
}
}

if (process.argv[1] === fileURLToPath(import.meta.url)) {
const maintenanceIssueUpdater = new MaintenanceIssueUpdater(
new Octokit({
auth: githubToken,
}),
new Date(),
);
maintenanceIssueUpdater.run();
}
Loading
Loading