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+ version_scheme = "no-guess-dev"
71+ EOF
72+ python3 -m venv .venv
73+ source .venv/bin/activate
74+ python3 -m pip install setuptools_scm
75+ NEW_VERSION=$(python3 -m setuptools_scm -c setuptools.cfg)
76+ NEW_VERSION="${NEW_VERSION//dev/post}"
77+ echo "New version is: $NEW_VERSION"
78+ echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
79+
80+ - name : Build Python distributions
81+ # FYI: Checks in this script only work because the -e flag is enabled by default in GitHub actions
82+ run : |
83+ python3 -m pip install build
84+
85+ echo "Setting new version in setup.cfg":
86+ # make sure setup.cfg is not dirty yet
87+ git diff --exit-code setup.cfg
88+ sed -i -E 's/^(version\s*=\s*)("?)[^"]+("?)/\1\2'"$NEW_VERSION"'\3/' setup.cfg
89+ # make sure setup.cfg is dirty now
90+ ! git diff --exit-code setup.cfg
91+
92+ echo "Building new version and tagging commit..."
93+ python3 -m build
94+
95+ - name : Tag successful build
96+ run : |
97+ git tag -a $NEW_VERSION -m $NEW_VERSION
98+
99+ - name : Clean up
100+ run : |
101+ git reset --hard
102+ git clean -df
103+
104+ - name : Store built distributions
105+ uses : actions/upload-artifact@v4
106+ with :
107+ name : moto-ext-dists
108+ path : dist/*.*
109+
110+ # publish the package before pushing the tag (this might fail if the version already exists on PyPI)
111+ - name : Publish package distributions to PyPI
112+ if : ${{ github.event.inputs.dry_run == false }}
113+ run : |
114+ echo "Ensure that this is really only triggered if dry run is explicitly set to false"
115+ # uses: pypa/gh-action-pypi-publish@release/v1
116+
117+ - name : Push & Create Release
118+ if : ${{ github.event.inputs.dry_run == false }}
119+ run : |
120+ echo "Ensure that this is really only triggered if dry run is explicitly set to false"
121+ # git push --force-with-lease
122+ # git push --atomic origin localstack $NEW_VERSION
123+ # gh release create $NEW_VERSION
0 commit comments