{"id":13933019,"url":"https://github.com/sbt/sbt-dynver","last_synced_at":"2025-05-16T01:06:24.845Z","repository":{"id":38475290,"uuid":"68446926","full_name":"sbt/sbt-dynver","owner":"sbt","description":"An sbt plugin to dynamically set your version from git","archived":false,"fork":false,"pushed_at":"2025-05-09T13:25:28.000Z","size":532,"stargazers_count":304,"open_issues_count":31,"forks_count":50,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-05-12T08:56:31.139Z","etag":null,"topics":["dynamic-version","sbt","sbt-plugin","versioning"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sbt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-17T10:56:20.000Z","updated_at":"2025-05-09T13:25:32.000Z","dependencies_parsed_at":"2022-07-11T19:53:09.505Z","dependency_job_id":"13096d36-6959-48c5-9262-45dddcce24eb","html_url":"https://github.com/sbt/sbt-dynver","commit_stats":null,"previous_names":["dwijnand/sbt-dynver"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbt%2Fsbt-dynver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbt%2Fsbt-dynver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbt%2Fsbt-dynver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbt%2Fsbt-dynver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sbt","download_url":"https://codeload.github.com/sbt/sbt-dynver/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253939146,"owners_count":21987411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dynamic-version","sbt","sbt-plugin","versioning"],"created_at":"2024-08-07T21:01:29.232Z","updated_at":"2025-05-16T01:06:19.814Z","avatar_url":"https://github.com/sbt.png","language":"Scala","funding_links":[],"categories":["Scala"],"sub_categories":[],"readme":"# sbt-dynver\n\n`sbt-dynver` is an [sbt](http://www.scala-sbt.org/) plugin to dynamically set your version from git.\n\nInspired by:\n* The way that Mercurial [versions itself](https://selenic.com/hg/file/3.9.1/setup.py#l179)\n* The\n  [GitVersioning](https://github.com/sbt/sbt-git/blob/v0.8.5/src/main/scala/com/typesafe/sbt/SbtGit.scala#L266-L270)\n  AutoPlugin in [sbt-git](https://github.com/sbt/sbt-git).\n\nFeatures:\n* Dynamically set your version by looking at the closest tag to the current commit\n* Detect the previous version\n    * Useful for automatic [binary compatibility checks](https://github.com/lightbend/migration-manager) across library versions\n\n## Setup\n\nAdd this to your sbt build plugins, in either `project/plugins.sbt` or `project/dynver.sbt`:\n\n    addSbtPlugin(\"com.github.sbt\" % \"sbt-dynver\" % \"x.y.z\")\n    // Until version 4.1.1:\n    addSbtPlugin(\"com.dwijnand\" % \"sbt-dynver\" % \"4.1.1\")\n\nThe latest release is: [![dynver Scala version support](https://index.scala-lang.org/sbt/sbt-dynver/dynver/latest.svg)](https://index.scala-lang.org/sbt/sbt-dynver/dynver)\n\nThen make sure to **NOT set the version setting**, otherwise you will override `sbt-dynver`.\n\nIn CI, if you're using GitHub Actions and\n[actions/checkout](https://github.com/actions/checkout) you may need to use\n`fetch-depth: 0` to avoid situations where a shallow clone will result in the\nlast tag not being fetched.\n\n```yaml\n  - uses: actions/checkout@v3\n    with:\n      fetch-depth: 0\n```\n\nIf you're manually running git commands then you may need to run `git fetch\n--unshallow` (or, sometimes, `git fetch --depth=10000`). Additionally `git fetch\n--tags` if the repo is cloned with `--no-tags`.\n\nOther than that, as `sbt-dynver` is an AutoPlugin that is all that is required.\n\n## Detail\n\n`ThisBuild / version`, `ThisBuild / isSnapshot` and `ThisBuild / isVersionStable` will be automatically set to:\n\n```\n| tag    | dist | HEAD sha | dirty | version                        | isSnapshot | isVersionStable |\n| ------ | ---- | -------- | ----- | ------------------------------ | ---------- | --------------- |\n| v1.0.0 | 0    | -        | No    | 1.0.0                          | false      | true            |\n| v1.0.0 | 0    | 1234abcd | Yes   | 1.0.0+0-1234abcd+20140707-1030 | true       | false           |\n| v1.0.0 | 3    | 1234abcd | No    | 1.0.0+3-1234abcd               | true       | true            |\n| v1.0.0 | 3    | 1234abcd | Yes   | 1.0.0+3-1234abcd+20140707-1030 | true       | false           |\n| \u003cnone\u003e | 3    | 1234abcd | No    | 0.0.0+3-1234abcd               | true       | true            |\n| \u003cnone\u003e | 3    | 1234abcd | Yes   | 0.0.0+3-1234abcd+20140707-1030 | true       | false           |\n| no commits or no git repo at all | HEAD+20140707-1030             | true       | false           |\n```\n\nWhere:\n* `tag` means what is the latest tag (relative to HEAD)\n* `dist` means the distance of the HEAD commit from the tag\n* `dirty` refers to whether there are local changes in the git repo\n\n#### Previous Version Detection\n\nGiven the following git history, here's what `previousStableVersion` returns when at each commit:\n\n```\n*   (tagged: v1.1.0)       --\u003e Some(\"1.0.0\")\n*   (untagged)             --\u003e Some(\"1.0.0\")\n| * (tagged: v2.1.0)       --\u003e Some(\"2.0.0\")\n| * (tagged: v2.0.0)       --\u003e Some(\"1.0.0\")\n|/\n*   (tagged: v1.0.0)       --\u003e None\n*   (untagged)             --\u003e None\n```\n\nPrevious version is detected by looking at the closest tag of the parent commit of HEAD.\n\nIf the current commit has multiple parents, the first parent will be used. In git, the first parent\ncomes from the branch you merged into (e.g. `master` in `git checkout master \u0026\u0026 git merge my-feature-branch`)\n\nTo use this feature with the Migration Manager [MiMa](https://github.com/lightbend/migration-manager) sbt plugin, add\n\n```scala\nmimaPreviousArtifacts := previousStableVersion.value.map(organization.value %% moduleName.value % _).toSet\n```\n\n## Tag Requirements\n\nIn order to be recognized by sbt-dynver, by default tags must begin with the lowercase letter 'v' followed by a digit.\n\nIf you're not seeing what you expect, then either start with this:\n\n    git tag -a v0.0.1 -m \"Initial version tag for sbt-dynver\"\n\nor change the value of `ThisBuild / dynverVTagPrefix` to remove the requirement for the v-prefix:\n\n    ThisBuild / dynverVTagPrefix := false\n\nor, more generally, use `ThisBuild / dynverTagPrefix` to fully customising tag prefixes, for example:\n\n    ThisBuild / dynverTagPrefix := \"foo-\" // our tags have the format foo-\u003cversion\u003e, e.g. foo-1.2.3\n\n## Tasks\n\n* `dynver`: Returns the dynamic version of your project, inferred from the git metadata\n* `dynverCurrentDate`: Returns the captured current date. Used for (a) the dirty suffix of `dynverGitDescribeOutput` and (b) the fallback version (e.g if not a git repo).\n* `dynverGitDescribeOutput`: Returns the captured `git describe` out, in a structured form. Useful to define a [custom version string](#custom-version-string).\n* `dynverCheckVersion`: Checks if version and dynver match\n* `dynverAssertVersion`: Asserts if version and dynver match\n\n## Publishing to Sonatype's snapshots repository (aka \"Sonatype mode\")\n\nIf you're publishing to Sonatype sonashots then enable `ThisBuild / dynverSonatypeSnapshots := true` to append\n\"-SNAPSHOT\" to the version if `isSnapshot` is `true` (which it is unless building on a tag with no local\nchanges).  This opt-in exists because the Sonatype's snapshots repository requires all versions to end with\n`-SNAPSHOT`.\n\n## Portable version strings\n\nThe default version string format includes `+` characters, which is an escape character in URL and is not compatible with docker tags.\nThis character can be overridden by setting:\n\n```scala\nThisBuild / dynverSeparator := \"-\"\n```\n\nIf you don't want to override `dynverSeparator` for your whole project you can instead do the following\ninstead (assuming you have a sbt sub project for your docker build)\n\n```scala\nlazy val dockerBuild = project\n  .in(\"docker-build\")\n  .settings(\n    inConfig(Docker)(DynVerPlugin.buildSettings ++ Seq(dynverSeparator := \"-\"))\n  )\n```\n\n## Custom version string\n\nSometimes you want to customise the version string. It might be for personal preference, or for compatibility with another tool or spec.\n\nFor simple cases you can customise a version by simply post-processing the value of `ThisBuild / version` (and optionally `ThisBuild / dynver`), for example by replacing '+' with '-' (emulating the docker support mentioned above):\n\n```scala\nThisBuild / version ~= (_.replace('+', '-'))\nThisBuild / dynver  ~= (_.replace('+', '-'))\n```\n\nTo completely customise the string format you can use `dynverGitDescribeOutput`, `dynverCurrentDate` and `sbtdynver.DynVer`, like so:\n\n```scala\ndef versionFmt(out: sbtdynver.GitDescribeOutput): String = {\n  val dirtySuffix = out.dirtySuffix.dropPlus.mkString(\"-\", \"\")\n  if (out.isCleanAfterTag) out.ref.dropPrefix + dirtySuffix // no commit info if clean after tag\n  else out.ref.dropPrefix + out.commitSuffix.mkString(\"-\", \"-\", \"\") + dirtySuffix\n}\n\ndef fallbackVersion(d: java.util.Date): String = s\"HEAD-${sbtdynver.DynVer timestamp d}\"\n\ninThisBuild(List(\n  version := dynverGitDescribeOutput.value.mkVersion(versionFmt, fallbackVersion(dynverCurrentDate.value)),\n   dynver := {\n     val d = new java.util.Date\n     sbtdynver.DynVer.getGitDescribeOutput(d).mkVersion(versionFmt, fallbackVersion(d))\n   }\n))\n```\n\nEssentially this:\n\n1. defines how to transform the structured output of `git describe`'s into a string, with `versionFmt`\n2. defines the fallback version string, with `fallbackVersion`, and\n3. wires everything back together\n\n## Sanity checking the version\n\nAs a sanity check, you can stop the build from loading by running a check during sbt's `onLoad`.\nFor instance, to make sure that the version is derived from tags you can use:\n\n```scala\nGlobal / onLoad := (Global / onLoad).value.andThen { s =\u003e\n  dynverAssertTagVersion.value\n  s\n}\n```\n\nThis will return an error message like the following:\n\n```\n[error] Failed to derive version from git tags. Maybe run `git fetch --unshallow`? Version: 3-d9489763\n```\n\nOr, using sbt-dynver v1.1.0 to v4.0.0:\n\n```scala\nGlobal / onLoad := (Global / onLoad).value.andThen { s =\u003e\n  val v = version.value\n  if (dynverGitDescribeOutput.value.hasNoTags)\n    throw new MessageOnlyException(\n      s\"Failed to derive version from git tags. Maybe run `git fetch --unshallow`? Version: $v\"\n    )\n  s\n}\n```\n\n\n## Dependencies\n\n* `git`, on the `PATH`\n\n## Library Usage\n\nsbt-dynver also publishes a standalone library, `dynver`.\n\n[![dynver Scala version support](https://index.scala-lang.org/sbt/sbt-dynver/dynver/latest-by-scala-version.svg?platform=jvm)](https://index.scala-lang.org/sbt/sbt-dynver/dynver)\n\n```scala\n\"com.github.sbt\" % \"dynver\" % \"x.y.z\")\n```\n\nThe easiest way to use this library is to use the methods that exist on `DynVer`\nto which you can query with questions like:\n\n- The current version\n- The sonatype version\n- If this a snapshot?\n- What the previous version was\n\n```scala\nimport java.util.Date\nimport sbtdynver.DynVer\n\nDynVer.version(Date())\n// res0: String = 0.2.0+0-3d78911a+20230427-1401\nDynVer.isSnapshot()\n// res1: Boolean = true\nDynVer.isDirty()\n// res2: Boolean = true\nDynVer.previousVersion\n// res3: Option[String] = None\n```\n\nYou can get a full idea of what exists on `DynVer` by looking at it\n[here](https://github.com/sbt/sbt-dynver/blob/main/dynver/src/main/scala/sbtdynver/DynVer.scala).\n\n\n## FAQ\n\n### How do I make previousStableVersion return None for major version branches?\n\nDeciding whether going from one version to another is a \"breaking change\" is out of scope for this project.\nIf you have binary compatibility check setup using `previousStableVersion` in CI\nand want to skip the check for major version branches (e.g. `1.x` vs `2.x`), see https://github.com/sbt/sbt-dynver/issues/70#issuecomment-458620722\nfor the recommended solution.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsbt%2Fsbt-dynver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsbt%2Fsbt-dynver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsbt%2Fsbt-dynver/lists"}