Skip to content

Commit 6923baf

Browse files
Merge pull request #7 from codemod/chore/align-release-automation
Align release and publish automation
2 parents 867a072 + 68a9491 commit 6923baf

7 files changed

Lines changed: 191 additions & 74 deletions

File tree

.github/workflows/ci.yml

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,67 @@ name: CI
22

33
on:
44
push:
5+
branches:
6+
- main
57
pull_request:
8+
branches:
9+
- main
10+
11+
permissions:
12+
contents: read
613

714
jobs:
815
checks:
916
runs-on: ubuntu-latest
10-
permissions:
11-
contents: read
1217
steps:
1318
- uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
1422
- uses: pnpm/action-setup@v4
1523
with:
1624
version: 9.14.2
25+
1726
- uses: actions/setup-node@v4
1827
with:
19-
node-version: 20
28+
node-version-file: .nvmrc
2029
cache: pnpm
30+
2131
- run: pnpm install --frozen-lockfile
22-
- run: pnpm run test
32+
2333
- run: pnpm run check-types
34+
35+
- name: Run tests for changed codemods
36+
shell: bash
37+
env:
38+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
39+
EVENT_NAME: ${{ github.event_name }}
40+
HEAD_SHA: ${{ github.sha }}
41+
run: |
42+
if [ "$EVENT_NAME" != "pull_request" ]; then
43+
pnpm run test
44+
exit 0
45+
fi
46+
47+
changed_paths=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
48+
49+
if echo "$changed_paths" | grep -qE '^(package\.json|pnpm-lock\.yaml|pnpm-workspace\.yaml|\.github/workflows/ci\.yml)$'; then
50+
pnpm run test
51+
exit 0
52+
fi
53+
54+
filters=$(
55+
echo "$changed_paths" \
56+
| grep '^codemods/' \
57+
| cut -d/ -f1-2 \
58+
| sort -u \
59+
| sed 's|^|--filter ./|' || true
60+
)
61+
62+
if [ -z "$filters" ]; then
63+
echo "No codemod packages affected; skipping tests."
64+
exit 0
65+
fi
66+
67+
# shellcheck disable=SC2086
68+
pnpm $filters test

.github/workflows/publish.yml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
name: Publish
2+
3+
on:
4+
workflow_run:
5+
workflows:
6+
- CI
7+
types:
8+
- completed
9+
workflow_dispatch:
10+
inputs:
11+
codemod_name:
12+
description: Codemod directory name under codemods/
13+
required: true
14+
type: string
15+
16+
concurrency: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.ref }}
17+
18+
permissions:
19+
id-token: write
20+
contents: write
21+
22+
jobs:
23+
tag:
24+
name: Tag released versions
25+
if: >-
26+
github.event.workflow_run.conclusion == 'success' &&
27+
github.event.workflow_run.event == 'push' &&
28+
github.event.workflow_run.head_branch == 'main'
29+
runs-on: ubuntu-latest
30+
outputs:
31+
changed_dirs: ${{ steps.tag.outputs.changed_dirs }}
32+
steps:
33+
- uses: actions/checkout@v4
34+
with:
35+
ref: ${{ github.event.workflow_run.head_sha }}
36+
fetch-depth: 0
37+
38+
- uses: pnpm/action-setup@f520eceda224fe1a4aed5a2a27a194379a409996 # v6
39+
40+
- uses: actions/setup-node@v4
41+
with:
42+
node-version-file: .nvmrc
43+
cache: pnpm
44+
45+
- run: pnpm install --frozen-lockfile
46+
47+
- name: Detect pending changesets
48+
id: pending
49+
run: |
50+
count="$(find .changeset -maxdepth 1 -type f -name '*.md' ! -name 'README.md' | wc -l | tr -d ' ')"
51+
echo "count=$count" >> "$GITHUB_OUTPUT"
52+
53+
- name: Tag released versions
54+
if: steps.pending.outputs.count == '0'
55+
id: tag
56+
run: node scripts/tag-and-publish.mjs
57+
58+
publish:
59+
name: Publish ${{ matrix.dir }}
60+
needs: tag
61+
if: >-
62+
github.event_name == 'workflow_run' &&
63+
needs.tag.outputs.changed_dirs != '' &&
64+
needs.tag.outputs.changed_dirs != '[]'
65+
runs-on: ubuntu-latest
66+
strategy:
67+
fail-fast: false
68+
matrix:
69+
dir: ${{ fromJson(needs.tag.outputs.changed_dirs) }}
70+
steps:
71+
- uses: actions/checkout@v4
72+
with:
73+
ref: ${{ github.event.workflow_run.head_sha }}
74+
75+
- uses: pnpm/action-setup@f520eceda224fe1a4aed5a2a27a194379a409996 # v6
76+
77+
- uses: actions/setup-node@v4
78+
with:
79+
node-version-file: .nvmrc
80+
cache: pnpm
81+
82+
- run: pnpm install --frozen-lockfile
83+
84+
- name: Publish codemod
85+
uses: codemod/publish-action@dd6c8dbc5ceb1a6146feba41481d88b43da50024 # v1
86+
with:
87+
path: ${{ matrix.dir }}
88+
89+
publish-manual:
90+
name: Publish codemod (manual)
91+
if: github.event_name == 'workflow_dispatch'
92+
runs-on: ubuntu-latest
93+
steps:
94+
- uses: actions/checkout@v4
95+
96+
- name: Publish codemod
97+
uses: codemod/publish-action@dd6c8dbc5ceb1a6146feba41481d88b43da50024 # v1
98+
with:
99+
path: codemods/${{ inputs.codemod_name }}

