Skip to content

Commit 30c03be

Browse files
committed
Add workflow for auto-versioning and publishing
1 parent d465961 commit 30c03be

8 files changed

Lines changed: 701 additions & 3 deletions

File tree

.github/workflows/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# GitHub Actions Workflows
2+
3+
## Auto Version and Publish
4+
5+
The workflow system consists of two parts:
6+
- `auto-version-and-publish.yml` - Main workflow that runs on push to main, builds packages, and triggers publishing
7+
- `version-and-publish-package.yml` - Reusable workflow that handles version bumping and npm publishing
8+
9+
### How It Works
10+
11+
1. **Change Detection**
12+
- SDK: `src/**`, `package.json`, `tsconfig.json`
13+
- CLI: `packages/cli/src/**`, `packages/cli/package.json`, `packages/cli/tsconfig.json`
14+
15+
2. **Automatic Versioning**
16+
- Beta versions: `1.0.0-beta.2``1.0.0-beta.3`
17+
- Released versions: `1.0.0``1.0.1` (patch)
18+
19+
3. **Publishing**
20+
- Only publishes packages with actual changes
21+
- Only bumps version if it already exists in registry
22+
- Creates git tags for release tracking (e.g., `sdk-v1.2.3`, `cli-v1.2.3`)
23+
24+
### Manual Trigger
25+
26+
Trigger from GitHub Actions tab:
27+
- **version_type**: `patch`, `minor`, `major`, `prerelease`
28+
- **prerelease_tag**: `beta`, `rc` (default: `beta`)
29+
- **force_cli_publish**: Force CLI publish without changes
30+
31+
### Transitioning from Beta
32+
33+
To release from beta (e.g., `1.0.0-beta.5``1.0.0`):
34+
1. Manually trigger workflow
35+
2. Select `major`, `minor`, or `patch`
36+
37+
38+
## Local Development
39+
40+
### Version Management
41+
42+
```bash
43+
# Bump both packages simultaneously
44+
npm run version:patch # 1.0.0 → 1.0.1 for both SDK and CLI
45+
npm run version:minor # 1.0.0 → 1.1.0 for both packages
46+
npm run version:major # 1.0.0 → 2.0.0 for both packages
47+
npm run version:prerelease # 1.0.0 → 1.0.0-beta.0 for both
48+
49+
# Bump individual packages only
50+
npm run version:sdk patch # Updates SDK version only
51+
npm run version:cli minor # Updates CLI version only
52+
```
53+
54+
### Pre-release Checks
55+
56+
```bash
57+
npm run pre-release # Runs linting, tests, and build to ensure release readiness
58+
npm run verify # Verifies package.json configs and dependencies
59+
npm pack --dry-run # Shows what files will be included in published package
60+
```
61+
62+
## Troubleshooting
63+
64+
- **Build failures**: Check TypeScript compilation and dependencies
65+
- **Publish failures**: Verify npm authentication and package.json
66+
- **Version not bumping**: Only bumps if version exists in registry
67+
- **Missing dist**: Check build logs for errors
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
name: Auto Version and Publish
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
inputs:
9+
version_type:
10+
description: 'Version bump type'
11+
required: true
12+
default: 'patch'
13+
type: choice
14+
options:
15+
- patch
16+
- minor
17+
- major
18+
- prerelease
19+
prerelease_tag:
20+
description: 'Prerelease tag (beta, rc)'
21+
required: false
22+
default: 'beta'
23+
force_cli_publish:
24+
description: 'Force publish CLI even without changes'
25+
required: false
26+
default: false
27+
type: boolean
28+
29+
jobs:
30+
# Detect changes
31+
changes:
32+
runs-on: ubuntu-latest
33+
outputs:
34+
cli: ${{ steps.filter.outputs.cli }}
35+
sdk: ${{ steps.filter.outputs.sdk }}
36+
steps:
37+
- uses: actions/checkout@v4
38+
with:
39+
fetch-depth: 0
40+
41+
- uses: dorny/paths-filter@v3
42+
id: filter
43+
with:
44+
filters: |
45+
cli:
46+
- 'packages/cli/src/**'
47+
- 'packages/cli/package.json'
48+
- 'packages/cli/tsconfig.json'
49+
sdk:
50+
- 'src/**'
51+
- 'package.json'
52+
- 'tsconfig.json'
53+
54+
# Build all packages
55+
build:
56+
runs-on: ubuntu-latest
57+
needs: changes
58+
steps:
59+
- uses: actions/checkout@v4
60+
61+
- name: Setup Node.js
62+
uses: actions/setup-node@v4
63+
with:
64+
node-version: '20'
65+
cache: 'npm'
66+
67+
- name: Install dependencies
68+
run: npm ci
69+
70+
- name: Run linting
71+
run: npm run lint
72+
73+
- name: Build packages
74+
run: |
75+
npm run clean
76+
npm run build
77+
78+
# TODO: Add tests
79+
# - name: Run tests
80+
# run: npm test
81+
82+
- name: Upload SDK artifacts
83+
uses: actions/upload-artifact@v4
84+
with:
85+
name: sdk-dist
86+
path: dist/
87+
88+
- name: Upload CLI artifacts
89+
uses: actions/upload-artifact@v4
90+
with:
91+
name: cli-dist
92+
path: packages/cli/dist/
93+
94+
# Version and publish SDK
95+
publish-sdk:
96+
needs: [changes, build]
97+
if: needs.changes.outputs.sdk == 'true'
98+
uses: ./.github/workflows/version-and-publish-package.yml
99+
with:
100+
package_name: sdk
101+
package_path: .
102+
artifact_name: sdk-dist
103+
npm_package_name: '@uipath/uipath-typescript'
104+
version_type: ${{ github.event_name == 'workflow_dispatch' && inputs.version_type || 'auto' }}
105+
prerelease_tag: ${{ inputs.prerelease_tag || 'beta' }}
106+
permissions:
107+
contents: write
108+
packages: write
109+
110+
# Version and publish CLI
111+
publish-cli:
112+
needs: [changes, build]
113+
if: needs.changes.outputs.cli == 'true' || inputs.force_cli_publish
114+
uses: ./.github/workflows/version-and-publish-package.yml
115+
with:
116+
package_name: cli
117+
package_path: packages/cli
118+
artifact_name: cli-dist
119+
npm_package_name: '@uipath/cli'
120+
version_type: ${{ github.event_name == 'workflow_dispatch' && inputs.version_type || 'auto' }}
121+
prerelease_tag: ${{ inputs.prerelease_tag || 'beta' }}
122+
permissions:
123+
contents: write
124+
packages: write
125+
126+
# Push all changes
127+
push-changes:
128+
runs-on: ubuntu-latest
129+
needs: [publish-sdk, publish-cli]
130+
if: always() && (needs.publish-sdk.outputs.published == 'true' || needs.publish-cli.outputs.published == 'true')
131+
permissions:
132+
contents: write
133+
steps:
134+
- uses: actions/checkout@v4
135+
with:
136+
token: ${{ secrets.GITHUB_TOKEN }}
137+
fetch-depth: 0
138+
ref: main
139+
140+
- name: Configure Git
141+
run: |
142+
git config --global user.name "github-actions[bot]"
143+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
144+
145+
- name: Pull and push changes
146+
run: |
147+
git pull origin main --rebase
148+
git push origin main --follow-tags
149+
150+
# Summary
151+
summary:
152+
runs-on: ubuntu-latest
153+
needs: [changes, build, publish-sdk, publish-cli]
154+
if: always()
155+
steps:
156+
- name: Generate Summary
157+
run: |
158+
echo "## Build and Publish Summary" >> $GITHUB_STEP_SUMMARY
159+
echo "" >> $GITHUB_STEP_SUMMARY
160+
161+
echo "### Changes Detected" >> $GITHUB_STEP_SUMMARY
162+
echo "- SDK: ${{ needs.changes.outputs.sdk == 'true' && '✅' || '❌' }}" >> $GITHUB_STEP_SUMMARY
163+
echo "- CLI: ${{ needs.changes.outputs.cli == 'true' && '✅' || '❌' }}" >> $GITHUB_STEP_SUMMARY
164+
echo "" >> $GITHUB_STEP_SUMMARY
165+
166+
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
167+
echo "- Build: ${{ needs.build.result == 'success' && '✅' || '❌' }}" >> $GITHUB_STEP_SUMMARY
168+
echo "" >> $GITHUB_STEP_SUMMARY
169+
170+
echo "### Publishing" >> $GITHUB_STEP_SUMMARY
171+
if [ "${{ needs.publish-sdk.outputs.published }}" == "true" ]; then
172+
echo "- SDK: ✅ Published ${{ needs.publish-sdk.outputs.version }}" >> $GITHUB_STEP_SUMMARY
173+
elif [ "${{ needs.changes.outputs.sdk }}" == "true" ]; then
174+
echo "- SDK: ❌ Failed to publish" >> $GITHUB_STEP_SUMMARY
175+
else
176+
echo "- SDK: ⏭️ No changes" >> $GITHUB_STEP_SUMMARY
177+
fi
178+
179+
if [ "${{ needs.publish-cli.outputs.published }}" == "true" ]; then
180+
echo "- CLI: ✅ Published ${{ needs.publish-cli.outputs.version }}" >> $GITHUB_STEP_SUMMARY
181+
elif [ "${{ needs.changes.outputs.cli }}" == "true" ] || [ "${{ inputs.force_cli_publish }}" == "true" ]; then
182+
echo "- CLI: ❌ Failed to publish" >> $GITHUB_STEP_SUMMARY
183+
else
184+
echo "- CLI: ⏭️ No changes" >> $GITHUB_STEP_SUMMARY
185+
fi
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
name: Version and Publish Package
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
package_name:
7+
required: true
8+
type: string
9+
description: 'Package name (sdk or cli)'
10+
package_path:
11+
required: false
12+
type: string
13+
default: '.'
14+
description: 'Path to package directory'
15+
artifact_name:
16+
required: true
17+
type: string
18+
description: 'Name of the build artifact to download'
19+
npm_package_name:
20+
required: true
21+
type: string
22+
description: 'NPM package name (e.g., @uipath/uipath-typescript)'
23+
version_type:
24+
required: false
25+
type: string
26+
default: 'auto'
27+
description: 'Version type: auto, patch, minor, major, prerelease'
28+
prerelease_tag:
29+
required: false
30+
type: string
31+
default: 'beta'
32+
description: 'Prerelease tag'
33+
outputs:
34+
published:
35+
description: 'Whether the package was published'
36+
value: ${{ jobs.publish.outputs.published }}
37+
version:
38+
description: 'The published version'
39+
value: ${{ jobs.publish.outputs.version }}
40+
41+
jobs:
42+
publish:
43+
runs-on: ubuntu-latest
44+
outputs:
45+
published: ${{ steps.publish.outputs.published }}
46+
version: ${{ steps.get_version.outputs.version }}
47+
steps:
48+
- uses: actions/checkout@v4
49+
with:
50+
token: ${{ secrets.GITHUB_TOKEN }}
51+
fetch-depth: 0
52+
53+
- name: Setup Node.js
54+
uses: actions/setup-node@v4
55+
with:
56+
node-version: '20'
57+
registry-url: 'https://npm.pkg.github.com'
58+
59+
- name: Install dependencies
60+
run: npm ci
61+
62+
- name: Download artifacts
63+
uses: actions/download-artifact@v4
64+
with:
65+
name: ${{ inputs.artifact_name }}
66+
path: ${{ inputs.package_path }}/dist/
67+
68+
- name: Determine version type
69+
id: version_type
70+
working-directory: ${{ inputs.package_path }}
71+
run: |
72+
if [ "${{ inputs.version_type }}" != "auto" ]; then
73+
echo "type=${{ inputs.version_type }}" >> $GITHUB_OUTPUT
74+
else
75+
# Auto-detect based on current version
76+
CURRENT_VERSION=$(node -p "require('./package.json').version")
77+
if echo "$CURRENT_VERSION" | grep -q "beta"; then
78+
echo "type=prerelease" >> $GITHUB_OUTPUT
79+
else
80+
echo "type=patch" >> $GITHUB_OUTPUT
81+
fi
82+
fi
83+
84+
- name: Check if version exists
85+
id: check_version
86+
working-directory: ${{ inputs.package_path }}
87+
run: |
88+
CURRENT_VERSION=$(node -p "require('./package.json').version")
89+
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
90+
91+
if npm view ${{ inputs.npm_package_name }}@$CURRENT_VERSION version 2>/dev/null; then
92+
echo "needs_bump=true" >> $GITHUB_OUTPUT
93+
else
94+
echo "needs_bump=false" >> $GITHUB_OUTPUT
95+
fi
96+
env:
97+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
98+
99+
- name: Bump version if needed
100+
id: bump_version
101+
if: steps.check_version.outputs.needs_bump == 'true'
102+
working-directory: ${{ inputs.package_path }}
103+
run: |
104+
VERSION_TYPE="${{ steps.version_type.outputs.type }}"
105+
106+
if [ "$VERSION_TYPE" == "prerelease" ]; then
107+
NEW_VERSION=$(npm version prerelease --preid=${{ inputs.prerelease_tag }} --no-git-tag-version)
108+
else
109+
NEW_VERSION=$(npm version $VERSION_TYPE --no-git-tag-version)
110+
fi
111+
112+
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
113+
echo "bumped=true" >> $GITHUB_OUTPUT
114+
115+
- name: Get final version
116+
id: get_version
117+
working-directory: ${{ inputs.package_path }}
118+
run: |
119+
VERSION=$(node -p "require('./package.json').version")
120+
echo "version=v$VERSION" >> $GITHUB_OUTPUT
121+
122+
- name: Publish package
123+
id: publish
124+
working-directory: ${{ inputs.package_path }}
125+
run: |
126+
npm publish
127+
echo "published=true" >> $GITHUB_OUTPUT
128+
env:
129+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
130+
131+
- name: Commit version changes
132+
if: steps.bump_version.outputs.bumped == 'true'
133+
run: |
134+
git config --global user.name "github-actions[bot]"
135+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
136+
git add ${{ inputs.package_path }}/package.json
137+
git commit -m "chore(${{ inputs.package_name }}): bump version to ${{ steps.get_version.outputs.version }}"
138+
139+
- name: Create release tag
140+
run: |
141+
git tag -a "${{ inputs.package_name }}-${{ steps.get_version.outputs.version }}" \
142+
-m "${{ inputs.package_name }} Release ${{ steps.get_version.outputs.version }}"

0 commit comments

Comments
 (0)