1
- name : Release
1
+ name : Automatic Release Creation
2
2
3
3
on :
4
- schedule :
5
- # Run every day at 9:00 UTC
6
- - cron : ' 0 9 * * *'
7
- # Allow manual trigger for testing
8
4
workflow_dispatch :
9
5
10
6
jobs :
11
- prepare :
7
+ detect-last-release :
12
8
runs-on : ubuntu-latest
13
9
outputs :
14
- matrix : ${{ steps.set-matrix.outputs.matrix }}
15
10
last_release : ${{ steps.last-release.outputs.hash }}
16
11
steps :
17
12
- uses : actions/checkout@v4
18
13
with :
19
14
fetch-depth : 0
20
15
21
- - name : Find package directories
22
- id : set-matrix
23
- run : |
24
- # Find all package.json and pyproject.toml files, excluding root
25
- DIRS=$(git ls-tree -r HEAD --name-only | grep -E "package.json|pyproject.toml" | xargs dirname | grep -v "^.$" | jq -R -s -c 'split("\n")[:-1]')
26
- echo "matrix=${DIRS}" >> $GITHUB_OUTPUT
27
- echo "Found directories: ${DIRS}"
28
-
29
16
- name : Get last release hash
30
17
id : last-release
31
18
run : |
32
19
HASH=$(git rev-list --tags --max-count=1 || echo "HEAD~1")
33
20
echo "hash=${HASH}" >> $GITHUB_OUTPUT
34
21
echo "Using last release hash: ${HASH}"
35
22
36
- release :
37
- needs : prepare
23
+ create-tag-name :
38
24
runs-on : ubuntu-latest
39
- environment : release
40
- strategy :
41
- matrix :
42
- directory : ${{ fromJson(needs.prepare.outputs.matrix) }}
43
- fail-fast : false
44
- permissions :
45
- contents : write
46
- packages : write
25
+ outputs :
26
+ tag_name : ${{ steps.last-release.outputs.tag}}
27
+ steps :
28
+ - name : Get last release hash
29
+ id : last-release
30
+ run : |
31
+ DATE=$(date +%Y.%m.%d)
32
+ echo "tag=v${DATE}" >> $GITHUB_OUTPUT
33
+ echo "Using tag: v${DATE}"
47
34
35
+ detect-packages :
36
+ needs : [detect-last-release]
37
+ runs-on : ubuntu-latest
38
+ outputs :
39
+ packages : ${{ steps.find-packages.outputs.packages }}
48
40
steps :
49
41
- uses : actions/checkout@v4
50
42
with :
51
43
fetch-depth : 0
52
44
53
- - uses : astral-sh/setup-uv@v5
54
-
55
- - name : Setup Node.js
56
- if : endsWith(matrix.directory, '/package.json')
57
- uses : actions/setup-node@v4
58
- with :
59
- node-version : ' 18'
60
- registry-url : ' https://registry.npmjs.org'
61
-
62
- - name : Setup Python
63
- if : endsWith(matrix.directory, '/pyproject.toml')
64
- run : uv python install
45
+ - name : Install uv
46
+ uses : astral-sh/setup-uv@v5
65
47
66
- - name : Release package
67
- id : release
68
- env :
69
- NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
70
- UV_PUBLISH_TOKEN : ${{ secrets.PYPI_TOKEN }}
48
+ - name : Find packages
49
+ id : find-packages
50
+ working-directory : src
71
51
run : |
72
- # Create unique hash for this directory
73
- dir_hash=$(echo "${{ matrix.directory }}" | sha256sum | awk '{print $1}')
52
+ cat << 'EOF' > find_packages.py
53
+ import json
54
+ import os
55
+ import subprocess
56
+ from itertools import chain
57
+ from pathlib import Path
74
58
75
- # Run git diff first to show changes
76
- echo "Changes since last release:"
77
- git diff --name-only "${{ needs.prepare.outputs.last_release }}" -- "${{ matrix.directory }}" || true
59
+ packages = []
78
60
79
- # Run the release
80
- output=$(uv run --script scripts/release.py "${{ matrix.directory }}" "${{ needs.prepare.outputs.last_release }}" 2>&1)
81
- exit_code=$?
61
+ print("Starting package detection...")
62
+ print(f"Using LAST_RELEASE: {os.environ['LAST_RELEASE']}")
82
63
83
- echo "Release output (exit code: $exit_code):"
84
- echo "$output"
64
+ # Find all directories containing package.json or pyproject.toml
65
+ paths = chain(Path('.').glob('*/package.json'), Path('.').glob('*/pyproject.toml'))
66
+ for path in paths:
67
+ print(f"\nChecking path: {path}")
68
+ # Check for changes in .py or .ts files
69
+ # Run git diff from the specific directory
70
+ cmd = ['git', 'diff', '--name-only', f'{os.environ["LAST_RELEASE"]}..HEAD', '--', '.']
71
+ result = subprocess.run(cmd, capture_output=True, text=True, cwd=path.parent)
85
72
86
- # Extract package info if successful
87
- if [ $exit_code -eq 0 ]; then
88
- pkg_info=$(echo "$output" | grep -o -E "[a-zA-Z0-9\-]+@[0-9]+\.[0-9]+\.[0-9]+" || true)
89
- else
90
- echo "Release failed"
91
- exit 1
92
- fi
73
+ # Check if any .py or .ts files were changed
74
+ changed_files = result.stdout.strip().split('\n')
75
+ print(f"Changed files found: {changed_files}")
93
76
94
- if [ ! -z "$pkg_info" ]; then
95
- echo "Released package: $pkg_info"
77
+ has_changes = any(f.endswith(('.py', '.ts')) for f in changed_files if f)
78
+ if has_changes:
79
+ print(f"Adding package: {path.parent}")
80
+ packages.append(str(path.parent))
96
81
97
- # Create outputs directory
98
- mkdir -p ./outputs
82
+ print(f"\nFinal packages list: {packages}")
99
83
100
- # Save both package info and full changes
101
- echo "$pkg_info" > "./outputs/${dir_hash}_info"
102
- echo "dir_hash=${dir_hash}" >> $GITHUB_OUTPUT
84
+ # Write output
85
+ with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
86
+ f.write(f"packages={json.dumps(packages)}\n")
87
+ EOF
103
88
104
- # Log what we're saving
105
- echo "Saved package info to ./outputs/${dir_hash}_info:"
106
- cat "./outputs/${dir_hash}_info"
107
- else
108
- echo "No release needed for this package"
109
- fi
110
-
111
- - name : Set artifact name
112
- if : steps.release.outputs.dir_hash
113
- id : artifact
114
- run : |
115
- # Replace forward slashes with dashes
116
- SAFE_DIR=$(echo "${{ matrix.directory }}" | tr '/' '-')
117
- echo "name=release-outputs-${SAFE_DIR}" >> $GITHUB_OUTPUT
118
-
119
- - uses : actions/upload-artifact@v4
120
- if : steps.release.outputs.dir_hash
121
- with :
122
- name : ${{ steps.artifact.outputs.name }}
123
- path : ./outputs/${{ steps.release.outputs.dir_hash }}*
89
+ LAST_RELEASE=${{ needs.detect-last-release.outputs.last_release }} uv run --script --python 3.12 find_packages.py
124
90
125
91
create-tag :
126
- needs : [prepare, release ]
92
+ needs : [detect-packages, create-tag-name ]
127
93
runs-on : ubuntu-latest
128
94
permissions :
129
95
contents : write
130
96
steps :
131
97
- uses : actions/checkout@v4
132
98
133
- - uses : actions/download-artifact@v4
134
- with :
135
- pattern : release-outputs-src-*
136
- merge-multiple : true
137
- path : outputs
138
-
139
- - name : Create tag and release
99
+ - name : Create release
140
100
env :
141
101
GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
142
102
run : |
143
- if [ -d outputs ]; then
144
- # Collect package info
145
- find outputs -name "*_info" -exec cat {} \; > packages.txt
146
-
147
- if [ -s packages.txt ]; then
148
- DATE=$(date +%Y.%m.%d)
149
- echo "Creating tag v${DATE}"
150
-
151
- # Generate comprehensive release notes
152
- {
153
- echo "# Release ${DATE}"
154
- echo ""
155
- echo "## Updated Packages"
156
- while IFS= read -r line; do
157
- echo "- $line"
158
- done < packages.txt
159
- } > notes.md
160
-
161
- # Create and push tag
162
- git tag -a "v${DATE}" -m "Release ${DATE}"
163
- git push origin "v${DATE}"
164
-
165
- # Create GitHub release
166
- gh release create "v${DATE}" \
167
- --title "Release ${DATE}" \
168
- --notes-file notes.md
169
- else
170
- echo "No packages need release"
171
- fi
103
+ # Configure git
104
+ git config --global user.name "GitHub Actions"
105
+ git config --global user.email "[email protected] "
106
+
107
+ # Get packages array
108
+ PACKAGES='${{ needs.detect-packages.outputs.packages }}'
109
+
110
+ if [ "$(echo "$PACKAGES" | jq 'length')" -gt 0 ]; then
111
+ # Generate comprehensive release notes
112
+ {
113
+ echo "# Release ${{ needs.create-tag-name.outputs.tag_name }}"
114
+ echo ""
115
+ echo "## Updated Packages"
116
+ echo "$PACKAGES" | jq -r '.[]' | while read -r package; do
117
+ echo "- $package"
118
+ done
119
+ } > notes.md
120
+
121
+ # Create and push tag
122
+ git tag -a "${{ needs.create-tag-name.outputs.tag_name }}" -m "Release ${{ needs.create-tag-name.outputs.tag_name }}"
123
+ git push origin "${{ needs.create-tag-name.outputs.tag_name }}"
124
+
125
+ # Create GitHub release
126
+ gh release create "${{ needs.create-tag-name.outputs.tag_name }}" \
127
+ --title "Release ${{ needs.create-tag-name.outputs.tag_name }}" \
128
+ --notes-file notes.md
172
129
else
173
- echo "No release artifacts found "
174
- fi
130
+ echo "No packages need release "
131
+ fi
0 commit comments