.github/workflows/release.yml

Lines changed: 5 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ on:
77
types:
88
- completed
99

10-
concurrency: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.ref }}
10+
concurrency: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}
1111

1212
permissions:
13-
id-token: write
1413
contents: write
1514
pull-requests: write
1615

@@ -22,66 +21,23 @@ jobs:
2221
github.event.workflow_run.event == 'push' &&
2322
github.event.workflow_run.head_branch == 'main'
2423
runs-on: ubuntu-latest
25-
outputs:
26-
published: ${{ steps.changesets.outputs.published }}
27-
changed_dirs: ${{ steps.tag.outputs.changed_dirs }}
2824
steps:
2925
- uses: actions/checkout@v4
3026
with:
3127
ref: ${{ github.event.workflow_run.head_sha }}
32-
fetch-depth: 0
33-
fetch-tags: true
3428

35-
- uses: pnpm/action-setup@v4
36-
with:
37-
version: 9.14.2
29+
- uses: pnpm/action-setup@f520eceda224fe1a4aed5a2a27a194379a409996 # v6
3830

3931
- uses: actions/setup-node@v4
4032
with:
41-
node-version: 20
33+
node-version-file: .nvmrc
4234
cache: pnpm
4335

4436
- run: pnpm install --frozen-lockfile
4537

46-
- name: Create Release PR or Publish
47-
id: changesets
48-
uses: changesets/action@v1
38+
- name: Create Release Pull Request
39+
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1.9.0
4940
with:
5041
version: pnpm version-packages
5142
env:
5243
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53-
54-
- name: Tag released versions
55-
if: steps.changesets.outputs.hasChangesets == 'false'
56-
id: tag
57-
run: node scripts/tag-and-publish.mjs
58-
59-
publish:
60-
name: Publish ${{ matrix.dir }}
61-
needs: release
62-
if: needs.release.result == 'success' && needs.release.outputs.changed_dirs != '[]' && needs.release.outputs.changed_dirs != ''
63-
runs-on: ubuntu-latest
64-
strategy:
65-
fail-fast: false
66-
matrix:
67-
dir: ${{ fromJson(needs.release.outputs.changed_dirs) }}
68-
steps:
69-
- uses: actions/checkout@v4
70-
with:
71-
ref: ${{ github.event.workflow_run.head_sha }}
72-
73-
- uses: pnpm/action-setup@v4
74-
with:
75-
version: 9.14.2
76-
77-
- uses: actions/setup-node@v4
78-
with:
79-
node-version: 20
80-
cache: pnpm
81-
82-
- run: pnpm install --frozen-lockfile
83-
84-
- name: Publish codemod
85-
uses: codemod/publish-action@v1
86-
with:
87-
path: ${{ matrix.dir }}

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
20

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"test": "pnpm -r --filter \"react-*\" test",
99
"check-types": "pnpm -r --filter \"react-*\" check-types",
1010
"changeset": "changeset",
11-
"version-packages": "changeset version && bash scripts/sync-codemod-versions.sh",
11+
"version-packages": "changeset version && node scripts/sync-codemod-yaml-versions.mjs",
1212
"ci": "pnpm run test && pnpm run check-types"
1313
},
1414
"keywords": [

scripts/sync-codemod-versions.sh

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env node
2+
import { readdirSync, readFileSync, writeFileSync } from 'node:fs'
3+
import { dirname, join, relative } from 'node:path'
4+
import { fileURLToPath } from 'node:url'
5+
6+
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
7+
const versionPattern = /^version:\s*(['"]?)([^'"\n]+)\1\s*$/m
8+
9+
function findCodemodYamlFiles(directory) {
10+
const paths = []
11+
12+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
13+
if (entry.name === 'node_modules') continue
14+
15+
const path = join(directory, entry.name)
16+
if (entry.isDirectory()) {
17+
paths.push(...findCodemodYamlFiles(path))
18+
} else if (entry.isFile() && entry.name === 'codemod.yaml') {
19+
paths.push(path)
20+
}
21+
}
22+
23+
return paths
24+
}
25+
26+
for (const yamlPath of findCodemodYamlFiles(join(root, 'codemods'))) {
27+
const dir = dirname(yamlPath)
28+
const { version } = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'))
29+
const content = readFileSync(yamlPath, 'utf8')
30+
const updated = content.replace(versionPattern, `version: "${version}"`)
31+
32+
if (updated !== content) {
33+
writeFileSync(yamlPath, updated)
34+
console.log(`${relative(root, yamlPath)} -> ${version}`)
35+
}
36+
}

0 commit comments

Comments
 (0)