Skip to content

Commit 0c71721

Browse files
authored
ci: refactor release scripts/docs, add release workflow (#1642)
1 parent 3131e97 commit 0c71721

File tree

16 files changed

+1366
-1111
lines changed

16 files changed

+1366
-1111
lines changed

.github/workflows/release.yml

Lines changed: 391 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,391 @@
1+
name: FloPy release
2+
on:
3+
push:
4+
branches:
5+
- master
6+
- v*
7+
release:
8+
types:
9+
- published
10+
jobs:
11+
prep:
12+
name: Prepare release
13+
runs-on: ubuntu-latest
14+
if: ${{ github.event_name == 'push' && github.ref_name != 'master' }}
15+
permissions:
16+
contents: write
17+
defaults:
18+
run:
19+
shell: bash
20+
steps:
21+
22+
- name: Checkout release branch
23+
uses: actions/checkout@v3
24+
with:
25+
fetch-depth: 0
26+
27+
- name: Setup Python
28+
uses: actions/setup-python@v4
29+
with:
30+
python-version: 3.7
31+
cache: 'pip'
32+
cache-dependency-path: setup.cfg
33+
34+
- name: Install Python dependencies
35+
run: |
36+
pip install --upgrade pip
37+
pip install build twine
38+
pip install .
39+
pip install ".[lint, test, optional]"
40+
41+
- name: Install MODFLOW
42+
run: |
43+
mkdir -p ~/.local/bin
44+
get-modflow ~/.local/bin
45+
env:
46+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47+
48+
- name: Update FloPy version
49+
id: version
50+
run: |
51+
# extract version from branch name
52+
ref="${{ github.ref_name }}"
53+
ver="${ref#"v"}"
54+
55+
# update version files
56+
if [[ "$ver" == *"rc"* ]]; then
57+
python scripts/update_version.py -v "${ref%"rc"}"
58+
else
59+
python scripts/update_version.py -v "$ver" --approve
60+
fi
61+
62+
# show version and set output
63+
python -c "import flopy; print(f'FloPy version: {flopy.__version__}')"
64+
echo "version=${ver#"v"}" >> $GITHUB_OUTPUT
65+
66+
- name: Update FloPy plugins
67+
run: python -c 'import flopy; flopy.mf6.utils.generate_classes(branch="master", backup=False)'
68+
69+
- name: Lint Python files
70+
run: python scripts/pull_request_prepare.py
71+
72+
- name: Run tests
73+
working-directory: autotest
74+
run: pytest -v -m="not example and not regression" -n=auto --durations=0 --keep-failed=.failed
75+
env:
76+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77+
78+
- name: Upload failed test outputs
79+
uses: actions/upload-artifact@v2
80+
if: failure()
81+
with:
82+
name: failed-${{ matrix.os }}-${{ matrix.python-version }}
83+
path: |
84+
./autotest/.failed/**
85+
86+
- name: Run notebooks
87+
working-directory: scripts
88+
run: python run_notebooks.py
89+
90+
- name: Generate changelog
91+
id: cliff
92+
uses: orhun/git-cliff-action@v1
93+
with:
94+
config: cliff.toml
95+
args: --verbose --unreleased --tag ${{ steps.version.outputs.version }}
96+
env:
97+
OUTPUT: CHANGELOG.md
98+
99+
- name: Update changelog
100+
run: |
101+
# move changelog
102+
sudo cp ${{ steps.cliff.outputs.changelog }} CHANGELOG.md
103+
104+
# show changelog
105+
cat CHANGELOG.md
106+
107+
# substitute full group names
108+
sed -i 's/#### Ci/#### Continuous integration/' CHANGELOG.md
109+
sed -i 's/#### Feat/#### New features/' CHANGELOG.md
110+
sed -i 's/#### Fix/#### Bug fixes/' CHANGELOG.md
111+
sed -i 's/#### Refactor/#### Refactoring/' CHANGELOG.md
112+
sed -i 's/#### Test/#### Testing/' CHANGELOG.md
113+
114+
# prepend changelog to docs/version_changes.md
115+
cat CHANGELOG.md | cat - docs/version_changes.md | tee docs/version_changes.md
116+
117+
- name: Upload changelog
118+
uses: actions/upload-artifact@v3
119+
with:
120+
name: changelog
121+
path: CHANGELOG.md
122+
123+
- name: Push release branch
124+
run: |
125+
git config core.sharedRepository true
126+
git config user.name "github-actions[bot]"
127+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
128+
git add -A
129+
git commit -m "ci(release): set version to ${{ steps.version.outputs.version }}, update plugins from DFN files, update changelog"
130+
git push origin "${{ github.ref_name }}"
131+
132+
pr:
133+
name: Draft release PR
134+
needs: prep
135+
if: ${{ github.event_name == 'push' && !(contains(github.ref_name, 'rc')) }}
136+
runs-on: ubuntu-22.04
137+
permissions:
138+
contents: write
139+
pull-requests: write
140+
defaults:
141+
run:
142+
shell: bash -l {0}
143+
steps:
144+
145+
- name: Checkout release branch
146+
uses: actions/checkout@v3
147+
with:
148+
ref: ${{ github.ref_name }}
149+
150+
- name: Draft pull request
151+
env:
152+
GITHUB_TOKEN: ${{ github.token }}
153+
run: |
154+
ref="${{ github.ref_name }}"
155+
ver="${ref#"v"}"
156+
title="Release $ver"
157+
body='
158+
# FloPy '$ver'
159+
160+
The release can be approved by merging this pull request into `master`. This will trigger a final job to publish the release to PyPI.
161+
'
162+
gh pr create -B "master" -H "$ref" --title "$title" --draft --body "$body"
163+
164+
release:
165+
name: Draft release
166+
# runs only when changes are merged to master
167+
if: ${{ github.event_name == 'push' && github.ref_name == 'master' }}
168+
runs-on: ubuntu-latest
169+
permissions:
170+
contents: write
171+
pull-requests: write
172+
steps:
173+
174+
- name: Checkout master branch
175+
uses: actions/checkout@v3
176+
with:
177+
ref: master
178+
179+
# actions/download-artifact won't look at previous workflow runs but we need to in order to get changelog
180+
- name: Download artifacts
181+
uses: dawidd6/action-download-artifact@v2
182+
183+
- name: Draft release
184+
env:
185+
GITHUB_TOKEN: ${{ github.token }}
186+
run: |
187+
version=$(cat version.txt)
188+
title="FloPy $version"
189+
notes=$(cat changelog/CHANGELOG.md)
190+
gh release create "$version" \
191+
--target master \
192+
--title "$title" \
193+
--notes "$notes" \
194+
--draft \
195+
--latest
196+
197+
publish:
198+
name: Publish package
199+
# runs only after release is published (manually promoted from draft)
200+
if: ${{ github.event_name == 'release' }}
201+
runs-on: ubuntu-22.04
202+
permissions:
203+
contents: write
204+
pull-requests: write
205+
steps:
206+
207+
- name: Checkout master branch
208+
uses: actions/checkout@v3
209+
with:
210+
ref: master
211+
212+
- name: Setup Python
213+
uses: actions/setup-python@v4
214+
with:
215+
python-version: 3.7
216+
cache: 'pip'
217+
cache-dependency-path: setup.cfg
218+
219+
- name: Install Python dependencies
220+
run: |
221+
pip install --upgrade pip
222+
pip install build twine
223+
pip install .
224+
pip install ".[lint, test, optional]"
225+
226+
- name: Build package
227+
run: python -m build
228+
229+
- name: Check package
230+
run: twine check --strict dist/*
231+
232+
- name: Upload package
233+
uses: actions/upload-artifact@v3
234+
with:
235+
name: dist
236+
path: dist
237+
238+
- name: Publish to PyPI
239+
env:
240+
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
241+
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
242+
run: python -m twine upload dist/*
243+
244+
# TODO: only need if regro-cf-autotick-bot doesn't autodetect release and open PR on conda-forge/flopy-feedstock
245+
246+
# - name: Setup Micromamba
247+
# uses: mamba-org/provision-with-micromamba@main
248+
# with:
249+
# environment-file: flopy/etc/environment.yml
250+
# cache-downloads: true
251+
# cache-env: true
252+
253+
# - name: Install dependencies
254+
# run: |
255+
# conda install -c conda-forge conda-smithy
256+
# pip install --upgrade pip
257+
# pip install build twine
258+
259+
# - name: Download release assets
260+
# uses: robinraju/[email protected]
261+
# with:
262+
# latest: true
263+
# tarBall: true
264+
# zipBall: false
265+
266+
# - name: Calculate checksum
267+
# id: checksum
268+
# run: |
269+
# sha256=$(openssl sha256 "Source code (tar.gz).tar.gz")
270+
# echo "SHA256: $sha256"
271+
# echo "sha256=$sha256" >> $GITHUB_OUTPUT
272+
273+
# - name: Checkout feedstock
274+
# uses: actions/checkout@v3
275+
# with:
276+
# repository: w-bonelli/flopy-feedstock
277+
# path: flopy-feedstock
278+
# ref: master
279+
280+
# - name: Get version
281+
# working-directory: flopy
282+
# id: version
283+
# run: |
284+
# version=$(python scripts/update_version.py --get)
285+
# echo "version: $version"
286+
# echo "version=$version" >> $GITHUB_OUTPUT
287+
288+
# - name: Update feedstock
289+
# working-directory: flopy-feedstock
290+
# run: |
291+
# git remote add upstream https://github.com/conda-forge/flopy-feedstock.git
292+
# git fetch upstream
293+
# git checkout master
294+
# git reset --hard upstream/master
295+
# # git push origin master --force
296+
# git switch -c "v${{ steps.version.outputs.version }}-update-conda"
297+
298+
# - name: Rerender feedstock
299+
# working-directory: flopy-feedstock
300+
# run: |
301+
# conda smithy rerender
302+
303+
# - name: Update feedstock recipe
304+
# working-directory: flopy-feedstock
305+
# run: |
306+
# sed -i '1s/.*/{% set version = "'${{ steps.version.outputs.version }}'" %}/' recipe/meta.yaml
307+
# sed -i 's/sha256:.*/sha256: ${{ steps.checksum.outputs.sha256 }}/g' recipe/meta.yaml
308+
# git add recipe/meta.yaml
309+
# git commit -m "ci(release): update recipe"
310+
# # git push -u origin "v${{ steps.version.outputs.version }}-update-conda"
311+
312+
# - name: Draft feedstock PR
313+
# working-directory: flopy-feedstock
314+
# env:
315+
# GITHUB_TOKEN: ${{ github.token }}
316+
# run: |
317+
# body='
318+
# # FloPy '$ver' release
319+
#
320+
# This release can be approved by merging this pull request into `master`. This will trigger a final job to publish the release to PyPI and open a PR to update the [Conda feedstock](https://github.com/jdhughes-usgs/flopy-feedstock).
321+
# '
322+
# gh pr create -B "master" -H "$ref" --title "Release version $ver" --draft --latest --body "$body"
323+
324+
reset:
325+
name: Draft reset PR
326+
if: ${{ github.event_name == 'release' }}
327+
runs-on: ubuntu-22.04
328+
permissions:
329+
contents: write
330+
pull-requests: write
331+
defaults:
332+
run:
333+
shell: bash -l {0}
334+
steps:
335+
336+
- name: Checkout master branch
337+
uses: actions/checkout@v3
338+
with:
339+
ref: master
340+
341+
- name: Setup Python
342+
uses: actions/setup-python@v4
343+
with:
344+
python-version: 3.7
345+
cache: 'pip'
346+
cache-dependency-path: setup.cfg
347+
348+
- name: Install Python dependencies
349+
run: |
350+
pip install --upgrade pip
351+
pip install build twine
352+
pip install .
353+
pip install ".[lint, test, optional]"
354+
355+
- name: Get release tag
356+
uses: oprypin/find-latest-tag@v1
357+
id: latest_tag
358+
with:
359+
repository: ${{ github.repository }}
360+
releases-only: true
361+
362+
- name: Draft pull request
363+
env:
364+
GITHUB_TOKEN: ${{ github.token }}
365+
run: |
366+
# create reset branch from master
367+
reset_branch="post-release-${{ steps.latest_tag.outputs.tag }}-reset"
368+
git switch -c $reset_branch
369+
370+
# increment patch version
371+
major_version=$(echo "${{ steps.latest_tag.outputs.tag }}" | cut -d. -f1)
372+
minor_version=$(echo "${{ steps.latest_tag.outputs.tag }}" | cut -d. -f2)
373+
patch_version=$(echo "${{ steps.latest_tag.outputs.tag }}" | cut -d. -f3)
374+
version="$major_version.$minor_version.$((patch_version + 1))"
375+
python scripts/update_version.py -v "$version"
376+
377+
# commit and push reset branch
378+
git config core.sharedRepository true
379+
git config user.name "github-actions[bot]"
380+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
381+
git add -A
382+
git commit -m "ci(release): update to development version $version"
383+
git push -u origin $reset_branch
384+
385+
# create PR into develop
386+
body='
387+
# Reinitialize for development
388+
389+
Updates the `develop` branch from `master` following a successful release. Increments the patch version number.
390+
'
391+
gh pr create -B "develop" -H "$reset_branch" --title "Reinitialize develop branch" --draft --body "$body"

0 commit comments

Comments
 (0)