zachdaniel / git_ops Goto Github PK
View Code? Open in Web Editor NEWA tool for version and changelog management in Elixir via conventional commits.
License: MIT License
A tool for version and changelog management in Elixir via conventional commits.
License: MIT License
mix git_ops.release --allow-major
and if thats not supplied, it will prompt for confirmation. This would have saved me lots of stress on multiple occasions ๐
This will have several benefits, particularly that with GitHub releases, the tag's message will be added into the body.
As @zachdaniel mentioned in a Discord conversation, the implementation should be pretty easy to add:
We'll probably need to update the
Changelog.write!/5
function to return the text contents that it wrote to the changelog, and then pass that into theconfirm_and_tag
function
If I got it right, adding a footer with BREAKING CHANGE: something
should bump the MAJOR version, but it is actually bumping the MINOR version.
If I would guess, this is related to the same problem highlighted in the #57 where a single commit is being split into multiple ones. Meaning that a BREAKING CHANGE is actually never inside the Commit
footer field
Various other tools require knowledge of the git repo, e.g. ex_doc
in mix.exs
and also allow configuration via the mix.exs
file. You have it twice (see also the typo in the first link :P) Allowing configuration here would be one fewer spot where a name of the git repo or even the app name itself would need to be propagated to. Additionally, several internal libraries do not even have config files except for git_ops
which feels really strange on a large enough number of projects.
In my umbrella project after mix git_ops.release --initial
I get error:
** (ArgumentError) cannot use an empty string as the match to replace
(elixir) lib/string.ex:823: String.replace_leading/3
lib/mix/tasks/git_ops.release.ex:100: Mix.Tasks.GitOps.Release.run/1
(mix) lib/mix/task.ex:316: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
and after commit commit like "fix: certificates updated"
I get error when I do mix git_ops.release in docker container:
/home/ds# MIX_ENV=dev mix git_ops.release
** (RuntimeError) No changes should result in a new release version.
Options:
* If no fixes or features were added, then perhaps you don't need to release.
* If a fix or feature commit was not correctly annotated, you could alter your git
history to fix it and run this command again, or create an empty commit via
`git commit --allow-empty` that contains an appropriate message.
* If you don't care and want a new version, you can use `--force-patch` which
will update the patch version regardless.
* You can add build metadata using `--build` that will signify that something was
unique about this build.
lib/git_ops/version.ex:25: GitOps.Version.determine_new_version/4
lib/mix/tasks/git_ops.release.ex:92: Mix.Tasks.GitOps.Release.run/1
(mix) lib/mix/task.ex:316: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2"
My mix.exs:
defp deps do
[
{:git_ops, "~> 0.5.0", only: [:dev]},
{:distillery, "~> 2.0", runtime: false, override: true},
{:credo, "~> 0.9.3", only: [:dev, :test]},
{:excoveralls, "~> 0.8.1", only: [:dev, :test]}
]
end
and config:
config :git_ops,
mix_project: DigitalSignatureUmbrella.MixProject,
changelog_file: "CHANGELOG.md",
repository_url: "https://github.com/edenlabllc/ds.api/",
types: [
# Makes an allowed commit type called `tidbit` that is not
# shown in the changelog
tidbit: [
hidden?: true
],
# Makes an allowed commit type called `important` that gets
# a section in the changelog with the header "Important Changes"
important: [
header: "Important Changes"
]
],
# Instructs the tool to manage your mix version in your `mix.exs` file
# See below for more information
manage_mix_version?: true,
# Instructs the tool to manage the version in your README.md
# Pass in `true` to use `"README.md"` or a string to customize
manage_readme_version: "README.md"
My commit:
git commit -am "fix: Update sign + stamp content"
This project use .so
files so in OSX it can be compiled only in docker container
Out of docker I get same error
The motivation for this is that some tools (like GitHub releases) will not parse the message content of git tags as Markdown. GitHub releases does however support Markdown in the release body if you specify it manually, which can be done in CI.
So, to make that content available to other tooling, it would be ideal to optionally allow a separate file, such as RELEASE_CHANGELOG.md
, which could be loaded directly
See changes in #30
The semver tags get filtered in 3-4 places currently and can be filtered on ingress. This requires perhaps opening the GitOps.Version.parse
code up but I think it would clean up the control flow and reduce the possibility of errors on tags that have out of band formats.
As per v1.0 of the Conventional Commits spec, a breaking change commit can be specified either by a BREAKING CHANGE:
footer or a ! after the required type
and the optional scope
.
The given exemple is:
refactor!: drop support for Node 6
So we need to accept the above, as opposed to
!refactor: drop support for Node 6
Due to the way --initial
works currently, it forces a script writer to check for the existence of CHANGELOG.md
or similar to know to call with this flag or not. This flag, or a similar flag, would be more flexible in scripts if it created if not exists but otherwise allowed the behavior to continue as though it already existed.
Hi,
This is probably related to the Roadmap point "Validation of commits".
I started to work on a mechanism to automatically validate the Git commit message by using a commit-msg
git hook. It uses two mix tasks:
mix git_ops.check_message
- receives the path to a commit message and validates if it follows the Conventional Commits spec using the existing parser in the project;mix git_ops.msg_hook
- install / uninstall a Git commit-msg
hook that calls the above task. It does nothing if the hook already exists. Some inspiration drown from here: https://github.com/qgadrian/elixir_git_hooksI have pushed these in the following branch: https://github.com/djantea/git_ops/tree/comm_msg_validation
The reasons I have not created the pull request are:
Something that could be part of a subsequent pull request:
3. To see if there is a way to automatically run mix git_ops.msg_hook
when compiling the project that includes git_ops
as a dependency, as a way to share the commit message validation mechanism with the team working on the project.
So inside a mix.exs
file, you can read files from priv
, and in order to play nicely with different tools that interact with version files, it might be nice to be able read from e.g. /priv/VERSION.txt
or something along those lines. Would it be possible to add the ability to specify the location of the version? The @version
tag would then @version File.read!("/priv/VERSION.txt")
in that case.
One concern I have is that then :manage_mix_version?
becomes weird, so it may need to be broken our to (e.g.) :manages_version?
and :version_location
with special behavior based on if that is mix.exs
.
https://github.com/zachdaniel/git_ops/blob/master/lib/mix/tasks/git_ops.release.ex#L103
prefix "" is not allowed by code String.trim_leading(prefixed_new_version, prefix)
- second arg could not be empty
Can a license be added to the project so people can fork/modify freely?
I have a Phoenix API app in project-name/backend
and JS web client in project-name/client
. Is it possible for git_ops to work with the Phoenix app in a subdirectory?
I tried modifying project-name/.git/hooks/commit-msg
command to MIX_EXS=backend/mix.exs mix git_ops.check_message "$@"
but I get errors:
Unchecked dependencies for environment dev:
* ex_aws_s3 (Hex package)
the dependency is not available, run "mix deps.get"
* another_dep (Hex package)
the dependency is not available, run "mix deps.get"
* another_dep (Hex package)
the dependency is not available, run "mix deps.get"
* another_dep (Hex package)
the dependency is not available, run "mix deps.get"
I added git_ops
to my mix.exs
but forgot to put in the config.exs
stuff before I ran mix git_ops.release --initial
for the first time. The resulting error message doesn't make it obvious what the problem was:
** (UndefinedFunctionError) function nil.project/0 is undefined. If you are using the dot syntax, such as map.field or module.function, make sure the left side of the dot is an atom or a map
nil.project()
lib/mix/tasks/git_ops.release.ex:62: Mix.Tasks.GitOps.Release.run/1
(mix) lib/mix/task.ex:316: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
Nowadays it is getting common for a git repository to have more than one project inside of it. For example, in my company we have a repo that has 2 elixir projects and one frontend/angular one.
That means that people will push commits to different projects in the same repo, so I need a way to filter out commits that are not related to the specific project I'm working on.
In our case, normally our commits will start with the project name, for example:
Backend: Did something
Frontend: Applied something else
It would be great if I could create rules in git_ops that will tell it to just add commits to my changelog when the title starts with Backend
via a regex.
Since this lib expects conventional commits, maybe another way of achieving the same would be to refex the content of the commit instead for some keyword?
Hi everyone!
Just included this tool as part of my workflow today and have to take my hat off to you guys, it works like a charm.
My team and I have been using Conventional Commits for some time and took the next step to also do semantic releases... However, after setting things up we discovered that the lib is not using the standard spec, but a modified/ mixed version between the Commitlint convention and then old Angular convention + and additional improvement
type (which has been discussed here and here and still not agreed upon).
So, the proposal is to use the standard spec types by changing the default_types attribute to default to only feat
and fix
. In addition to this change, another config called extended_types
should be added. This config would allow you to specify extra types to be merged into the default_types
attribute, making it easier to extend values as intended by the specification:
- @default_types [
- build: [
- hidden?: true
- ],
- chore: [
- hidden?: true
- ],
- ci: [
- hidden?: true
- ],
- docs: [
- hidden?: true
- ],
- feat: [
- header: "Features",
- hidden?: false
- ],
- fix: [
- header: "Bug Fixes",
- hidden?: false
- ],
- improvement: [
- header: "Improvements",
- hidden?: false
- ],
- perf: [
- header: "Performance Improvements",
- hidden?: false
- ],
- refactor: [
- hidden?: true
- ],
- style: [
- hidden?: true
- ],
- test: [
- hidden?: true
- ]
- ]
+ @standard_types [
+ feat: [header: "Features", hidden?: false],
+ fix: [header: "Bug Fixes", hidden?: false]
+ ]
+ @default_types Application.compile_env(:git_opts, :types, @standard_types)
+ @extended_types Application.compile_env(:git_ops, :extended_types, [])
[...]
def types do
- configured = Application.get_env(:git_ops, :types) || []
@default_types
|> Keyword.merge(@extended_types)
|> Enum.into(%{}, fn {key, value} ->
sanitized_key =
key
|> to_string()
|> String.downcase()
{sanitized_key, value}
end)
end
Another suggestion that can be part of this proposal is to add a preset
option to allow users to automatically opt-in to existing conventions - like the Commitlint or Angular convention that are mentioned in the Conventional Commits website.
PS.: Another thing that I was thinking is that since most of the config types default to hidden?: false
, wouldn't it be easier to invert the logic and use visible?: true
, while everything else defaults to visible: false
when the config is not present? On a side-note, if there are no other options other than header
and hidden?
, perhaps it would be better to use a tuple to configure that instead of a list.
Its really ugly/huge right now :)
Went through the code and didn't see anything like this. My project is a "poncho" setup in that its a bunch of apps in a parent directory (they don't share a mix file). I want to be able to use Git Ops to generate a changelog by installing it on one of the apps (the main entry point) and using the custom commits to delineate between the different libraries but it won't let me define where the .git
folder is and instead just initializes a .git
folder in the app's folder. Is there some way to do this that I am missing?
Currently it seems only a few of the commit types from the specification are supported, the full list includes:
Unless I'm missing something feat, fix, chore are the ones that this library can currently handle.
Tried installing the message hook for convention checks but it fails with the below:
** (KeyError) key :error not found in: %Git.Error{args: ["core.hookspath"], code: 1, command: "config", message: ""}
lib/git_ops/git.ex:90: GitOps.Git.handle_hooks_path_error/1
lib/mix/tasks/git_ops.message_hook.ex:180: Mix.Tasks.GitOps.MessageHook.commit_msg_hook_info!/1
lib/mix/tasks/git_ops.message_hook.ex:61: Mix.Tasks.GitOps.MessageHook.install/1
(mix 1.13.4) lib/mix/task.ex:397: anonymous fn/3 in Mix.Task.run_task/3
(mix 1.13.4) lib/mix/cli.ex:84: Mix.CLI.run_task/2
I recently did a release of Ash that generated a change log with a heap of extra stuff in it. I'm guessing that it's because I didn't have the previous version's tag fetched locally so the diff was incorrectly generated.
This should probably be detected and the command aborted with an error.
Hey everyone! I'm reaching out because you're a contributor on my git_ops
project on GitHub. The project can be found here: https://github.com/zachdaniel/git_ops. I've been notified that the license is actually much less permissive than we'd expect. Specifically, it is very unpermissive. Technically this means its a legal issue for those using it in their closed source work projects. However, this license is not in the spirit of what the creators intended. For ethical reasons, it is my responsibility to reach out to each contributor and confirm that they are okay with their work being relicensed under the MIT software license, which is extremely permissive. If those users would then like to update to the latest version of git_ops with that new license (once it is published) then all is well with the world and no one needs to worry.
Some names may already be checked off, which means that I received confirmation from them through various media. If I was able to contact them by email, their email is not included here for their own privacy.
If we can't get ahold of @benwoodward we can undo his changes until we hear from him (or permanently if we never do):
97db3b5
Just noticed this in one of our CI builds.
The blog link: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
It might be a super-quick fix - I'll take a look at implementing it and open a PR.
Summary: Currently git_ops doesn't seem compatible with Phoenix umbrella projects.
Install git_ops on each one of the umbrella apps
Inside the app folder execute mix git_ops.release --initial
Git ops should initialize the project on the right context
The following error happens when executing at
** (Git.Error) fatal: your current branch 'master' does not have any commits yet
lib/git.ex:128: Git.result_or_fail/1
lib/git_ops/git.ex:29: GitOps.Git.get_initial_commits!/1
lib/mix/tasks/git_ops.release.ex:140: Mix.Tasks.GitOps.Release.get_commit_messages/4
lib/mix/tasks/git_ops.release.ex:92: Mix.Tasks.GitOps.Release.run/1
(mix) lib/mix/task.ex:331: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
Installed at the main umbrella project resulted on a different failure where git_ops can't read the configuration from the child app.
It would be really nice if you could specify a version tag prefix (like v
) and it would use that prefix (like v1.2.3
) when tagging the release (and also look for that prefix when parsing existing versions).
It would also be great if there were a better error message when it fails to parse the version tags the way it's expecting to. Currently, this happens:
** (FunctionClauseError) no function clause matching in Version.parse!/1
The following arguments were given to Version.parse!/1:
# 1
nil
Attempted function clauses (showing 1 out of 1):
def parse!(string) when is_binary(string)
(elixir) lib/version.ex:282: Version.parse!/1
lib/git_ops/version.ex:30: GitOps.Version.determine_new_version/3
lib/mix/tasks/git_ops.release.ex:100: Mix.Tasks.GitOps.Release.run/1
(mix) lib/mix/task.ex:316: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
If git_ops was just added to your project and you want to run git_ops.release --initial
in dry run mode, i.e. git_ops.release --initial --dry-run --dry-run
, the Changelog.md file is still created. So if you want to run git_ops.release --initial
after that, it will fail because Changelog.md already exists, and the tool will ask you to delete it first before re-trying.
In my mind, running the mix task in dry run mode, shouldn't change anything on the disk, so that it will not affect subsequent executions of the same task.
Hi,
I've been trying to use git_ops
in one of my project's release pipeline, and I am surprised that when I push a chore
commit (or something that should not create a version bump), the mix task completes with a status code of 1, therefore failing the workflow. Since there's no version to be determined, isn't that expected behaviour? Could we just log it instead and continue?
We can look in the git-notes
for a commit to see if there is an updated description.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.