Skip to content

Commit 79aa5fa

Browse files
committed
feat | LAY-917 Added an action to create a new tag. Added scripts for release. Added guideline for release process
1 parent 93823cc commit 79aa5fa

5 files changed

Lines changed: 374 additions & 1 deletion

File tree

.github/workflows/create-tag.yaml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# This workflow creates and pushes a release tag using the push-release-tag.sh script.
2+
# It can be triggered manually and will prompt for confirmation before creating the tag.
3+
4+
name: Create Release Tag
5+
6+
on:
7+
workflow_dispatch:
8+
inputs:
9+
dry_run:
10+
description: "Run in dry-run mode (show what would be done without actually creating/pushing the tag)"
11+
required: false
12+
type: boolean
13+
default: true
14+
confirm_release:
15+
description: "Type 'YES' to confirm you want to create and push the release tag"
16+
required: true
17+
type: string
18+
19+
jobs:
20+
check-branch:
21+
runs-on: ubuntu-latest
22+
environment: production
23+
steps:
24+
- name: Check if running on release branch
25+
run: |
26+
if [ "${{ github.ref }}" != "refs/heads/release" ]; then
27+
echo "Error: This workflow can only be run from the 'release' branch."
28+
echo "Current branch: ${{ github.ref }}"
29+
echo "Please switch to the 'release' branch and try again."
30+
exit 1
31+
fi
32+
echo "Running on release branch - proceeding with workflow."
33+
34+
create-release-tag:
35+
runs-on: ubuntu-latest
36+
needs: check-branch
37+
environment: production
38+
if: github.ref == 'refs/heads/release'
39+
40+
permissions:
41+
contents: write # Required to create and push tags
42+
43+
steps:
44+
- name: Validate confirmation
45+
if: github.event.inputs.confirm_release != 'YES' && github.event.inputs.dry_run != 'true'
46+
run: |
47+
echo "Error: You must type 'YES' in the confirm_release input to proceed with creating a release tag."
48+
echo "Received: '${{ github.event.inputs.confirm_release }}'"
49+
exit 1
50+
51+
- uses: actions/checkout@v4
52+
with:
53+
fetch-depth: 0 # Fetch all history and tags
54+
55+
- name: Make scripts executable
56+
run: |
57+
chmod +x scripts/push_release_tag.sh
58+
chmod +x scripts/get_version.sh
59+
60+
- name: Configure Git
61+
run: |
62+
git config --global user.name "github-actions[bot]"
63+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
64+
65+
- name: Run push-release-tag script (dry-run)
66+
if: github.event.inputs.dry_run == 'true'
67+
run: |
68+
echo "Running in dry-run mode..."
69+
make push-release-tag DRY_RUN=--dry-run
70+
71+
- name: Run push-release-tag script
72+
if: github.event.inputs.dry_run != 'true'
73+
env:
74+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
75+
run: |
76+
echo "Creating and pushing release tag..."
77+
# Override the interactive confirmation since we already confirmed via workflow input
78+
echo "YES" | make push-release-tag

.github/workflows/publish-to-aws.yaml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,36 @@ name: Deploy Python Package to AWS
33
on:
44
push:
55
tags:
6-
- "*"
6+
# e.g. v1.0.0, v1.0.1, v1.0.0-rc1, etc.
7+
- "v[0-9]+.[0-9]+.[0-9]+*"
78
workflow_dispatch:
89

910
env:
1011
PACKAGE_NAME: atlas
1112

