Skip to content

feat: add ability to detect current project#242

Open
danudey wants to merge 11 commits intosemaphoreci:masterfrom
danudey:get-current-project-feat
Open

feat: add ability to detect current project#242
danudey wants to merge 11 commits intosemaphoreci:masterfrom
danudey:get-current-project-feat

Conversation

@danudey
Copy link
Contributor

@danudey danudey commented Sep 29, 2025

The Semaphore CLI tool has the ability to detect the current project, but there are a few caveats:

  1. It relies on the assumption that origin is the upstream remote; this is not a safe assumption because when creating a fork the gh cli tool will rename the upstream remote to upstream and set the new fork to be origin.
  2. This functionality is never exposed to the user directly

This means that if a user needs the current project ID (e.g. to trigger a pipeline via the API), they must get the list of all remote URLs themselves, get the list of all projects themselves, find a match between the two, and then call sem get project <project name> to get the project's ID.

This PR does a few things (updated from the previous implementation):

First, we add a new function getAllGitRemotesAndProjects(), which does the following:

  1. Gets all the configured git remotes and their URLs via git config
  2. Gets all the configured projects in the current Semaphore context
  3. Produces a list of (remoteName, remoteURL, semaphoreProject) where the project URL matches the remote URL; in other words, every configured remote for which a configured project exists.

Secondly, we also add a small helper function, getGitHubBaseRemoteName(), which checks the repository's git configuration via git config to see if the user has run gh repo set-default to choose a default remote.

Thirdly, we refactor InferProject() to call getAllGitRemotesAndProjects() and then choose one of the results with the following detection logic:

  1. If we only have one result, use that
  2. If the user has used gh repo set-default and that remote is in the list, use that
  3. If the results include an origin repo, use that; if not but there's an upstream repo, use that
  4. If the multiple non-default, non-origin, non-upstream remotes all have the same URL, return the project matching that URL
  5. At this point, we have multiple remotes with non-standard remote names and different URLs, all of which have different projects configured for them; we can't guess a correct project so give up.

The original InferProject() simply chose the origin remote and used that, so this new logic will cover those cases as well, and thus shouldn't cause issues with the rest of the codebase.

Lastly, we add a new sem get current_project (alias sem get cur) which simply prints out the project's metadata:

sem get current_project
04ebc08e-437f-45e0-9abd-b5d1d66bb126 projectname git@github.com:thisorg/project.git

Originally I was planning on highlighting the current project when a user did sem get project without an argument, but that ended up feeling messier than just having a separate command for it which a user could parse.

Edit: Added a --json flag to current_project to format the output as JSON (which includes far more data).

Edit 2: Bumped golang version from 1.20 to 1.21 to get the slices package (should go to 1.25 IMHO but this is a minimal change), and added -buildvcs=false to work around git permissions warnings in docker container when running make build

Edit 3: Completely rewrote almost everything into a vastly simplified and yet more complicated implementation.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants