conan-recipe-version.yml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. name: Get Conan Recipe Version
  2. on:
  3. workflow_call:
  4. inputs:
  5. project_name:
  6. required: true
  7. type: string
  8. user:
  9. required: false
  10. default: ultimaker
  11. type: string
  12. additional_buildmetadata:
  13. required: false
  14. default: ""
  15. type: string
  16. outputs:
  17. recipe_id_full:
  18. description: "The full Conan recipe id: <name>/<version>@<user>/<channel>"
  19. value: ${{ jobs.get-semver.outputs.recipe_id_full }}
  20. recipe_id_latest:
  21. description: "The full Conan recipe aliased (latest) id: <name>/(latest)@<user>/<channel>"
  22. value: ${{ jobs.get-semver.outputs.recipe_id_latest }}
  23. recipe_semver_full:
  24. description: "The full semver <Major>.<Minor>.<Patch>-<PreReleaseTag>+<BuildMetaData>"
  25. value: ${{ jobs.get-semver.outputs.semver_full }}
  26. is_release_branch:
  27. description: "is current branch a release branch?"
  28. value: ${{ jobs.get-semver.outputs.release_branch }}
  29. user:
  30. description: "The conan user"
  31. value: ${{ jobs.get-semver.outputs.user }}
  32. channel:
  33. description: "The conan channel"
  34. value: ${{ jobs.get-semver.outputs.channel }}
  35. project_name:
  36. description: "The conan projectname"
  37. value: ${{ inputs.project_name }}
  38. jobs:
  39. get-semver:
  40. runs-on: ubuntu-latest
  41. outputs:
  42. recipe_id_full: ${{ steps.get-conan-broadcast-data.outputs.recipe_id_full }}
  43. recipe_id_latest: ${{ steps.get-conan-broadcast-data.outputs.recipe_id_latest }}
  44. semver_full: ${{ steps.get-conan-broadcast-data.outputs.semver_full }}
  45. is_release_branch: ${{ steps.get-conan-broadcast-data.outputs.is_release_branch }}
  46. user: ${{ steps.get-conan-broadcast-data.outputs.user }}
  47. channel: ${{ steps.get-conan-broadcast-data.outputs.channel }}
  48. steps:
  49. - name: Checkout repo
  50. uses: actions/checkout@v3
  51. if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
  52. with:
  53. fetch-depth: 0
  54. ref: ${{ github.head_ref }}
  55. - name: Checkout repo PR
  56. uses: actions/checkout@v3
  57. if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
  58. with:
  59. fetch-depth: 0
  60. ref: ${{ github.base_ref }}
  61. - name: Setup Python and pip
  62. uses: actions/setup-python@v4
  63. with:
  64. python-version: "3.10.x"
  65. cache: 'pip'
  66. cache-dependency-path: .github/workflows/requirements-conan-package.txt
  67. - name: Install Python requirements and Create default Conan profile
  68. run: |
  69. pip install -r .github/workflows/requirements-conan-package.txt
  70. pip install gitpython
  71. - id: get-conan-broadcast-data
  72. name: Get Conan broadcast data
  73. run: |
  74. import subprocess
  75. import os
  76. from conan.tools.scm import Version
  77. from conan.errors import ConanException
  78. from git import Repo
  79. repo = Repo('.')
  80. user = "${{ inputs.user }}".lower()
  81. project_name = "${{ inputs.project_name }}"
  82. event_name = "${{ github.event_name }}"
  83. issue_number = "${{ github.ref }}".split('/')[2]
  84. is_tag = "${{ github.ref_type }}" == "tag"
  85. is_release_branch = False
  86. ref_name = "${{ github.base_ref }}" if event_name == "pull_request" else "${{ github.ref_name }}"
  87. buildmetadata = "" if "${{ inputs.additional_buildmetadata }}" == "" else "${{ inputs.additional_buildmetadata }}_"
  88. # FIXME: for when we push a tag (such as an release)
  89. channel = "testing"
  90. if is_tag:
  91. branch_version = Version(ref_name)
  92. is_release_branch = True
  93. channel = "_"
  94. user = "_"
  95. actual_version = f"{branch_version}"
  96. else:
  97. try:
  98. branch_version = Version(repo.active_branch.name)
  99. except ConanException:
  100. branch_version = Version('0.0.0')
  101. if ref_name == f"{branch_version.major}.{branch_version.minor}":
  102. channel = 'stable'
  103. is_release_branch = True
  104. elif ref_name in ("main", "master"):
  105. channel = 'testing'
  106. else:
  107. channel = "_".join(repo.active_branch.name.replace("-", "_").split("_")[:2]).lower()
  108. if "pull_request" in event_name:
  109. channel = f"pr_{issue_number}"
  110. # %% Get the actual version
  111. latest_branch_version = Version("0.0.0")
  112. latest_branch_tag = None
  113. for tag in repo.git.tag(merged = True).splitlines():
  114. if str(tag).startswith("firmware") or str(tag).startswith("master"):
  115. continue # Quick-fix for the versioning scheme name of the embedded team in fdm_materials(_private) repo
  116. try:
  117. version = Version(tag)
  118. except ConanException:
  119. continue
  120. if version > latest_branch_version and version < Version("10.0.0"):
  121. # FIXME: stupid old Cura tags 13.04 etc. keep popping up
  122. latest_branch_version = version
  123. latest_branch_tag = repo.tag(tag)
  124. if latest_branch_tag:
  125. # %% Get the actual version
  126. no_commits = 0
  127. for commit in repo.iter_commits("HEAD"):
  128. if commit == latest_branch_tag.commit:
  129. break
  130. no_commits += 1
  131. latest_branch_version_prerelease = latest_branch_version.prerelease
  132. if latest_branch_version.prerelease and not "." in latest_branch_version.prerelease:
  133. # The prerealese did not contain a version number, default it to 1
  134. latest_branch_version_prerelease = f"{latest_branch_version.prerelease}.1"
  135. if event_name == "pull_request":
  136. actual_version = f"{latest_branch_version.major}.{latest_branch_version.minor}.{latest_branch_version.patch}-{latest_branch_version_prerelease.lower()}+{buildmetadata}pr_{issue_number}_{no_commits}"
  137. channel_metadata = f"{channel}_{no_commits}"
  138. else:
  139. if channel in ("stable", "_", ""):
  140. channel_metadata = f"{no_commits}"
  141. else:
  142. channel_metadata = f"{channel}_{no_commits}"
  143. if is_release_branch:
  144. if latest_branch_version.prerelease == "" and branch_version > latest_branch_version:
  145. actual_version = f"{branch_version.major}.{branch_version.minor}.0-beta.1+{buildmetadata}{channel_metadata}"
  146. elif latest_branch_version.prerelease == "":
  147. # An actual full release has been created, we are working on patch
  148. bump_up_patch = int(latest_branch_version.patch) + 1
  149. actual_version = f"{latest_branch_version.major}.{latest_branch_version.minor}.{bump_up_patch}-beta.1+{buildmetadata}{channel_metadata}"
  150. else:
  151. # An beta release has been created we are working toward a next beta or full release
  152. bump_up_release_tag = int(latest_branch_version.prerelease.split('.')[1]) + 1
  153. actual_version = f"{latest_branch_version.major}.{latest_branch_version.minor}.{latest_branch_version.patch}-{latest_branch_version.prerelease.split('.')[0]}.{bump_up_release_tag}+{buildmetadata}{channel_metadata}"
  154. else:
  155. max_branches_version = Version("0.0.0")
  156. branches_no_commits = no_commits
  157. for branch in repo.references:
  158. try:
  159. if "remotes/origin" in branch.abspath:
  160. b_version = Version(branch.name.split("/")[-1])
  161. if b_version < Version("10.0.0") and b_version > max_branches_version:
  162. max_branches_version = b_version
  163. branches_no_commits = repo.commit().count() - branch.commit.count()
  164. except:
  165. pass
  166. if max_branches_version > latest_branch_version:
  167. actual_version = f"{max_branches_version.major}.{int(max_branches_version.minor) + 1}.0-alpha+{buildmetadata}{channel}_{branches_no_commits}"
  168. else:
  169. actual_version = f"{latest_branch_version.major}.{int(latest_branch_version.minor) + 1}.0-alpha+{buildmetadata}{channel_metadata}"
  170. # %% Set the environment output
  171. output_env = os.environ["GITHUB_OUTPUT"]
  172. content = ""
  173. if os.path.exists(output_env):
  174. with open(output_env, "r") as f:
  175. content = f.read()
  176. with open(output_env, "w") as f:
  177. f.write(content)
  178. f.writelines(f"name={project_name}\n")
  179. f.writelines(f"version={actual_version}\n")
  180. f.writelines(f"channel={channel}\n")
  181. f.writelines(f"recipe_id_full={project_name}/{actual_version}@{user}/{channel}\n")
  182. f.writelines(f"recipe_id_latest={project_name}/latest@{user}/{channel}\n")
  183. f.writelines(f"semver_full={actual_version}\n")
  184. f.writelines(f"is_release_branch={str(is_release_branch).lower()}\n")
  185. summary_env = os.environ["GITHUB_STEP_SUMMARY"]
  186. with open(summary_env, "w") as f:
  187. f.writelines(f"# {project_name}\n")
  188. f.writelines(f"name={project_name}\n")
  189. f.writelines(f"version={actual_version}\n")
  190. f.writelines(f"channel={channel}\n")
  191. f.writelines(f"recipe_id_full={project_name}/{actual_version}@{user}/{channel}\n")
  192. f.writelines(f"recipe_id_latest={project_name}/latest@{user}/{channel}\n")
  193. f.writelines(f"semver_full={actual_version}\n")
  194. f.writelines(f"is_release_branch={str(is_release_branch).lower()}\n")
  195. shell: python