1- name : Release
1+ name : Automatic Release Creation
22
33on :
4- schedule :
5- # Run every day at 9:00 UTC
6- - cron : ' 0 9 * * *'
7- # Allow manual trigger for testing
84 workflow_dispatch :
95
106jobs :
11- prepare :
7+ detect-last-release :
128 runs-on : ubuntu-latest
139 outputs :
14- matrix : ${{ steps.set-matrix.outputs.matrix }}
1510 last_release : ${{ steps.last-release.outputs.hash }}
1611 steps :
1712 - uses : actions/checkout@v4
1813 with :
1914 fetch-depth : 0
2015
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-
2916 - name : Get last release hash
3017 id : last-release
3118 run : |
3219 HASH=$(git rev-list --tags --max-count=1 || echo "HEAD~1")
3320 echo "hash=${HASH}" >> $GITHUB_OUTPUT
3421 echo "Using last release hash: ${HASH}"
3522
36- release :
37- needs : prepare
23+ create-tag-name :
3824 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}"
4734
35+ detect-packages :
36+ runs-on : ubuntu-latest
37+ outputs :
38+ packages : ${{ steps.find-packages.outputs.packages }}
4839 steps :
4940 - uses : actions/checkout@v4
50- with :
51- fetch-depth : 0
5241
53- - uses : astral-sh/setup-uv@v5
42+ - name : Find packages
43+ id : find-packages
44+ working-directory : src
45+ run : |
46+ # Find all package.json and pyproject.toml files
47+ PACKAGES=$(find . \( -name "package.json" -o -name "pyproject.toml" \) -exec dirname {} \; | sed 's/^\.\///' | jq -R -s -c 'split("\n")[:-1]')
48+ echo "packages=$PACKAGES" >> $GITHUB_OUTPUT
5449
55- - name : Setup Node.js
56- if : endsWith(matrix.directory, '/package.json')
57- uses : actions/setup-node@v4
50+ detect-updates :
51+ needs : [detect-packages, detect-last-release]
52+ strategy :
53+ matrix :
54+ package : ${{ fromJson(needs.detect-packages.outputs.packages) }}
55+ name : Check ${{ matrix.package }}
56+ runs-on : ubuntu-latest
57+ steps :
58+ - uses : actions/checkout@v4
5859 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
60+ fetch-depth : 0
6561
66- - name : Release package
67- id : release
68- env :
69- NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
70- UV_PUBLISH_TOKEN : ${{ secrets.PYPI_TOKEN }}
62+ - name : Check updates
63+ working-directory : src/${{ matrix.package }}
7164 run : |
72- # Create unique hash for this directory
73- dir_hash=$(echo "${{ matrix.directory }}" | sha256sum | awk '{print $1}')
74-
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
78-
79- # Run the release
80- output=$(uv run --script scripts/release.py "${{ matrix.directory }}" "${{ needs.prepare.outputs.last_release }}" 2>&1)
81- exit_code=$?
82-
83- echo "Release output (exit code: $exit_code):"
84- echo "$output"
85-
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
93-
94- if [ ! -z "$pkg_info" ]; then
95- echo "Released package: $pkg_info"
96-
97- # Create outputs directory
98- mkdir -p ./outputs
99-
100- # Save both package info and full changes
101- echo "$pkg_info" > "./outputs/${dir_hash}_info"
102- echo "dir_hash=${dir_hash}" >> $GITHUB_OUTPUT
103-
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"
65+ mkdir -p '.info/${{ matrix.package }}'
66+ if git diff --name-only ${{ needs.detect-last-release.outputs.last_release }}..HEAD -- "*.py" "*.ts" ; then
67+ echo "Changes detected in Python or TypeScript files for ${{ matrix.package }}"
68+ echo "${{ matrix.package }}" > ".info/${{ matrix.package }}/changed"
10969 fi
11070
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
71+ - name : Upload artifacts
72+ uses : actions/upload-artifact@v4
12173 with :
122- name : ${{ steps.artifact.outputs.name }}
123- path : ./outputs/ ${{ steps.release.outputs.dir_hash }}*
74+ name : release- ${{ matrix.package }}
75+ path : .info/ ${{ matrix.package }}
12476
12577 create-tag :
126- needs : [prepare, release ]
78+ needs : [detect-updates, create-tag-name ]
12779 runs-on : ubuntu-latest
12880 permissions :
12981 contents : write
@@ -132,25 +84,26 @@ jobs:
13284
13385 - uses : actions/download-artifact@v4
13486 with :
135- pattern : release-outputs-src- *
87+ pattern : release-*
13688 merge-multiple : true
13789 path : outputs
13890
139- - name : Create tag and release
91+ - name : Create release
14092 env :
14193 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
14294 run : |
14395 if [ -d outputs ]; then
96+ # Configure git
97+ git config --global user.name "GitHub Actions"
98+ git config --global user.email "actions@github.com"
99+
144100 # Collect package info
145- find outputs -name "*_info " -exec cat {} \; > packages.txt
101+ find outputs -name "changed " -exec cat {} \; > packages.txt
146102
147103 if [ -s packages.txt ]; then
148- DATE=$(date +%Y.%m.%d)
149- echo "Creating tag v${DATE}"
150-
151104 # Generate comprehensive release notes
152105 {
153- echo "# Release ${DATE }"
106+ echo "# Release ${{ needs.create-tag-name.outputs.tag_name } }"
154107 echo ""
155108 echo "## Updated Packages"
156109 while IFS= read -r line; do
@@ -159,16 +112,16 @@ jobs:
159112 } > notes.md
160113
161114 # Create and push tag
162- git tag -a "v${DATE} " -m "Release ${DATE }"
163- git push origin "v${DATE }"
115+ git tag -a "${{ needs.create-tag-name.outputs.tag_name }} " -m "Release ${{ needs.create-tag-name.outputs.tag_name } }"
116+ git push origin "${{ needs.create-tag-name.outputs.tag_name } }"
164117
165118 # Create GitHub release
166- gh release create "v${DATE }" \
167- --title "Release ${DATE }" \
119+ gh release create "${{ needs.create-tag-name.outputs.tag_name } }" \
120+ --title "Release ${{ needs.create-tag-name.outputs.tag_name } }" \
168121 --notes-file notes.md
169122 else
170123 echo "No packages need release"
171124 fi
172125 else
173126 echo "No release artifacts found"
174- fi
127+ fi
0 commit comments