diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c8c4952e..58ead2bd 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -146,7 +146,7 @@ The following points should be considered when merging branches to `develop`: * Make sure the branch gets accepted by at least one developer with writing access. * Wait at least a day before merging, to allow other developers to inspect the pull request. * To simplify the git history, use "Squash and merge" in pull requests to `develop` (but **never** use this option when merging to `main`, see also below). -* As soon as the branch is merged, confirm that `develop` is still possible to merge to `main` (this can be checked [here](https://github.com/CompMetEng/GECKO/compare/develop)). If conflicts appear, fix the conflict _locally_ as soon as possible in `develop` and then push it (note, **DO NOT** pull any other changes from `main` to `develop`, just the single file that is creating the conflict). +* As soon as the branch is merged, confirm that `develop` is still possible to merge to `main` (this can be checked [here](https://github.com/CompMetEng/GECKO/compare/develop)). If conflicts appear, fix the conflict _locally_ as soon as possible in `develop` and then push it. Changes of `main` reach `develop` only through the pull request of the last step of [releasing a new version](#releasing-a-new-version). ### Releasing a new version @@ -164,15 +164,28 @@ GECKO follows [semantic versioning](https://semver.org/): - Re-organization of data - Refactoring of code. +`version.txt` and the version in the first sentence of the `README.md` after "About GECKO" are release-only: they exist on `main` and never on `develop`, which is ahead of the last release by an unknown number of changes. A check on every pull request into `develop` rejects `version.txt`. + When releasing, please follow these steps: -1. Create a pull request from `develop` to `main`: +1. Create the branch `release/` from `develop`, with two changes: + - Add `version.txt` containing the version, e.g. `4.0.0b2`. + - In `README.md`, replace "This is the development version of GECKO 4." by "This is GECKO ****." +2. Create a pull request from `release/` to `main`: - Specify the intended version in the title, e.g. `GECKO 3.0.1` - - Indicating all new features/fixes/etc. and referencing every previous pull request included (examples [here](https://github.com/CompMetEng/GECKO/releases)). + - Indicating all new features/fixes/etc. and referencing every previous pull request included (examples [here](https://github.com/CompMetEng/GECKO/releases)). The description is the release text, as GECKO has no changelog file. - If any [issue](https://github.com/CompMetEng/GECKO/issues) gets solved in the release, write in the pull request description "Closes #X", where "X" is the issue number. That way the issue will be automatically closed after merge. -2. Wait at least a day for at least one approval. The GitHub Actions must also pass successfully. -3. Merge the pull request from `develop` to `main` with the option "Create a merge commit", **not** "Squash and merge". -4. Edit the `version.txt` in the `main` branch directly [link](https://github.com/CompMetEng/GECKO/edit/main/version.txt) to refer to the new version number. Commit the change directly to the `main` branch. +3. Wait at least a day for at least one approval. The GitHub Actions must also pass successfully. +4. Merge the pull request into `main` with the option "Create a merge commit", **not** "Squash and merge". 5. Make the [new release](https://github.com/CompMetEng/GECKO/releases/new) at GitHub: - - Define a new tag with the version, prefixed by `v`: e.g. `v3.0.1`. - - Copy the description from the corresponding PR from step 1. + - Define a new tag with the version, without prefix: e.g. `4.0.0b2`, as the existing tags. + - Copy the description from the pull request of step 2. +6. Bring `main` back into `develop` through a pull request from a branch cut from `develop`, without the release-only changes: + ``` + git checkout -b sync/main-to-develop- origin/develop + git merge --no-commit --no-ff origin/main + git rm --cached version.txt + git checkout origin/develop -- README.md + git commit -m "chore: merge main into develop after " + ``` + Merge this pull request with "Create a merge commit". `develop` then contains `main`, and the next release pull request shows only the changes since this release. diff --git a/.github/workflows/branch-hygiene.yml b/.github/workflows/branch-hygiene.yml new file mode 100644 index 00000000..de1563f8 --- /dev/null +++ b/.github/workflows/branch-hygiene.yml @@ -0,0 +1,36 @@ +name: Branch hygiene + +# version.txt is stamped at release time and belongs on main only. develop is +# never "at" a version, it is ahead of the last release by an unknown number of +# changes. .gitignore cannot keep the file off develop: it is consulted only for +# untracked paths, so once the file is tracked on main, a merge of main into +# develop carries it across regardless. This check prevents that. +on: + pull_request: + branches: [develop] + push: + branches: [develop] + +jobs: + no-release-only-files-on-develop: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Checkout + uses: actions/checkout@v5 + + # On a pull_request event this runs against the merge result rather than + # the pull-request branch, so it answers "would develop contain this once + # this is merged?", which also catches a file arriving through a merge + # commit. + - name: No release-only files on develop + run: | + found=$(git ls-files 'version.txt') + if [ -n "$found" ]; then + echo "::error::version.txt is stamped at release time and belongs on main only." + echo "If it arrived here through a merge of main into develop, drop it in the merge commit:" + echo "" + echo " git rm --cached version.txt" + exit 1 + fi + echo "No release-only files tracked on develop." diff --git a/README.md b/README.md index 49960be5..eeacf47e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The **GECKO** toolbox enhances a **G**enome-scale model to account for **E**nzym GECKO is written in MATLAB. Its Python port, [geckopy](https://github.com/CompMetEng/geckopy), reads and writes the same ecModel YAML files, and the two toolboxes are kept in step by a [parity ledger](https://github.com/CompMetEng/raven-gecko-parity). The documentation covers both. -This is GECKO **4.0.0b1**. For the changes from GECKO 3, see [GECKO 3 → GECKO 4](https://gecko-docs.readthedocs.io/en/latest/gecko3-to-gecko4.html); for the differences between GECKO and geckopy, see [GECKO vs. geckopy](https://gecko-docs.readthedocs.io/en/latest/gecko-to-geckopy.html). +This is the development version of GECKO 4. For the changes from GECKO 3, see [GECKO 3 → GECKO 4](https://gecko-docs.readthedocs.io/en/latest/gecko3-to-gecko4.html); for the differences between GECKO and geckopy, see [GECKO vs. geckopy](https://gecko-docs.readthedocs.io/en/latest/gecko-to-geckopy.html). ## Get started diff --git a/src/gather_kcats/convertCustomKcats.m b/src/gather_kcats/convertCustomKcats.m index b777f2a3..c1d5aaf8 100644 --- a/src/gather_kcats/convertCustomKcats.m +++ b/src/gather_kcats/convertCustomKcats.m @@ -94,7 +94,7 @@ if ~isfolder(folder) mkdir(folder); end -gecko = strtrim(fileread(fullfile(findGECKOroot(), 'version.txt'))); +gecko = geckoVersion(); [~, name, ext] = fileparts(inFile); fid = fopen(file, 'w', 'n', 'UTF-8'); fprintf(fid, '# source: custom\n'); @@ -141,3 +141,12 @@ function checkOptions(args, names, functionName) strjoin(names, ', ')) end end + +function v = geckoVersion() +file = fullfile(findGECKOroot(), 'version.txt'); +if isfile(file) + v = strtrim(fileread(file)); +else + v = 'unknown'; +end +end diff --git a/version.txt b/version.txt deleted file mode 100644 index c9d9681b..00000000 --- a/version.txt +++ /dev/null @@ -1 +0,0 @@ -4.0.0b1