1+ # LocalStack specific workflow to implement a fully-integrated continuous integration pipeline for our fork
2+ # - Rebase this fork based on the latest commit on `main` of upstream
3+ # - Build a Python source and wheel distribution of moto-ext with deterministic versioning
4+ # - Publish the distributions to PyPi
5+ # - Tag the commit in this fork with the new version
6+ # - Create a GitHub release for the new version
7+
8+ name : Sync / Release moto-ext
9+
10+ on :
11+ # TODO remove this trigger after testing
12+ push :
13+ workflow_dispatch :
14+ inputs :
15+ dry_run :
16+ description : ' Dry Run?'
17+ default : true
18+ required : true
19+ type : boolean
20+
21+ # limit concurrency to 1
22+ concurrency :
23+ group : ${{ github.workflow }}
24+
25+ permissions :
26+ contents : write
27+
28+ jobs :
29+ sync-build-release-moto-ext :
30+ runs-on : ubuntu-latest
31+ environment :
32+ name : pypi
33+ url : https://pypi.org/project/moto-ext/
34+ steps :
35+ - name : Checkout
36+ uses : actions/checkout@v4
37+ with :
38+ fetch-depth : 0
39+ ref : localstack
40+
41+ - name : Setup Python
42+ uses : actions/setup-python@v6
43+ with :
44+ python-version : ' 3.13'
45+
46+ - name : Rebase localstack branch with latest master from upstream
47+ run : |
48+ # Configure git
49+ git config --global user.name 'LocalStack Bot'
50+ git config --global user.email 'localstack-bot@users.noreply.github.com'
51+
52+ # make sure to switch to the `localstack` branch (default / main branch of this fork)
53+ git switch localstack
54+ # add moto upstream as remote
55+ git remote add upstream https://github.com/getmoto/moto.git
56+ # rebase with latest changes
57+ git pull
58+ git fetch upstream
59+ # TODO make this less dangerous:
60+ # - Use a custom merge driver which prefers everything from upstream _BUT_ the name and the URL
61+ # - Set a .gitattributes file to only use this merge driver for setup.cfg
62+ git rebase -Xtheirs upstream/master
63+
64+ - name : Determine new version
65+ run : |
66+ echo "Determining new version..."
67+ cat > setuptools.cfg << EOF
68+ [tool.setuptools_scm]
69+ local_scheme = "no-local-version"
70+ EOF
71+ python3 -m venv .venv
72+ source .venv/bin/activate
73+ python3 -m pip install setuptools_scm build
74+ NEW_VERSION=$(python3 -m setuptools_scm -c setuptools.cfg)
75+ NEW_VERSION="${NEW_VERSION//dev/post}"
76+ echo "New version is: $NEW_VERSION"
77+ echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
78+
79+ - name : Build Python distributions
80+ # FYI: Checks in this script only work because the -e flag is enabled by default in GitHub actions
81+ run : |
82+ echo "Setting new version in setup.cfg":
83+ # make sure setup.cfg is not dirty yet
84+ git diff --exit-code setup.cfg
85+ sed -i -E 's/^(version\s*=\s*)("?)[^"]+("?)/\1\2'"$NEW_VERSION"'\3/' setup.cfg
86+ # make sure setup.cfg is dirty now
87+ ! git diff --exit-code setup.cfg
88+
89+ echo "Building new version and tagging commit..."
90+ python3 -m build
91+
92+ - name : Tag successful build
93+ run : |
94+ git tag -a $NEW_VERSION -m $NEW_VERSION
95+
96+ - name : Clean up
97+ run : |
98+ git reset --hard
99+ git clean -df
100+
101+ - name : Store built distributions
102+ uses : actions/upload-artifact@v4
103+ with :
104+ name : moto-ext-dists
105+ path : dist/*.*
106+
107+ # publish the package before pushing the tag (this might fail if the version already exists on PyPI)
108+ - name : Publish package distributions to PyPI
109+ if : ${{ github.event.inputs.dry_run == false }}
110+ run : |
111+ echo "Ensure that this is really only triggered if dry run is explicitly set to false"
112+ # uses: pypa/gh-action-pypi-publish@release/v1
113+
114+ - name : Push & Create Release
115+ if : ${{ github.event.inputs.dry_run == false }}
116+ run : |
117+ echo "Ensure that this is really only triggered if dry run is explicitly set to false"
118+ # git push --force-with-lease
119+ # git push --atomic origin localstack $NEW_VERSION
120+ # gh release create $NEW_VERSION
0 commit comments