Showing posts with label github. Show all posts
Showing posts with label github. Show all posts

Sunday, April 14, 2024

GitLab to GitHub Migration Example

In this example, I'll demonstrate one way of migrating a repository from GitLab to GitHub. Sounds simple enough? Kinda? Here are the requirements and a caveat.

  • Preserve as much history as possible (e.g. tags, branches, commits, merges, etc.).
  • The GitLab repo is on premise and is only accessible through the organization VPN.

Now this would have been easy if your GitLab repo can be seen by GitHub. Sadly it can't because your repo is behind a firewall. What do we do now? Well the good thing is both are git repositories. I did these steps on a Windows 11 machine with git for Windows v2.44.

  1. Create a new repo on GitHub. Make sure to name it the same as the one on GitLab.

  2. On git bash, make a "bare" clone of the GL (GitLab) repo in your local machine. This creates a full copy of the data, but without a working directory for editing files, and ensures a clean, fresh export of all the old data.

    
    	# $ git clone --bare https://gitlab-host.com/username/repo.git
    	
    	$ git clone --bare https://gitlab.com/jpllosa/migration-demo.git
    	Cloning into bare repository 'migration-demo.git'...
    	remote: Enumerating objects: 11, done.
    	remote: Counting objects: 100% (11/11), done.
    	remote: Compressing objects: 100% (8/8), done.
    	remote: Total 11 (delta 3), reused 0 (delta 0), pack-reused 0
    	Receiving objects: 100% (11/11), done.
    	Resolving deltas: 100% (3/3), done.
        
    	
  3. Push the locally cloned repository to GH (GitHub) using the "mirror" option. This ensures that all references, such as branches and tags, are copied to the imported repository.

    
    	# $ cd repo.git
    	# $ git push --mirror https://github.com/username/repo.git
    
    	$ cd migration-demo.git/
    	user@hostname MINGW64 /c/temp/migration-demo.git (BARE:main)
    	$ git push --mirror https://github.com/jpllosa/migration-demo.git
    	Enumerating objects: 11, done.
    	Counting objects: 100% (11/11), done.
    	Delta compression using up to 20 threads
    	Compressing objects: 100% (5/5), done.
    	Writing objects: 100% (11/11), 3.57 KiB | 3.57 MiB/s, done.
    	Total 11 (delta 3), reused 11 (delta 3), pack-reused 0 (from 0)
    	remote: Resolving deltas: 100% (3/3), done.
    	To https://github.com/jpllosa/migration-demo.git
    	 * [new branch]      branch-two -> branch-two
    	 * [new branch]      main -> main
    	 * [new tag]         v1.0 -> v1.0
        
    	

    As you can see from above, it looks like everything got copied over. Branches, tags and all that jazz. A thing to note though, if you got various git accounts from different git servers then you might need to change some configuration before you can push. See git config command for more details.

  4. All done. You can now remove the temporary local repo and then use the GH repo from now on.

    
        cd ..
        rm -rf REPO.git
        
    	

GitLab to GitHub Migration

Were the branches preserve? As can bee seen below, it has been.

Were the tags preserve? As can bee seen below, it has been.

Were the commits preserve? As can bee seen below, it has been.

Awesome! That was a successful migration. Great job!

Some Reminders

  • On GH don't forget to configure the default branch settings, add collaborators and teams, etc.
  • If your repo is a Maven project, don't forget to update the scm details.
  • Don't forget to update your CI/CD pipelines. For example update your Jenkins job to pull from the new GH repo.

GitLab to GitHub Migration Closing

Now you know how to migrate your git repo from GL to GH. Everything got preserved as well even when your GL server was behind a firewall.

Sunday, September 17, 2023

GitHub Actions Java with Maven Example

What do you hate the most about pull requests? Is it the formatting changes that clearly add no value and just makes the diff confusing? Or a PR that breaks the build? Don't you just hate a PR that breaks the build? In this example we will automate the code review by checking for a broken build when a pull request is opened. How is this done? By the power of GitHub actions.

GitHub Actions

We'll utilize my old GitHub project, github.com/jpllosa/tdd-junit from Test-Driven Development with Spring Boot Starter Test. Clicking on the Actions tab, GitHub will offer GitHub actions if you haven't created any. If you already have an Action then hit the New workflow button. For our example repo, we should see somthing like below:

