diff --git a/.github/actions/setup-ubuntu-host/action.yml b/.github/actions/setup-ubuntu-host/action.yml new file mode 100644 index 000000000..8ab3c2a4c --- /dev/null +++ b/.github/actions/setup-ubuntu-host/action.yml @@ -0,0 +1,19 @@ +name: 'Setup Ubuntu Runner Host' +inputs: + python-version: + description: 'Python version to use' + required: true +runs: + using: "composite" + steps: + - name: setup python + uses: actions/setup-python@v5 + with: + python-version: ${{inputs.python-version}} + cache: 'pip' # caching pip dependencies + - name: Install dependencies + shell: bash + run: | + sudo apt-get install libldap2-dev libsasl2-dev # Required for python-ldap + pip install --upgrade pip + pip install -r requirements.txt diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f9e4925a5..b71f8075f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,6 +7,11 @@ ## Checklist + - [ ] Have you linked a jira ticket and/or is the ticket in the title? - [ ] Have you checked whether your jira ticket required DOCSP changes? -- [ ] Have you checked for release_note changes? +- [ ] Have you added changelog file? + - use `skip-changelog` label if not needed + - refer + to [Changelog files and Release Notes](https://github.com/mongodb/mongodb-kubernetes/blob/master/CONTRIBUTING.md#changelog-files-and-release-notes) + section in CONTRIBUTING.md for more details diff --git a/.github/workflows/preview_release_notes.yml b/.github/workflows/preview_release_notes.yml new file mode 100644 index 000000000..0badd51cb --- /dev/null +++ b/.github/workflows/preview_release_notes.yml @@ -0,0 +1,46 @@ +name: Preview Release Notes +on: + push: + branches: + - master + - release-* + pull_request: + branches: + - master + - release-* + +jobs: + preview_release_notes: + name: Preview Release Notes + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: '0' + - name: Setup host + uses: ./.github/actions/setup-ubuntu-host + with: + python-version: '${{ vars.PYTHON_VERSION }}' + - name: Generate Release Notes + id: generate_release_notes + run: python -m scripts.release.release_notes -s $INITIAL_COMMIT_SHA -v $INITIAL_VERSION -o release_notes_tmp.md + env: + INITIAL_COMMIT_SHA: ${{ vars.RELEASE_INITIAL_COMMIT_SHA }} + INITIAL_VERSION: ${{ vars.RELEASE_INITIAL_VERSION }} + - name: Add disclaimer to release notes preview + run: | + echo -e "_:warning: (this preview might not be accurate if the PR is not rebased on current master branch)_\n" > release_notes_preview.md + cat release_notes_tmp.md >> release_notes_preview.md + - name: Summarize results + run: cat release_notes_preview.md >> $GITHUB_STEP_SUMMARY + - name: Update PR comment + # If the PR is from a fork, we cannot update the comment using read only permissions + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository + run: gh issue comment $ISSUE --edit-last --create-if-none --body-file release_notes_preview.md + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUE: ${{ github.event.pull_request.html_url }} diff --git a/.github/workflows/require_changelog.yml b/.github/workflows/require_changelog.yml new file mode 100644 index 000000000..d5811d36d --- /dev/null +++ b/.github/workflows/require_changelog.yml @@ -0,0 +1,35 @@ +name: Validate Changelog Requirement +on: + pull_request: + branches: + - master + - release-* + types: + - opened + - synchronize + - reopened + - labeled + - unlabeled + +jobs: + validate-changelog: + name: Check for valid changelog entry + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: '0' + - name: Setup host + uses: ./.github/actions/setup-ubuntu-host + with: + python-version: '${{ vars.PYTHON_VERSION }}' + - name: Check if changelog entry file was added in this PR + run: | + set -o pipefail + python -m scripts.release.check_changelog -b $BASE_SHA -f $FAIL_ON_NO_CHANGES | tee >> $GITHUB_STEP_SUMMARY + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + FAIL_ON_NO_CHANGES: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-changelog') }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d289d9dae..a7e4b1f4c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,51 @@ # Summary + Contributing to the Mongodb Controllers for Kubernetes (MCK) project -Pull requests are always welcome, and the MCK dev team appreciates any help the community can give to help make MongoDB better. +Pull requests are always welcome, and the MCK dev team appreciates any help the community can give to help make MongoDB +better. + +## PR Prerequisites -# PR Prerequisites -* Please ensure you have signed our Contributor Agreement. You can find it [here](https://www.mongodb.com/legal/contributor-agreement). +* Please ensure you have signed our Contributor Agreement. You can find + it [here](https://www.mongodb.com/legal/contributor-agreement). * Please ensure that all commits are signed. +* Create a changelog file that will describe the changes you made. Use the `skip-changelog` label if your changes do not + require a changelog entry. + +## Changelog files and Release Notes + +Each Pull Request usually has a changelog file that describes the changes made in the PR using Markdown syntax. +Changelog files are placed in the `changelog/` directory and used to generate the Release Notes for the +upcoming release. Preview of the Release Notes is automatically added as comment to each Pull Request. +The changelog file needs to follow the naming convention +`YYYYMMDD--.md`. To create changelog file please use the +`scripts/release/create_changelog.py` script. Example usage: + +```console +python3 -m scripts.release.create_changelog --kind fix "Fix that I want to describe in the changelog" +``` + +For more options, run the script with `--help`: + +```console +python3 -m scripts.release.create_changelog --help +usage: create_changelog.py [-h] [-c ] [-d ] [-e] -k title + +Utility to easily create a new changelog entry file. + +positional arguments: + title Title for the changelog entry + +options: + -h, --help show this help message and exit + -c, --changelog-path + Path to the changelog directory relative to a current working directory. Default is 'changelog/' + -d, --date Date in 'YYYY-MM-DD' format to use for the changelog entry. Default is today's date + -e, --editor Open the created changelog entry in the default editor (if set, otherwise uses 'vi'). Default is True + -k, --kind Kind of the changelog entry: + - 'prelude' for prelude entries + - 'breaking' for breaking change entries + - 'feature' for feature entries + - 'fix' for bugfix entries + - 'other' for other entries +``` diff --git a/scripts/release/check_changelog.py b/scripts/release/check_changelog.py new file mode 100644 index 000000000..6728e9ad0 --- /dev/null +++ b/scripts/release/check_changelog.py @@ -0,0 +1,79 @@ +import argparse +import pathlib + +from git import Repo + +from scripts.release.changelog import DEFAULT_CHANGELOG_PATH, get_changelog_entries + + +def str2bool(v): + if isinstance(v, bool): + return v + if v.lower() in ("yes", "true", "t", "y", "1"): + return True + elif v.lower() in ("no", "false", "f", "n", "0"): + return False + else: + raise argparse.ArgumentTypeError("Boolean value expected.") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Check if there are changelog entries", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + "-p", + "--path", + default=".", + metavar="", + action="store", + type=pathlib.Path, + help="Path to the Git repository. Default is the current directory '.'", + ) + parser.add_argument( + "-c", + "--changelog-path", + default=DEFAULT_CHANGELOG_PATH, + metavar="", + action="store", + type=str, + help=f"Path to the changelog directory relative to the repository root. Default is '{DEFAULT_CHANGELOG_PATH}'", + ) + parser.add_argument( + "-b", + "--base-sha", + metavar="", + action="store", + required=True, + type=str, + help="Base commit SHA to compare against. This should be the SHA of the base branch the Pull Request is targeting.", + ) + parser.add_argument( + "-f", + "--fail-on-no-changes", + default=True, + metavar="", + action="store", + type=str2bool, + nargs="?", + help="Fail if no changelog entries are found. Default is True.", + ) + args = parser.parse_args() + + repo = Repo(args.path) + base_commit = repo.commit(args.base_sha) + + try: + changelog = get_changelog_entries(base_commit, repo, args.changelog_path) + except Exception as e: + print(f"Error retrieving changelog entries. Possible validation issues: {e}") + exit(1) + + if not changelog: + print("No changelog entries found.") + if args.fail_on_no_changes: + print("Exiting with error due to no changelog entries found.") + exit(1) + else: + print("Changelog entries found and validated")