1213
jobs:
14+
validate:
15+
runs-on: ubuntu-latest
16+
environment: development
17+
outputs:
18+
release_tag: ${{ steps.set_release_tag.outputs.release_tag }}
19+
steps:
20+
- uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0 # Fetch all history for checking branch
23+
- name: Set release tag
24+
id: set_release_tag
25+
# ensure the tag is valid (matches code, is on release branch, etc)
26+
run: |
27+
RELEASE_TAG=${GITHUB_REF#refs/tags/}
28+
echo "Using tag: $RELEASE_TAG"
29+
chmod +x ./scripts/validate_release_tag.sh
30+
./scripts/validate_release_tag.sh "$RELEASE_TAG"
31+
echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_ENV
32+
echo "release_tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
33+
1334
deploy:
35+
needs: validate
1436
runs-on: ubuntu-latest
1537
environment: development
1638

scripts/push_release_tag.sh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
ROOT_DIR=$(git rev-parse --show-toplevel)
5+
6+
# Parse command line arguments
7+
DRY_RUN=false
8+
9+
while [[ $# -gt 0 ]]; do
10+
case "$1" in
11+
--dry-run)
12+
DRY_RUN=true
13+
shift
14+
;;
15+
*)
16+
echo "Unknown option: $1"
17+
echo "Usage: $0 [--dry-run]"
18+
exit 1
19+
;;
20+
esac
21+
done
22+
23+
git fetch --tags --prune
24+
25+
REPO_URL="https://github.com/LayerLens/atlas-python"
26+
# e.g. v1.0.0, v1.0.1, etc.
27+
TAG_PREFIX="v"
28+
COMMIT=$(git rev-parse --short HEAD)
29+
VERSION=$(bash "$ROOT_DIR/scripts/get_version.sh")
30+
TAG="${TAG_PREFIX}${VERSION}"
31+
32+
if git rev-parse "$TAG" >/dev/null 2>&1; then
33+
echo "Error: Tag $TAG already exists"
34+
exit 1
35+
fi
36+
37+
# Find the most recent version tag
38+
LAST_RELEASE=$(git tag -l "${TAG_PREFIX}*" --sort=-v:refname | head -n 1)
39+
40+
echo "================================================"
41+
echo " Atlas Python SDK Release"
42+
echo "================================================"
43+
echo "version: ${TAG}"
44+
echo "commit: ${COMMIT}"
45+
echo "code: ${REPO_URL}/commit/${COMMIT}"
46+
echo "changeset: ${REPO_URL}/compare/${LAST_RELEASE}...${COMMIT}"
47+
48+
if [ "$DRY_RUN" = true ]; then
49+
exit 0
50+
fi
51+
52+
echo ""
53+
echo ""
54+
echo "Are you ready to release version ${VERSION}? Type 'YES' to continue:"
55+
read -r CONFIRMATION
56+
57+
if [ "$CONFIRMATION" != "YES" ]; then
58+
echo "Release cancelled."
59+
exit 1
60+
fi
61+
62+
# Create and push the tag
63+
echo ""
64+
echo "Creating and pushing tag ${TAG}"
65+
echo ""
66+
67+
git tag "$TAG" "$COMMIT"
68+
git push origin "$TAG"
69+
70+
echo ""
71+
echo "Tag ${TAG} has been created and pushed to origin."
72+
echo ""

scripts/validate_release_tag.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/bash
2+
# Validate release requirements
3+
# - Checks if the tag matches semantic versioning convention (v{major}.{minor}.{patch} with optional suffix)
4+
# - Checks if the tag matches the version in the package
5+
# - Ensures we're releasing from the release branch
6+
7+
set -e
8+
9+
# Get the tag from the first command line argument
10+
if [ $# -eq 0 ]; then
11+
echo "ERROR: Release tag argument not provided"
12+
echo "Usage: $0 <release-tag>"
13+
exit 1
14+
fi
15+
16+
ROOT_DIR=$(git rev-parse --show-toplevel)
17+
18+
# Fetch the latest tags to ensure we're up to date
19+
git fetch --tags --prune --force
20+
21+
TAG=$1
22+
23+
# Check if tag follows semantic versioning pattern (v{major}.{minor}.{patch} with optional suffix)
24+
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
25+
echo "ERROR: Tag must follow semantic versioning pattern (v{major}.{minor}.{patch} with optional suffix)"
26+
echo "Examples: v1.0.0, v2.1.3, v1.0.0-beta, v1.0.0-rc.1"
27+
exit 1
28+
fi
29+
30+
# Extract version without the 'v' prefix
31+
VERSION=${TAG#v}
32+
33+
PACKAGE_VERSION=$(bash "$ROOT_DIR/scripts/get_version.sh")
34+
35+
# Check if the tag version matches the package version
36+
if [ "$VERSION" != "$PACKAGE_VERSION" ]; then
37+
echo "ERROR: Tag version ($VERSION) does not match package version ($PACKAGE_VERSION)"
38+
exit 1
39+
fi
40+
41+
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
42+
if [ "$CURRENT_BRANCH" != "release" ]; then
43+
# If we're in detached HEAD state (which is likely in GitHub Actions with a tag),
44+
# we need to check if the tag is on the release branch
45+
if ! git rev-parse "$TAG" &>/dev/null; then
46+
echo "ERROR: Tag $TAG does not exist in the repository"
47+
exit 1
48+
fi
49+
50+
TAG_COMMIT=$(git rev-parse "$TAG")
51+
52+
# Ensure we have release branch history
53+
git fetch origin release --depth=1000
54+
55+
# Check if tag is on release branch
56+
if ! git merge-base --is-ancestor "$TAG_COMMIT" origin/release; then
57+
echo "ERROR: Tag $TAG is not on the release branch"
58+
exit 1
59+
fi
60+
fi
61+
62+
# All checks passed
63+
exit 0

src/CONTRIBUTING.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,141 @@ To format and fix all ruff issues automatically:
106106
```sh
107107
$ ./scripts/format
108108
```
109+
110+
## Release Process
111+
112+
This section outlines the complete process for releasing a new version of the Atlas Python SDK.
113+
114+
115+
### Step-by-Step Release Process
116+
117+
#### 1. Prepare the Release Branch
118+
119+
```sh
120+
# Switch to the main branch and pull latest changes
121+
$ git checkout main
122+
$ git pull origin main
123+
124+
# Create or switch to the release branch
125+
$ git checkout release
126+
$ git pull origin release
127+
128+
# rebase | cherry-pick latest changes from main into release
129+
$ git rebase main
130+
```
131+
132+
#### 2. Bump the Version
133+
134+
Update the version number in the following files:
135+
136+
- **`src/atlas/_version.py`**: Update the `__version__` string
137+
- **`pyproject.toml`**: Update the `version` field
138+
139+
**Version Format**: Use semantic versioning (MAJOR.MINOR.PATCH)
140+
- **MAJOR**: Breaking changes
141+
- **MINOR**: New features (backward compatible)
142+
- **PATCH**: Bug fixes (backward compatible)
143+
144+
**Examples**:
145+
- `1.0.2``1.0.3` (patch release for bug fixes)
146+
- `1.0.2``1.1.0` (minor release for new features)
147+
- `1.0.2``2.0.0` (major release for breaking changes)
148+
149+
```sh
150+
# Example: Update to version 1.0.3
151+
# Edit src/atlas/_version.py
152+
__version__ = "1.0.3"
153+
154+
# Edit pyproject.toml
155+
version = "1.0.3"
156+
```
157+
158+
#### 3. Test and Validate
159+
160+
```sh
161+
# Run all tests to ensure everything works
162+
$ ./scripts/test
163+
164+
# Run linting to ensure code quality
165+
$ ./scripts/lint
166+
167+
# Build the package to verify it builds correctly
168+
$ rye build
169+
```
170+
171+
#### 4. Commit and Push Changes
172+
173+
```sh
174+
# Add and commit the version bump
175+
$ git add src/atlas/_version.py pyproject.toml
176+
$ git commit -m "chore: bump version to 1.0.3"
177+
178+
# Push the release branch
179+
$ git push origin release
180+
```
181+
182+
#### 5. Create the Release Tag
183+
184+
Use the GitHub Actions workflow to create and push the release tag:
185+
186+
1. **Go to GitHub Actions**: Navigate to the "Actions" tab in the GitHub repository
187+
2. **Find "Create Release Tag"**: Look for the workflow in the left sidebar
188+
3. **Run workflow**: Click "Run workflow" with these settings:
189+
- **Use workflow from**: `release` (branch)
190+
- **Run in dry-run mode**: Check this box first to preview
191+
- **Confirm release**: Leave empty for dry-run
192+
193+
4. **Review dry-run output**: Check the workflow output to ensure everything looks correct
194+
195+
5. **Create actual release**: Run the workflow again with:
196+
- **Run in dry-run mode**: Uncheck this box
197+
- **Confirm release**: Type `YES` exactly
198+
199+
Alternatively, if any issue occurs, you can create the tag manually:
200+
201+
```sh
202+
# Create and push the tag manually (if preferred)
203+
$ git tag v1.0.3
204+
$ git push origin v1.0.3
205+
```
206+
207+
#### 6. Automatic Deployment
208+
209+
Once the tag is pushed, the "Deploy Python Package to AWS" workflow will automatically:
210+
211+
1. **Validate the release**: Run the validation script to ensure the tag follows semantic versioning
212+
2. **Run tests**: Execute the full test suite
213+
3. **Build the package**: Create distribution files
214+
4. **Deploy to AWS**: Publish the package to the configured AWS repository
215+
216+
#### 7. Verify the Release
217+
218+
1. **Check GitHub Actions**: Ensure the deployment workflow completed successfully
219+
2. **Verify package availability**: Check that the new version is available in your package repository
220+
3. **Test installation**: Try installing the new version in a clean environment
221+
222+
### Release Checklist
223+
224+
Use this checklist to ensure you we don't miss any steps:
225+
226+
- [ ] Switched to and updated the `release` branch
227+
- [ ] Merged latest changes from `main`
228+
- [ ] Updated version in `src/atlas/_version.py`
229+
- [ ] Updated version in `pyproject.toml`
230+
- [ ] Ran tests (`./scripts/test`)
231+
- [ ] Ran linting (`./scripts/lint`)
232+
- [ ] Built package successfully (`rye build`)
233+
- [ ] Committed and pushed version bump
234+
- [ ] Created release tag (via GitHub Actions or manually)
235+
- [ ] Verified deployment workflow completed successfully
236+
- [ ] Tested new version installation
237+
238+
### Troubleshooting
239+
240+
**Tag already exists**: If you need to recreate a tag, delete it first:
241+
```sh
242+
$ git tag -d v1.0.3 # Delete locally
243+
$ git push origin :v1.0.3 # Delete on remote
244+
```
245+
246+
**Rollback**: If you need to rollback a release, create a new patch version rather than trying to delete the problematic release.

0 commit comments

Comments
 (0)