How to get GitHub repository Default Branch name with GraphQL? - github

Is there a way to use GitHub's GraphQL API to retrieve the default branch name of a repository? I can build a query to get all the branch names, but none of the properties I see reference the default branch name. Some repositories I deal with have 'master' for their default, and others have 'main'.
I am aware I can use the HEAD in some commands to workaround this. Such as "HEAD:README.md" for fetching the README.md file, like in this example query below. This repository's default branch is 'main', and I only know that from manual trial and error.
query {
repository(owner: "newrelic", name: "newrelic-ruby-agent") {
object(expression: "HEAD:README.md") {
... on Blob {
text
}
}
}
}
But when I check the local cloned copy of that repository, the .git/HEAD file points to ref: refs/heads/dev. So it seems I am actually pulling the README.md file from the dev branch, and not the default branch?
So is there a nice way to get the name of the default branch for a GitHub repository using their GraphQL API?

There's a field defaultBranchRef on the repository object:
query {
repository(owner: "newrelic", name: "newrelic-ruby-agent") {
defaultBranchRef {
name
}
}
}

Related

How to get a list of submodules through github API?

I'm trying to get a list of submodules of a repository through GitHub API. After reading Github API docs, I did the following things: In Order to access the submodules of the Jquery, I use the following link to get a list of submodules, however, I cannot see any submodules from it. Could anyone please tell me what field should I use to get a list of submodules of a repository from GitHub API?
You can get the list of git submodules using Github GraphQL API v4 with the submodules connection property :
{
repository(owner: "bertrandmartel", name: "javacard-tutorial") {
submodules(first: 100) {
nodes {
name
path
}
}
}
}
Try this in the explorer
Output :
{
"data": {
"repository": {
"submodules": {
"nodes": [
{
"name": "oracle_javacard_sdks",
"path": "oracle_javacard_sdks"
}
]
}
}
}
}
Note that this will give only submodules on default branch's HEAD, from the documentation :
Returns a list of all submodules in this repository parsed from the .gitmodules file as of the default branch's HEAD commit.
Note that the jquery repository doesn't have any git submodules in its default branch's HEAD (and I don't see any in its other branches)
If you use v3 REST API you can
Get the HEAD commit SHA of the branch.
Use the returned commit SHA as the tree_sha to get tree. GET /repos/{owner}/{repo}/git/trees/{tree_sha}
Iterate the returned tree object for entry that has mode 160000 (submodule)

Fail a merge or build if a particular file has changed?

On VSTS, we have some files we want to protect on certain branches. How can one fail a merge/build if a particular file has changed?
First prize is to configure this on the build server, which in this case is VisualStudio.com (VSTS / GIT).
Scenario: we have various release branches v1, v2, v3. We want to protect the packages.json file to prevent anyone updating Nuget packages on these branches. So if the package.json file has changed on a pull request into "v3", don't allow the merge.
For Git, you can protect a certain branch (not a certain file), then all the files exist in the branch will be protected.
You can use Branch security which users/groups can contribute for the branch.
Or you can use Branch Policies to protect not commit changes on the branch directly but use pull request to make changes etc.
Or you can lock a branch to prevent updating.
To expanded Starain's answer:
First create a build definition for the branch you want to protected (such as select V3 branch in get sources step). And add a powershell task with the content below:
$head=$(git rev-parse HEAD)
$parents=$(git rev-list --parents -n 1 $head)
$p1,$p2,$p3=$parents.split(' ')
If ($p1 = $head)
{
$parent1=$p2
$parent2=$p3
}
ElseIf ($p2 = $head)
{
$parent1=$p1
$parent2=$p3
}
Else
{
$parent1=$p1
$parent2=$p2
}
$outp1=$(git diff $head $parent1 --name-only)
$outp2=$(git diff $head $parent2 --name-only)
If ($outp1 -contains 'package.json')
{
echo "changed the specified file on the branch which contains commit $parent1"
exit 1
}
If ($outp2 -contains 'package.json')
{
echo "changed the specified file on the branch which contains commit $parent2"
exit 1
}
So that when the file package.json has been change, powershell script will fail the build result.
Then add the branch policy for the branch which you want to protect.
Add build policy -> select the build definition you just created -> Policy requirement as Required -> Build expiration 0.1 hours (6 min) or other values since it’s every fast to queue a build with a powershell task -> save.
You can try to do it in the build, simple workflow:
Configure branch policy for a succeed build required
Check whether the specific file changed in that build
Fail build if specific file has been changed
You can put a required reviewer for a particular folder/file in VSTS for a particular branch.
In this way the person won't be able to check-in without getting an approval from the required reviewer.
Git doesn't really work that way; individual files don't have any sort of security on them.
You could use a pre-commit hook, but it's important to note that those hooks are client-side, not server-side -- each user would have to set up a pre-commit hook.
VSTS/TFS doesn't support Git server hooks (at least, not to the extent that it can block a push), otherwise a pre-receive or update hook would be exactly what you want.

How can we check in Jenkins home directory to Github?

We want to check in the Jenkins home directory into Github, certainly ignoring some files/folders. As we want to have everything defined by code, we try to achieve this using Job DSL & Pipeline DSL (not writing the pipeline script inside Jenkins GUI but having it read from a workspace file - see below).
My problem right now is that, being not very proficient in both DSL's yet, I don't know how to force git to do an initial clone of the remote repo (and later push) inside the home directory - which is a parent directory of the job's directory.
I tried this pipeline:
node('master') {
dir('../..') {
scm {
git {
remote {
github('company/repo', 'https')
credentials('xyz')
}
}
}
}
}
The job itself is defined like this:
pipelineJob('backup') {
definition {
cps {
script(readFileFromWorkspace('pipelines/backup.groovy'))
sandbox(true)
}
}
}
The job fails with this error message:
ERROR: ‘checkout scm’ is only available when using “Multibranch Pipeline” or “Pipeline script from SCM”
So I guess the above used 'pipelineJob(backup)' does not fit. Should I change this, and if, how, or should I take another approach?
Another shot at this was trying to rewrite the pipeline like this:
node {
dir('../..') {
git url: 'https://github.com/company/repo.git'
}
}
But then it won't work because credentials are missing...

How to search content on specific branch using Github API

I'm using the Github Kohsuke API to search for content on a remote repo on Github. Currently, I'm only able to pull down content from my default master branch. Is there a way to pull down content on a branch besides master? Here's the code snippet I have, which currently only pulls from my master branch. Thanks for any help!
public class GitCompareTest {
public static void main(String[] args) throws IOException {
GitHub github = GitHub.connect();
GHRepository repo = github.getRepository(repo_name);
List<GHContent> articleContents = repo.getDirectoryContent(path);
for (GHContent content : articleContents) {
if (content.isDirectory()) {
PagedIterable<GHContent> childArticleContents = content.listDirectoryContent();
for (GHContent childArticleContent : childArticleContents) {
String childText = childArticleContent.getContent();
String.out.println(childText);
}
}
}
}
}
Try getDirectoryContent(String path, String ref) using your branch's name for ref.
A branch name is essentially a name for a specific commit in git, and "ref" is git terminology for "name of a specific commit".
(Disclaimer: I haven't used Kohsuke's GitHub library yet, I'm drawing from general git knowledge.)

Orphan branch in libgit2sharp

How do you create an orphan branch in libgit2sharp?
All i could find are methods which create a branch which points to a commit.
I'm looking for an effect similar to the command:
git checkout --orphan BRANCH_NAME
git checkout --orphan BRANCH_NAME actually moves the HEAD to an unborn branch BRANCH_NAME without altering the working directory nor the index.
You can perform a similar operation with LibGit2Sharp by updating the target of the HEAD reference with repo.Refs.UpdateTarget() method.
The following test demonstrates this
[Fact]
public void CanCreateAnUnbornBranch()
{
string path = CloneStandardTestRepo();
using (var repo = new Repository(path))
{
// No branch named orphan
Assert.Null(repo.Branches["orphan"]);
// HEAD doesn't point to an unborn branch
Assert.False(repo.Info.IsHeadUnborn);
// Let's move the HEAD to this branch to be created
repo.Refs.UpdateTarget("HEAD", "refs/heads/orphan");
Assert.True(repo.Info.IsHeadUnborn);
// The branch still doesn't exist
Assert.Null(repo.Branches["orphan"]);
// Create a commit against HEAD
var signature = new Signature("Me", "me#there.com", DateTimeOffset.Now);
Commit c = repo.Commit("New initial root commit", signature, signature);
// Ensure this commit has no parent
Assert.Equal(0, c.Parents.Count());
// The branch now exists...
Branch orphan = repo.Branches["orphan"];
Assert.NotNull(orphan);
// ...and points to that newly created commit
Assert.Equal(c, orphan.Tip);
}
}