diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0333674e46..7b3bd375a51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,8 +57,11 @@ jobs: - name: Check Fortran source formatting run: python .github/common/fortran_format_check.py - - name: Check msvs project files + - name: Check MSVS project files run: python .github/common/msvs_vfproj_check.py + + - name: Check CITATION.cff + uses: dieghernan/cff-validator@v3 build: name: Build diff --git a/.github/workflows/release_dispatch.yml b/.github/workflows/release_dispatch.yml index 3037c98698e..efa9cc52295 100644 --- a/.github/workflows/release_dispatch.yml +++ b/.github/workflows/release_dispatch.yml @@ -240,82 +240,14 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: | # create draft release - ver=$(python distribution/update_version.py -g) - title="MODFLOW $ver" + version=$(python distribution/update_version.py -g) + title="MODFLOW $version" + citation=$(python distribution/update_version.py -c) notes=' - This is the approved USGS MODFLOW '$ver' release. + This is the approved USGS MODFLOW '$version' release. - *Insert citation here* + '$citation' Visit the USGS "MODFLOW and Related Programs" site for information on MODFLOW 6 and related software: https://doi.org/10.5066/F76Q1VQV ' - gh release create "$ver" ../mf*/mf*.zip ../release_notes/release.pdf --target master --title "$title" --notes "$notes" --draft --latest - - reset: - name: Draft reset PR - # runs only after GitHub release post is published (promoted from draft to public) - # to bring release commits from master back into develop and reset IDEVELOPMODE=1. - if: github.event_name == 'release' && (inputs.reset == 'true' || inputs.reset == '') - runs-on: ubuntu-22.04 - defaults: - run: - shell: bash -l {0} - steps: - - - name: Checkout modflow6 - uses: actions/checkout@v4 - with: - repository: ${{ github.repository_owner }}/modflow6 - path: modflow6 - - - name: Setup Micromamba - uses: mamba-org/setup-micromamba@v1 - with: - environment-file: modflow6/environment.yml - cache-downloads: true - cache-environment: true - - - name: Get release tag - uses: oprypin/find-latest-tag@v1 - id: latest_tag - with: - repository: ${{ github.repository }} - releases-only: true - - - name: Create pull request - working-directory: modflow6 - env: - GITHUB_TOKEN: ${{ github.token }} - run: | - # create reset branch from master - reset_branch="post-release-${{ steps.latest_tag.outputs.tag }}-reset" - git fetch origin - git checkout master - git switch -c $reset_branch - - # configure git - git config core.sharedRepository true - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - # updating version numbers if enabled - if [[ ("${{ inputs.commit_version }}" == "true") || ("${{ inputs.commit_version }}" == "") ]]; then - ver="${{ steps.latest_tag.outputs.tag }}" - python distribution/update_version.py -v "$ver" - git add -A - git commit -m "ci(release): update version to $ver, reset IDEVELOPMODE to 1" - else - # in either case we at least need to reset IDEVELOPMODE to 1 - python distribution/update_version.py - git add -A - git commit -m "ci(release): reset IDEVELOPMODE to 1" - fi - - # push reset branch - git push -u origin $reset_branch - - # create PR into develop - body=' - Reinitialize the `develop` branch following a successful release. - ' - gh pr create -B "develop" -H "$reset_branch" --title "Reinitialize develop branch" --draft --body "$body \ No newline at end of file + gh release create "$version" ../mf*/mf*.zip ../release_notes/release.pdf --target master --title "$title" --notes "$notes" --draft --latest diff --git a/CITATION.cff b/CITATION.cff index afb385b533a..c2fff462923 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -3,7 +3,7 @@ message: If you use this software, please cite the software itself. type: software title: MODFLOW 6 Modular Hydrologic Model version: 6.5.0.dev1 -date-released: '2024-02-07' +date-released: '2024-02-08' doi: 10.5066/F76Q1VQV abstract: MODFLOW 6 is an object-oriented program and framework developed to provide a platform for supporting multiple models and multiple types of models within the @@ -29,7 +29,7 @@ authors: affiliation: U.S. Geological Survey orcid: https://orcid.org/0000-0002-4443-1107 - family-names: Russcher - given-names: Martijn + given-names: Martijn J. alias: mjr-deltares affiliation: Deltares orcid: https://orcid.org/0000-0001-8799-6514 diff --git a/distribution/update_version.py b/distribution/update_version.py index e09e0c69aef..282c53593b4 100755 --- a/distribution/update_version.py +++ b/distribution/update_version.py @@ -123,6 +123,49 @@ def get_disclaimer(approved: bool = False, formatted: bool = False) -> str: return _preliminary_fmtdisclaimer if formatted else _preliminary_disclaimer +def get_software_citation( + timestamp: datetime, version: Version, approved: bool = False +) -> str: + # get data Software/Code citation for FloPy + citation = yaml.safe_load((project_root_path / "CITATION.cff").read_text()) + + sb = "" + if not approved: + sb = f" (preliminary)" + # format author names + authors = [] + for author in citation["authors"]: + tauthor = author["family-names"] + ", " + gnames = author["given-names"].split() + if len(gnames) > 1: + for gname in gnames: + tauthor += gname[0] + if len(gname) > 1: + tauthor += "." + # tauthor += " " + else: + tauthor += author["given-names"] + authors.append(tauthor.rstrip()) + + line = "" + for ipos, tauthor in enumerate(authors): + if ipos > 0: + line += ", " + if ipos == len(authors) - 1: + line += "and " + # add formatted author name to line + line += tauthor + + # add the rest of the citation + line += ( + f", {timestamp.year}, MODFLOW 6 Modular Hydrologic Model version {version}{sb}: " + f"U.S. Geological Survey Software Release, {timestamp:%-d %B %Y}, " + "https://doi.org/10.5066/P9FL1JCC" + ) + + return line + + def log_update(path, version: Version): print(f"Updated {path} with version {version}") @@ -292,11 +335,7 @@ def update_version( try: lock = FileLock(lock_path) previous = Version(version_file_path.read_text().strip()) - version = ( - version - if version - else previous - ) + version = version if version else previous with lock: update_version_txt_and_py(version, timestamp) @@ -320,7 +359,9 @@ def update_version( [ None, _initial_version, - Version(f"{_initial_version.major}.{_initial_version.minor}.dev{_initial_version.micro}"), + Version( + f"{_initial_version.major}.{_initial_version.minor}.dev{_initial_version.micro}" + ), ], ) @pytest.mark.parametrize("approved", [True, False]) @@ -417,17 +458,32 @@ def test_update_version(version, approved, developmode): action="store_true", help="Get the current version number, don't update anything (defaults to false)", ) + parser.add_argument( + "-c", + "--citation", + required=False, + action="store_true", + help="Show the citation, don't update anything (defaults to False)", + ) args = parser.parse_args() + approved = args.approved + releasemode = args.releasemode + version = Version(args.version) if args.version else _current_version if args.get: print(Version((project_root_path / "version.txt").read_text().strip())) + elif args.citation: + print( + get_software_citation( + timestamp=datetime.now(), version=version, approved=approved + ) + ) else: - print(f"Updating to version {args.version} with options") - print(f" releasemode: {args.releasemode}") - print(f" approved: {args.approved}") - version = Version(args.version) if args.version else _current_version + print(f"Updating to version {version} with options") + print(f" approved: {approved}") + print(f" releasemode: {releasemode}") update_version( version=version, timestamp=datetime.now(), - approved=args.approved, - developmode=not args.releasemode, + approved=approved, + developmode=not releasemode, )