GitHub Actions Java with Maven Example
GitHub Actions Java with Maven

Clicking Configure will create a template maven.yml file in .github/workflows folder as shown below. Editing a yml file in GitHub is also a nice way to search for actions. Commit then pull to have a local copy. Let's create a development branch and a feature branch (github-action-java-maven). What we would like to happen is when a pull request into development, it would automatically trigger a build, test and create a review comment if it's a broken build.

GitHub Actions Java with Maven Example
Finding GitHub Actions

$ git pull
From https://github.com/jpllosa/tdd-junit
 * [new branch]      development -> origin/development
 * [new branch]      github-action-java-maven -> origin/github-action-java-maven
Already up to date.

$ git checkout github-action-java-maven

maven.yml

Let's edit the maven.yml template. If you're using Spring Tool Suite and can't find your file, you might have to untick *. resources. Then you should be able to see the yml file.

GitHub Actions Java with Maven Example
Spring Tool Suite Filter
GitHub Actions Java with Maven Example
Spring Tool Suite Java Element Filter
GitHub Actions Java with Maven Example
GitHub Workflow YML file

Your yml file should look like below:


name: Java CI with Maven

on:
  pull_request:
    branches:
      - 'development'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v3.6.0
      - name: Set up JDK
        uses: actions/setup-java@v3.12.0
        with:
          java-version: '8'
          distribution: 'semeru'
          cache: maven
      - name: Build with Maven
        run: mvn -B clean package
      - name: View context attributes
        if: ${{ failure() }}
        uses: actions/github-script@v6.4.1
        with:
          script: |
            console.log(context);
          github-token: ${{ secrets.GITHUB_TOKEN }}
          debug: true
      - name: Create PR Comment
        if: ${{ failure() }}
        uses: actions/github-script@v6.4.1
        with:
          script: |
            github.rest.pulls.createReview({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.payload.pull_request.number,
              event: "COMMENT",
              body: "It is a mortal sin to PR a broken build! :rage:",
              comments: [],
            })
          github-token: ${{ secrets.GITHUB_TOKEN }}
          debug: true

I won't be explaining workflows in too much detail. I'll let the GitHub Docs do that for me. I will however explain this YAML file. Let's start from the top. Our workflow name is Java CI with Maven. This workflow is triggered when a pull request is opened on branch development. Our workflow run is made up of a single job, with a job ID of build. The type of machine that will process our job is the latest version of Ubuntu.

Steps, the place where all the grunt work is done. First is the Checkout. It uses the Checkout GitHub action to checkout our repository. Second it Set up JDK. It uses the Setup Java JDK GitHub action to download and set up Java version 8. Third is Build with Maven which runs the mvn -B clean package command. Fourth is the View context attributes. It uses the GitHub Script GitHub action to help us write scripts in our workflow that uses the GitHub API and the workflow run context. This step is ran when any of the previous steps has failed. The failure() is a status check function. This step is for debugging purposes only, hence the log to the console call. Fifth is the Create PR Comment action. It uses the same GitHub action as the previous one. If the Build with Maven step fails then this will create a review comment saying that it is a mortal sin to create a pull request with a broken build. LOL!

GitHub Actions in Action

Let's add a unit that fails in MathFunTest.java, push it then create a PR. Our source branch is github-action-java-maven and the target development so that the workflow gets triggered.


package com.blogspot.jpllosa;

// snipped...

@SpringBootTest
public class MathFunTest {
	// snipped...
	
	@Test
	public void testThatFails() {
		fail("Not yet implemented");
	}
}

What's the outcome? You should see something like below when creating a pull request with a broken build:

GitHub Actions Java with Maven Example
Pull Request Review Comment

Remove the failing test then push the code and you should have something like below:

GitHub Actions Java with Maven Example
GitHub Actions Success

GitHub Actions Java with Maven Summary

GitHub Actions did all the work for us. From setting up the machine with all the required Java tools. Checking out the repo and then building and running the tests. And finally creating the review comment via the GitHub Script Github action API. There you have it. An automated code review comment for those PRs breaking the build. Hope you had fun reading and applying a similar GitHub action. I know I did.