diff --git a/.github/workflows/create-releases.yml b/.github/workflows/create-releases.yml new file mode 100644 index 0000000..d3e6fe5 --- /dev/null +++ b/.github/workflows/create-releases.yml @@ -0,0 +1,35 @@ +name: Create releases and tags +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + unreleased-prs-metadata: + name: Get list of pending release pull requests + permissions: + pull-requests: read + contents: read + uses: equinor/radix-reusable-workflows/.github/workflows/template-unreleased-pr-metadata.yml@v1.0.2 + + release-pull-request: + name: Release pull request + needs: + - unreleased-prs-metadata + if: needs.unreleased-prs-metadata.outputs.unreleased-pull-request-count > 0 + strategy: + matrix: + pull-request-number: ${{ fromJson(needs.unreleased-prs-metadata.outputs.unreleased-pull-requests) }} + permissions: + pull-requests: write + contents: read + issues: write + uses: equinor/radix-reusable-workflows/.github/workflows/template-create-release-from-pr.yml@v1.0.2 + with: + pull-request-number: ${{ matrix.pull-request-number }} + use-github-app-token: true + github-app-id: ${{ vars.GH_APP_ID }} + secrets: + github-app-private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + \ No newline at end of file diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 72754b9..1e12595 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -7,6 +7,8 @@ on: jobs: test: runs-on: ubuntu-latest + permissions: + contents: read steps: - uses: actions/checkout@v4 @@ -21,6 +23,8 @@ jobs: lint: name: Lint runs-on: ubuntu-latest + permissions: + contents: read steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml new file mode 100644 index 0000000..0e87dd5 --- /dev/null +++ b/.github/workflows/prepare-release-pr.yml @@ -0,0 +1,24 @@ +name: Prepare release pull request +on: + push: + tags: + - '**' + branches: + - main + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }} + +jobs: + prepare-release-pr: + name: Prepare release pull request + uses: equinor/radix-reusable-workflows/.github/workflows/template-prepare-release-pr.yml@v1.0.2 + permissions: + contents: write + pull-requests: write + issues: write + with: + branch: main + cliff-config-path: cliff.toml + generate-pre-release-pr: false diff --git a/README.md b/README.md index e68873f..e5ebaa5 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,36 @@ [Radix](https://www.radix.equinor.com) is a PaaS. This document is for Radix developers, or anyone interested in poking around.. -* `tag` in git repository (in `main` branch) +## Development Process - Run following command to set `tag` (with corresponding version) - ``` - git tag v1.0.0 - git push origin v1.0.0 - ``` +The `radix-common` project follows a **trunk-based development** approach. - Want to contribute? Read our [contributing guideline](./contributing.md) +### ๐Ÿ” Workflow - [How to handle security issues](./security.md) +- **External contributors** should: + - Fork the repository + - Create a feature branch in their fork + +- **Maintainers** may create feature branches directly in the main repository. + +### โœ… Merging Changes + +All changes must be merged into the `main` branch using **pull requests** with **squash commits**. + +The squash commit message must follow the [Conventional Commits](https://www.conventionalcommits.org/en/about/) specification. + +## Release Process + +Merging a pull request into `main` triggers the **Prepare release pull request** workflow. +This workflow analyzes the commit messages to determine whether the version number should be bumped โ€” and if so, whether it's a major, minor, or patch change. + +It then creates a pull request for releasing a new stable version (e.g. `1.2.3`): +Merging this request triggers the **Create releases and tags** workflow, which reads the version stored in `version.txt`, creates a GitHub release, and tags it accordingly. + +## Contributing + +Want to contribute? Read our [contributing guidelines](./CONTRIBUTING.md) + +## Security + +[How to handle security issues](./security.md) diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..ab18efc --- /dev/null +++ b/cliff.toml @@ -0,0 +1,141 @@ +# git-cliff ~ configuration file +# https://git-cliff.org/docs/configuration + + +[changelog] +# A Tera template to be rendered as the changelog's footer. +# See https://keats.github.io/tera/docs/#introduction +header = """ +# Changelog\n +All notable changes to this project will be documented in this file.\n +""" +# A Tera template to be rendered for each release in the changelog. +# See https://keats.github.io/tera/docs/#introduction +body = """ +{%- macro remote_url() -%} + https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} +{%- endmacro -%} + +{% macro print_commit(commit) -%} + - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ + {% if commit.breaking %}[**breaking**] {% endif %}\ + {{ commit.message | upper_first }} - \ + ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ + {% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%} + {% if commit.remote.pr_number %} in \ + [#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \ + {%- endif %} +{% endmacro -%} + +{% if version %}\ + {% if previous.version %}\ + ## [{{ version | trim_start_matches(pat="v") }}]\ + ({{ self::remote_url() }}/compare/{{ previous.version }}..{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }} + {% else %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} + {% endif %}\ +{% else %}\ + ## [unreleased] +{% endif %}\ + +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | striptags | trim | upper_first }} + {% for commit in commits + | filter(attribute="scope") + | sort(attribute="scope") %} + {{ self::print_commit(commit=commit) }} + {%- endfor %} + {% for commit in commits %} + {%- if not commit.scope -%} + {{ self::print_commit(commit=commit) }} + {% endif -%} + {% endfor -%} +{% endfor -%} +{%- if github -%} +{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} + ## New Contributors โค๏ธ +{% endif %}\ +{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %} + * @{{ contributor.username }} made their first contribution + {%- if contributor.pr_number %} in \ + [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \ + {%- endif %} +{%- endfor -%} +{%- endif %} + +""" +# A Tera template to be rendered as the changelog's footer. +# See https://keats.github.io/tera/docs/#introduction +footer = """ + +""" +# Remove leading and trailing whitespaces from the changelog's body. +trim = true +# Render body even when there are no releases to process. +render_always = true +# An array of regex based postprocessors to modify the changelog. +postprocessors = [ + # Replace the placeholder with a URL. + #{ pattern = '', replace = "https://github.com/orhun/git-cliff" }, +] +# render body even when there are no releases to process +# render_always = true +# output file path +# output = "test.md" + +[git] +# Parse commits according to the conventional commits specification. +# See https://www.conventionalcommits.org +conventional_commits = true +# Exclude commits that do not match the conventional commits specification. +filter_unconventional = true +# Require all commits to be conventional. +# Takes precedence over filter_unconventional. +require_conventional = false +# Split commits on newlines, treating each line as an individual commit. +split_commits = false +# An array of regex based parsers to modify commit messages prior to further processing. +commit_preprocessors = [ + # Replace issue numbers with link templates to be updated in `changelog.postprocessors`. + #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, + # Check spelling of the commit message using https://github.com/crate-ci/typos. + # If the spelling is incorrect, it will be fixed automatically. + #{ pattern = '.*', replace_command = 'typos --write-changes -' }, +] +# Prevent commits that are breaking from being excluded by commit parsers. +protect_breaking_commits = false +# An array of regex based parsers for extracting data from the commit message. +# Assigns commits to groups. +# Optionally sets the commit's scope and can decide to exclude commits from further processing. +commit_parsers = [ + { message = "^feat", group = "๐Ÿš€ Features" }, + { message = "^fix", group = "๐Ÿ› Bug Fixes" }, + { message = "^docs", group = "๐Ÿ“š Documentation" }, + { message = "^perf", group = "โšก Performance" }, + { message = "^refactor", group = "๐Ÿšœ Refactor" }, + { message = "^style", group = "๐ŸŽจ Styling" }, + { message = "^test", group = "๐Ÿงช Testing" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore\\(deps.*\\)", skip = true }, + { message = "^chore\\(pr\\)", skip = true }, + { message = "^chore\\(pull\\)", skip = true }, + { message = "^chore|^ci", group = "โš™๏ธ Miscellaneous Tasks" }, + { body = ".*security", group = "๐Ÿ›ก๏ธ Security" }, + { message = "^revert", group = "โ—€๏ธ Revert" }, + { message = ".*", group = "๐Ÿ’ผ Other" }, +] +# Exclude commits that are not matched by any commit parser. +filter_commits = false +# An array of link parsers for extracting external references, and turning them into URLs, using regex. +link_parsers = [] +# Include only the tags that belong to the current branch. +use_branch_tags = false +# Order releases topologically instead of chronologically. +topo_order = false +# Order releases topologically instead of chronologically. +topo_order_commits = true +# Order of commits in each group/release within the changelog. +# Allowed values: newest, oldest +sort_commits = "oldest" +# Process submodules commits +recurse_submodules = false