Skip to content

Commit 17f2797

Browse files
authored
DAS-2267: Add CI config for testing and reporting. (#4)
1 parent e532406 commit 17f2797

9 files changed

Lines changed: 245 additions & 79 deletions

File tree

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# This workflow will build and publish Docker image to ghcr.io
2+
3+
# This workflow runs when changes are detected in the `main` branch, which
4+
# include an update to the `docker/service_version.txt` file. The workflow can
5+
# also be manually triggered by a repository maintainer.
6+
7+
# IF all pre-requisite tests pass, this workflow will build the docker images,
8+
# push them to ghcr.io and publish a GitHub release.
9+
name: Publish SMAP L2 Gridding Service
10+
11+
on:
12+
push:
13+
branches: [ main ]
14+
paths: docker/service_version.txt
15+
workflow_dispatch:
16+
17+
env:
18+
IMAGE_NAME: ${{ github.repository }}
19+
REGISTRY: ghcr.io
20+
21+
jobs:
22+
run_service_tests:
23+
uses: ./.github/workflows/run_service_tests.yml
24+
25+
run_lib_tests:
26+
uses: ./.github/workflows/run_lib_tests.yml
27+
28+
mypy:
29+
uses: ./.github/workflows/mypy.yml
30+
31+
build_and_publish:
32+
needs: [run_service_tests, run_lib_tests, mypy]
33+
runs-on: ubuntu-latest
34+
environment: release
35+
permissions:
36+
# write permission is required to create a GitHub release
37+
contents: write
38+
id-token: write
39+
packages: write
40+
strategy:
41+
fail-fast: false
42+
43+
steps:
44+
- name: Checkout smap-l2-gridder repository
45+
uses: actions/checkout@v4
46+
with:
47+
lfs: true
48+
49+
- name: Extract semantic version number
50+
run: echo "semantic_version=$(cat docker/service_version.txt)" >> $GITHUB_ENV
51+
52+
- name: Extract release version notes
53+
run: |
54+
version_release_notes=$(./bin/extract-release-notes.sh)
55+
echo "RELEASE_NOTES<<EOF" >> $GITHUB_ENV
56+
echo "${version_release_notes}" >> $GITHUB_ENV
57+
echo "EOF" >> $GITHUB_ENV
58+
59+
- name: Log-in to ghcr.io registry
60+
uses: docker/login-action@v2
61+
with:
62+
registry: ${{ env.REGISTRY }}
63+
username: ${{ github.actor }}
64+
password: ${{ secrets.GITHUB_TOKEN }}
65+
66+
- name: Add tags to the Docker image
67+
id: meta
68+
uses: docker/metadata-action@v4
69+
with:
70+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
71+
tags: |
72+
type=semver,pattern={{version}},value=${{ env.semantic_version }}
73+
74+
- name: Push Docker image
75+
uses: docker/build-push-action@v3
76+
with:
77+
context: .
78+
file: docker/service.Dockerfile
79+
push: true
80+
tags: ${{ steps.meta.outputs.tags }}
81+
labels: ${{ steps.meta.outputs.labels }}
82+
83+
- name: Publish GitHub release
84+
uses: ncipollo/release-action@v1
85+
with:
86+
body: ${{ env.RELEASE_NOTES }}
87+
commit: main
88+
name: Version ${{ env.semantic_version }}
89+
tag: ${{ env.semantic_version }}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This workflow will run the appropriate library tests across a python matrix of versions.
2+
name: Run Python library tests
3+
4+
on:
5+
workflow_call
6+
7+
jobs:
8+
build_and_test_lib:
9+
runs-on: ubuntu-latest
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
python-version: ['3.10', '3.11', '3.12']
14+
15+
steps:
16+
- name: Checkout smap-l2-gridder repository
17+
uses: actions/checkout@v4
18+
with:
19+
lfs: true
20+
21+
- name: Set up Python ${{ matrix.python-version }}
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: ${{ matrix.python-version }}
25+
26+
- name: Install dependencies
27+
run: |
28+
python -m pip install --upgrade pip
29+
pip install pytest
30+
pip install -r pip_requirements.txt -r tests/pip_test_requirements.txt
31+
32+
- name: Run science tests while excluding the service tests.
33+
run: |
34+
pytest tests --ignore tests/test_service
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# This workflow will build the service and test Docker images for smap-l2-gridder,
2+
# then run the `pytest` suite within a test Docker container, reporting
3+
# test results and code coverage as artefacts. It will be called by the
4+
# workflow that run tests against new PRs and as a first step in the workflow
5+
# that publishes new Docker images.
6+
7+
name: Run Python Service Tests
8+
9+
on:
10+
workflow_call
11+
12+
jobs:
13+
build_and_test_service:
14+
runs-on: ubuntu-latest
15+
strategy:
16+
fail-fast: false
17+
18+
steps:
19+
- name: Checkout smap-l2-gridder repository
20+
uses: actions/checkout@v4
21+
with:
22+
lfs: true
23+
24+
- name: Build service image
25+
run: ./bin/build-image
26+
27+
- name: Build test image
28+
run: ./bin/build-test
29+
30+
- name: Run test image
31+
run: ./bin/run-test
32+
33+
- name: Archive test results and coverage
34+
uses: actions/upload-artifact@v4
35+
with:
36+
name: reports
37+
path: reports/**/*

.github/workflows/run_tests_on_pull_requests.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,11 @@ on:
1111
workflow_dispatch:
1212

1313
jobs:
14+
build_and_test_service:
15+
uses: ./.github/workflows/run_service_tests.yml
16+
17+
run_lib_tests:
18+
uses: ./.github/workflows/run_lib_tests.yml
19+
1420
mypy:
1521
uses: ./.github/workflows/mypy.yml

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [Unreleased]
8+
## [v0.0.1] - 2024-11-27
99

1010
### Added
1111

1212
- Initial codebase that transforms SPL2SMP_E granules into NetCDF4-CF grids. [#1](https://github.com/nasa/harmony-SMAP-L2-gridding-service/pull/1)
1313
- Code and configuration to wrap gridding logic into a Harmony Service [#3](https://github.com/nasa/harmony-SMAP-L2-gridding-service/pull/3 )
14+
- GitHub actions CI configuration [#4](https://github.com/nasa/harmony-SMAP-L2-gridding-service/pull/4 )
15+
16+
17+
[v0.0.1]: https://github.com/nasa/harmony-SMAP-L2-gridding-service/releases/tag/0.0.1

README.md

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pip install pre-commit
104104
pre-commit install
105105
```
106106

107-
## Versioning:
107+
## Versioning
108108

109109
Docker service images for the `smap_l2_gridder` adhere to [semantic
110110
version](https://semver.org/) numbers: major.minor.patch.
@@ -113,13 +113,54 @@ version](https://semver.org/) numbers: major.minor.patch.
113113
* Minor increments: These are backwards compatible API changes.
114114
* Patch increments: These updates do not affect the API to the service.
115115

116-
## CI/CD:
116+
## CI/CD
117117

118118
The CI/CD for SMAP-L2-Gridding-Service is run on github actions with the workflows in the
119119
`.github/workflows` directory:
120120

121-
* [TODO: complete this section when the above statement is true]
121+
* `run_lib_tests.yml` - A reusable workflow that tests the library functions
122+
against the supported python versions.
123+
* `run_service_tests.yml` - A reusable workflow that builds the service and
124+
test Docker images, then runs the Python unit test suite in an instance of
125+
the test Docker container.
126+
* `run_tests_on_pull_requests.yml` - Triggered for all PRs against the `main`
127+
branch. It runs the workflow in `run_service_tests.yml` and
128+
`run_lib_tests.yml` to ensure all tests pass for the new code.
129+
* `publish_docker_image.yml` - Triggered either manually or for commits to the
130+
`main` branch that contain changes to the `docker/service_version.txt` file.
131+
* `publish_release.yml`<a name="release-workflow"></a> - workflow runs
132+
automatically when there is a change to the `docker/service_version.txt`
133+
file on the main branch. This workflow will:
134+
* Run the full unit test suite, to prevent publication of broken code.
135+
* Extract the semantic version number from `docker/service_version.txt`.
136+
* Extract the released notes for the most recent version from `CHANGELOG.md`.
137+
* Build and deploy a this service's docker image to `ghcr.io`.
138+
* Publish a GitHub release under the semantic version number, with associated
139+
git tag.
140+
122141

123142
## Releasing
124143

125-
* [TODO: complete when implemented]
144+
A release consists of a new Docker image for the harmony-SMAP-L2-gridding-service
145+
published to github's container repository.
146+
147+
A release is made automatically when a commit to the main branch contains a
148+
changes in the `docker/service_version.txt` file, see the [publish_release](#release-workflow) workflow in the CI/CD section above.
149+
150+
Before **merging** a PR that will trigger a release, ensure these two files are updated:
151+
152+
* `CHANGELOG.md` - Notes should be added to capture the changes to the service and a link to the current pull request should be included.
153+
* `docker/service_version.txt` - The semantic version number should be updated to trigger the release.
154+
155+
The `CHANGELOG.md` file requires a specific format for a new release, as it
156+
looks for the following string to define the newest release of the code
157+
(starting at the top of the file).
158+
159+
```
160+
## [vX.Y.Z] - YYYY-MM-DD
161+
```
162+
163+
Where the markdown reference needs to be updated at the bottom of the file following the existing pattern.
164+
```
165+
[vX.Y.Z]: https://github.com/nasa/harmony-SMAP-L2-gridding-service/releases/tag/X.Y.Z
166+
```

bin/extract-release-notes.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
###############################################################################
3+
#
4+
# A bash script to extract only the notes related to the most recent version of
5+
# SMAP L2 Gridding Service from CHANGELOG.md
6+
#
7+
###############################################################################
8+
9+
CHANGELOG_FILE="CHANGELOG.md"
10+
11+
## captures versions
12+
## >## v1.0.0
13+
## >## [v1.0.0]
14+
VERSION_PATTERN="^## [\[]v"
15+
16+
## captures url links
17+
## [unreleased]:https://github.com/nasa/harmony-browse-image-generator/compare/1.2.0..HEAD
18+
## [v1.2.0]: https://github.com/nasa/harmony-browse-image-generator/compare/1.1.0..1.2.0
19+
LINK_PATTERN="^\[.*\].*\.\..*"
20+
21+
# Read the file and extract text between the first two occurrences of the
22+
# VERSION_PATTERN
23+
result=$(awk "/$VERSION_PATTERN/{c++; if(c==2) exit;} c==1" "$CHANGELOG_FILE")
24+
25+
# Print the result
26+
echo "$result" | grep -v "$VERSION_PATTERN" | grep -v "$LINK_PATTERN"

docker/service_version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.0
1+
0.0.1

smap_l2_gridder/crs.py

Lines changed: 2 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -38,84 +38,13 @@ def col_row_to_xy(self, col: int, row: int) -> tuple[np.float64, np.float64]:
3838
return x, y
3939

4040

41-
# The authoritative value of well known text strings is from epsg.org
42-
43-
# The pyproj CRS created from this WKT string is the same as a CRS that has been
44-
# round tripped through the CRS creation process. But the output value on the
45-
# files CRS metadata may not match the authoritative value because of the
46-
# different varieties of WKT. That said, the CRS created by pyproj is the same.
47-
# i.e.
48-
# pyproj.crs.CRS.from_wkt(EPSG_6933_WKT).to_wkt() != EPSG_6933_WKT
49-
# but
50-
# pyproj.crs.CRS.from_wkt(pyproj.crs.CRS.from_wkt(EPSG_6933_WKT).to_wkt())
51-
# == pyproj.crs.CRS.from_wkt(EPSG_6933_WKT)
52-
5341
# NSIDC EASE-Grid 2.0 Global CRS definition
5442
# from: https://epsg.org/crs/wkt/id/6933
55-
EPSG_6933_WKT = (
56-
'PROJCRS["WGS 84 / NSIDC EASE-Grid 2.0 Global",'
57-
'BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble", '
58-
'MEMBER["World Geodetic System 1984 (Transit)", ID["EPSG",1166]], '
59-
'MEMBER["World Geodetic System 1984 (G730)", ID["EPSG",1152]], '
60-
'MEMBER["World Geodetic System 1984 (G873)", ID["EPSG",1153]], '
61-
'MEMBER["World Geodetic System 1984 (G1150)", ID["EPSG",1154]], '
62-
'MEMBER["World Geodetic System 1984 (G1674)", ID["EPSG",1155]], '
63-
'MEMBER["World Geodetic System 1984 (G1762)", ID["EPSG",1156]], '
64-
'MEMBER["World Geodetic System 1984 (G2139)", ID["EPSG",1309]], '
65-
'MEMBER["World Geodetic System 1984 (G2296)", ID["EPSG",1383]], '
66-
'ELLIPSOID["WGS 84",6378137,298.257223563,'
67-
'LENGTHUNIT["metre",1,ID["EPSG",9001]],ID["EPSG",7030]], '
68-
'ENSEMBLEACCURACY[2],ID["EPSG",6326]],ID["EPSG",4326]],'
69-
'CONVERSION["US NSIDC EASE-Grid 2.0 Global",'
70-
'METHOD["Lambert Cylindrical Equal Area",ID["EPSG",9835]],'
71-
'PARAMETER["Latitude of 1st standard parallel",30,'
72-
'ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9102]],'
73-
'ID["EPSG",8823]],PARAMETER["Longitude of natural origin",0,'
74-
'ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9102]],'
75-
'ID["EPSG",8802]],PARAMETER["False easting",0,'
76-
'LENGTHUNIT["metre",1,ID["EPSG",9001]],ID["EPSG",8806]],'
77-
'PARAMETER["False northing",0,LENGTHUNIT["metre",1,ID["EPSG",9001]],'
78-
'ID["EPSG",8807]],ID["EPSG",6928]],CS[Cartesian,2,ID["EPSG",4499]],'
79-
'AXIS["Easting (X)",east],AXIS["Northing (Y)",north],'
80-
'LENGTHUNIT["metre",1,ID["EPSG",9001]],ID["EPSG",6933]]'
81-
)
43+
EPSG_6933_WKT = CRS.from_epsg(6933).to_wkt()
8244

8345
# NSIDC EASE-Grid 2.0 North CRS definition
8446
# from: https://epsg.org/crs/wkt/id/6931
85-
EPSG_6931_WKT = (
86-
'PROJCRS["WGS 84 / NSIDC EASE-Grid 2.0 North",'
87-
'BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble", '
88-
'MEMBER["World Geodetic System 1984 (Transit)", ID["EPSG",1166]], '
89-
'MEMBER["World Geodetic System 1984 (G730)", ID["EPSG",1152]], '
90-
'MEMBER["World Geodetic System 1984 (G873)", ID["EPSG",1153]], '
91-
'MEMBER["World Geodetic System 1984 (G1150)", ID["EPSG",1154]], '
92-
'MEMBER["World Geodetic System 1984 (G1674)", ID["EPSG",1155]], '
93-
'MEMBER["World Geodetic System 1984 (G1762)", ID["EPSG",1156]], '
94-
'MEMBER["World Geodetic System 1984 (G2139)", ID["EPSG",1309]], '
95-
'MEMBER["World Geodetic System 1984 (G2296)", ID["EPSG",1383]], '
96-
'ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1,'
97-
'ID["EPSG",9001]],ID["EPSG",7030]], ENSEMBLEACCURACY[2],'
98-
'ID["EPSG",6326]],ID["EPSG",4326]],'
99-
'CONVERSION["US NSIDC EASE-Grid 2.0 North",'
100-
'METHOD["Lambert Azimuthal Equal Area",'
101-
'ID["EPSG",9820]],PARAMETER["Latitude of natural origin",90,'
102-
'ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9102]],ID["EPSG",8801]],'
103-
'PARAMETER["Longitude of natural origin",0,'
104-
'ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9102]],ID["EPSG",8802]],'
105-
'PARAMETER["False easting",0,LENGTHUNIT["metre",1,ID["EPSG",9001]],'
106-
'ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1,'
107-
'ID["EPSG",9001]],ID["EPSG",8807]],ID["EPSG",6929]],CS[Cartesian,2,'
108-
'ID["EPSG",4469]],AXIS["Easting (X)",South,MERIDIAN[90.0,'
109-
'ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9102]]]],'
110-
'AXIS["Northing (Y)",South,MERIDIAN[180.0,'
111-
'ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9102]]]],'
112-
'LENGTHUNIT["metre",1,ID["EPSG",9001]],ID["EPSG",6931]]'
113-
)
114-
115-
GPD_TO_WKT = {
116-
'EASE2_N09km.gpd': EPSG_6931_WKT,
117-
'EASE2_M09km.gpd': EPSG_6933_WKT,
118-
}
47+
EPSG_6931_WKT = CRS.from_epsg(6931).to_wkt()
11948

12049

12150
def geotransform_from_target_info(target_info: dict) -> Geotransform:

0 commit comments

Comments
 (0)