Saturday, 22 October 2022

How to Install & run Stable Diffusion AI image generator with a Web UI on Windows PC

Stable Diffusion is among the best AI art generators right now. In this post, I outline the steps to install its local copy with a Web UI on a Windows PC.

How to Install

1)  install prerequisite software:

2) install Stable Diffusion web UI by AUTOMATIC1111:

git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git

3) install the models:

  • the Stable Diffusion model checkpoint, a file with .ckpt extension, needs to be downloaded from this repo (v1.4 or v1.5, free Hugging Face login account required) and placed in the models/Stable-diffusion directory
  • (Optional) GFPGANv1.4.pth and/or GFPGANv1.3.pth, needed to be downloaded from this repo and placed in the base directory, alongside webui.py

How to Run

1) run webui-user.bat from Windows Explorer as normal, non-administrator, user:

  • first run may take long time since web app need download and install all dependencies automatically
  • if first run seem to be frozen, press space key to resume its execution

2) when Running on local URL: http://127.0.0.1:7860 appears in the command prompt window, the stable diffusion local instance is running.

  • It can be accessed with browsing the localhost link from the current PC
  • to stop the web app, either of the following methods:
    • close the command prompt window of webui-user.bat
    • press ctrl+c in the command prompt window of webui-user.bat

Some useful Tips

vram setting

Makes the Stable Diffusion model consume less VRAM so that it can run on low end computer, add the follow arguments in webui-user.bat (add to the end of the line as "set COMMANDLINE_ARGS="):

  • --medvram for the PC with less than 4GB vram GPU
  • --lowvram for the PC with less than 2GB vram GPU


Tuesday, 26 May 2020

How to use Git & GitHub for Unity projects

In this tutorial, I will outline how to use Git/GitHub to provide source/version control service for Unity projects.

Challenges & Solution

There are 2 main challenges to using Git & GitHub for Unity projects:
  1. Unity projects create lots of temporary & internal-used files, which should be excluded from the source control system. The ".gitignore" mechanism of Git could be configured to solve this in the prefect way, i.e., exclude unwanted files from Git;
  2. Unity project contains lots of binary format files, esp. large binary files, which are difficult to be tracked by the source control systems. To solve this challenge, 2 following methods should be deployed side by side:
    • Configure Unity project to use text format instead of binary format if possible
    • Use Git LFS(Git Large File Storage) service to track these large binary files such as images, audios, 3d models and etc

How-to guide

1. Prepare

  • install & config Git
  • setup GitHub account
  • install Git LFS (Git LFS has been included in Git for Windows)
  • your Unity project waiting for version control

2. Config Unity Project

You may check the following settings of the Unity project - "Edit > Project Settings > Editor":
  • "Version Control > Mode" should be "Visible Meta Files"
  • "Asset Serialization > Mode" should be "Force Text"
In general, I found the default settings of Unity 2018 or later should be correct for version control.

3. Config Git for Unity Project

You create the file ".gitignore" as follows and put it at the root directory of the Unity project:

# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
#
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/

# MemoryCaptures can get excessive in size.
# They also could contain extremely sensitive data
/[Mm]emoryCaptures/

# Asset meta data should only be ignored when the corresponding asset is also ignored
!/[Aa]ssets/**/*.meta

# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*

# Autogenerated Jetbrains Rider plugin
/[Aa]ssets/Plugins/Editor/JetBrains*

# Visual Studio cache directory
.vs/

# Gradle cache directory
.gradle/

# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db

# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
*.mdb.meta

# Unity3D generated file on crash reports
sysinfo.txt

# Builds
*.apk
#*.unitypackage

# Crashlytics generated file
crashlytics-build.properties

# Packed Addressables
/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*

# Temporary auto-generated Android Assets
/[Aa]ssets/[Ss]treamingAssets/aa.meta
/[Aa]ssets/[Ss]treamingAssets/aa/*


# Ignore some common files for Windows
#
# Get latest from https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
#
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db

# Dump file
*.stackdump

# Folder config file
[Dd]esktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Windows shortcuts
*.lnk

Note - this sample ".gitignore" file contains:
  • common files for Unity projects should be ignored
  • common files for Windows should be ignored

4. Config Git LFS for Unity Project

4.1 Activate Git LFS
You need to activate Git LFS as follows, only need run this once per user account:

$ git lfs install
verify that the installation was successful:

> Git LFS initialized.

4.2 ".gitattributes"
You create the file ".gitattributes" as follows and put it at the root directory of the Unity project:

# Git LFS tracking file list:
# 3D models
*.3dm filter=lfs diff=lfs merge=lfs -text
*.3ds filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.c4d filter=lfs diff=lfs merge=lfs -text
*.collada filter=lfs diff=lfs merge=lfs -text
*.dae filter=lfs diff=lfs merge=lfs -text
*.dxf filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.jas filter=lfs diff=lfs merge=lfs -text
*.lws filter=lfs diff=lfs merge=lfs -text
*.lxo filter=lfs diff=lfs merge=lfs -text
*.ma filter=lfs diff=lfs merge=lfs -text
*.max filter=lfs diff=lfs merge=lfs -text
*.mb filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text
*.ply filter=lfs diff=lfs merge=lfs -text
*.skp filter=lfs diff=lfs merge=lfs -text
*.stl filter=lfs diff=lfs merge=lfs -text
*.ztl filter=lfs diff=lfs merge=lfs -text
# Audio
*.aif filter=lfs diff=lfs merge=lfs -text
*.aiff filter=lfs diff=lfs merge=lfs -text
*.it filter=lfs diff=lfs merge=lfs -text
*.mod filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text
*.s3m filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.xm filter=lfs diff=lfs merge=lfs -text
# Fonts
*.otf filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
# Images
*.bmp filter=lfs diff=lfs merge=lfs -text
*.exr filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.hdr filter=lfs diff=lfs merge=lfs -text
*.iff filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.pict filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.tiff filter=lfs diff=lfs merge=lfs -text
# Unity packages
*.unitypackage filter=lfs diff=lfs merge=lfs -text

# Collapse Unity-generated files on GitHub
*.asset linguist-generated
*.mat linguist-generated
*.meta linguist-generated
*.prefab linguist-generated
*.unity linguist-generated

Note - this sample ".gitattributes" file contains:
  • Git LFS tracking file types that Unity currently supports
  • automatically collapsing the diffs on GitHub for Unity-generated files
  • see more details

Alternatively, you may configure additional file types at anytime, such as:

$ git lfs track "*.jpg"

4.3 Verify Git LFS
You may verify which files are being tracked as Git LFS files:

$ git lfs ls-files

5. Initial Commit

After all of Unity project, Git and Git LFS are configured, you can startup Git version control with Unity project as usual.

Just run the following Git commands under the root directory of Unity project:

$ git init
$ git add .
$ git commit -m 'Initial commit'
$ git log

Note:
  • start a Git repo
  • add all source files into staging area(index)
  • make initial commit
  • show commit log

6. Upload to GitHub

  1. login in your GitHub account
  2. create a new repository for Unity project - "Click the top-right-corner plus-sign button > New repository"
  3. copy the new repo url - "repository page > click Clone or download button > click copy button"
  4. run the following commands to upload Unity project to GitHub repo at the first time:
  5. $ git remote add origin <repo_url>
    $ git remote -v
    $ git push -u origin master
    $ git log
    
    
    Note:
    • config remote for the new repo
    • show remote repositories
    • upload Unity source files to remote repo
    • show commit log
  6. run the following command to update Unity project's GitHub repo later on:
  7. $ git push

7. Well done, finished!


References

Wednesday, 1 January 2020

How to Configure Visual Studio Code for C++ Development

In this tutorial, I provide the configuration details to setup a simple, modern C++ development environment:
  • Visual Studio Code as editor
  • Microsoft C++ compiler (msvc)
  • C++17
  • UTF-encoding source code
  • MS Windows 10 OS

Configure Steps

1. Install Tool-sets

  1. Install Visual Studio Code (version 1.41.1)
  2. Install C++ extension for VS Code (version 0.26.3)
  3. Install Microsoft C++ compiler tool-set, i.e., install either of the following tools:

2. Config C++ Project

  1. create an empty folder, for example, called "project", this is used to store all files for a VS Code project
  2. create an sub-folder called "debug" under "project" folder, this is used to store compiler producing files
  3. create an sub-folder called ".vscode" under "project" folder, this is used to store VS Code config files
  4. create 3 configure files of VS Code under "project/.vscode" folder:
    • c_cpp_properties.json
    • {
          "configurations": [
              {
                  "name": "Win32",
                  "includePath": [
                      "${workspaceFolder}/**"
                  ],
                  "defines": [
                      "_DEBUG",
                      "UNICODE",
                      "_UNICODE"
                  ],
                  "windowsSdkVersion": "10.0.18362.0",
                  "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.23.28105/bin/Hostx64/x64/cl.exe",
                  "cStandard": "c11",
                  "cppStandard": "c++17",
                  "intelliSenseMode": "${default}"
              }
          ],
          "version": 4
      }
      
      Note:
      • this configure file is for configuring compiler path and IntelliSense settings
      • the value of "compilerPath" may be adjusted based on your installation options for MS C++ compiler tool-set accordingly
      • the value of "cppStandard" is C++17, this configures VS Code source code editor accordingly
    • launch.json
    • {
        "version": "0.2.0",
        "configurations": [
          {
            "name": "(msvc) Launch",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceFolder}/debug/app.exe",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}/debug",
            "environment": [],
            "externalConsole": false
          }
        ]
      }
      
      Note:
      • this configure file is for configuring MS C++ debugger
      • the executable file is configured as "app.exe", this may be adjusted based on your project needs accordingly
    • tasks.json
    • {
        "version": "2.0.0",
        "tasks": [
          {
            "label": "msvc build",
            "type": "shell",
            "command": "cl.exe",
            "args": ["/EHsc", "/Zi", "/std:c++17", "/utf-8", "/Fe:", "app.exe", "../*.cpp"],
            "options": {
              "cwd": "${workspaceRoot}/debug"
            },
            "group": {
              "kind": "build",
              "isDefault": true
            },
            "presentation": {
              "reveal": "always",
              "focus": true
            },
            "problemMatcher": "$msCompile"
          },
          {
            "label": "clean build",
            "type": "shell",
            "command": "del",
            "args": ["/Q", "*"],
            "options": {
              "cwd": "${workspaceRoot}/debug"
            },
            "group": "build",
            "presentation": {
              "reveal": "always",
              "focus": true
            },
            "problemMatcher": "$msCompile"
          },
          {
            "label": "run build",
            "type": "shell",
            "command": "app.exe",
            "options": {
              "cwd": "${workspaceRoot}/debug"
            },
            "dependsOn": [
              "msvc build"
            ],
            "group": {
              "kind": "test",
              "isDefault": true
            },
            "presentation": {
              "reveal": "always"
            }
          }
        ]
      }
      
      Note:
      • this configure file is for configuring build instructions, including build/clean/run tasks
      • the executable file is configured as "app.exe", this may be adjusted based on your project needs accordingly
      • quick explanation for the compile arguments of "msvc build" task:
        • /EHsc - specify the exception handling mode
        • /Zi - produce a debug build with symbols
        • /std:c++17 - enable C++17 standard-specific features and behavior explicitly, preferable than /std:c++latest due to long-term maintenance
        • /utf-8 - set source and execution character sets to UTF-8
        • /Fe: - specify the executable file name

Work with C++ Project

  1. start "Developer Command Prompt for VS 2019", this is required for msvc
  2. from the developer command prompt, navigate into the folder "project", and start VS Code under the folder "project"
  3. > cd project
    > code .
    
  4. create a C++ source code under the folder "project" with VS Code, for example, let's create the following sample C++ source code "helloworld.cpp"
  5. #include <iostream>
    
    using namespace std;
    
    int main() {
     cout << "Hello, world!" << endl;
    
     return 0;
    }
    
  6. compile C++ code by either one of the following methods:
    • press the shortcut key: ctrl + shift + b
    • run tasks: msvc build
    Note:
    • The executable file "app.exe" will be generated by msvc under the subfolder "debug" if everything works properly
    • different methods to run task in VS Code:
      • press the shortcut key: F1 to access the command palette of VS Code, and then choose the desired task to run
      • press the shortcut key: ctrl + shift + p to access the command palette of VS Code, and then choose the desired task to run
      • through the menu of VS Code: terminal > run task, and then choose the desired task to run
  7. compile C++ code and then run the executable file with a single task:
    • run tasks: run build
  8. start debugging:
    • press the shortcut key: F5 to access the debugger GUI of VS Code
  9. clean up all of last build generated files:
    • run tasks: clean build

References

Saturday, 6 October 2018

How to Publish Your Open Source Library to Maven Central Repository

Apache Maven Logo

Apache Maven is a software project management and comprehension tool. It helps the developers to manage java projects in a controlled manner. For the open source developers, maven central repository provides the free hosting service for sharing their open source libraries to the global users.

This step-by-step guide shows the whole process of publishing an open source project to maven central repository with the helps of Maven, Git, GitHub, GPG and OSSRH:
  • Maven, used for project management and build automation
  • Git, used for source code version control
  • GitHub, used for source code repository
  • GPG, used to sign the built artifact
  • OSSRH, used as artifact repository

The Publish Process

1. Prerequisite Steps

In this step, we need to configure and prepare various of tools and services required by the project publishing process.

2. Maven Configuration Steps

In this step, we need to configure Maven so that the publishing process can be automatically performed with the Maven commands. It would be a simple task to release a new version later on, and can even be delegated to a CD (Continue Deployment) system.
  • Step 2.1 - configure pom.xml (see my sample pom file)
    • locate it under project root directory
    • add the project information 
      • compulsory information required by OSSRH:
        • correct coordinates
        • project name, description and url
        • license information
        • developer information
        • SCM Information - connection details the read only connection, while developerConnection details read and write access connection details. The url contains the URL for a web front end to your SCM system
      • optional information if possible:
        • organization information
        • issue tracking information (detailed by issueManagement)
        • continuous integration system information (detailed by ciManagement)
      • sample code segment:
      • <project ...>
          ...
          
          <name>archetype-modern-starter</name>
          <description>a modern Java standalone application template</description>
          <url>https://github.com/coder168/archetype-modern-starter</url>
        
          <licenses>
            <license>
              <name>The Apache Software License, Version 2.0</name>
              <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
            </license>
          </licenses>
        
          <organization>
            <name>Coder168</name>
            <url>https://github.com/coder168</url>
          </organization>
        
          <developers>
            <developer>
              <name>Ming Li</name>
              <email>coder168@users.noreply.github.com</email>
              <organization>Coder168</organization>
              <organizationUrl>https://github.com/coder168</organizationUrl>
            </developer>
          </developers>
        
          <scm>
            <connection>scm:git:git://github.com/coder168/archetype-modern-starter.git</connection>
            <developerConnection>scm:git:ssh://github.com:coder168/archetype-modern-starter.git</developerConnection>
            <url>https://github.com/coder168/archetype-modern-starter</url>
            <tag>HEAD</tag>
          </scm>
        
          <issueManagement>
            <system>Github</system>
            <url>https://github.com/coder168/archetype-modern-starter/issues</url>
          </issueManagement>
        
          <ciManagement>
            <system>Travis</system>
            <url>https://travis-ci.org/coder168/archetype-modern-starter</url>
          </ciManagement>
        
          ...
        </project>
        
    • add the plugin section for publishing to OSSRH
      • defined within a dedicated profile (ossrh-release) for clarity purpose
      • distributionManagement specifies the details of OSSRH repositories
      • properties specifies the plugins version details, easy for upgrade later on
      • maven-source-plugin creates a source jar for OSSRH requirement
      • maven-javadoc-plugin creates a javadoc jar for OSSRH requirement
      • maven-jar-plugin creates a fake javadoc jar contain README.md for OSSRH requirement. This is a workaround when maven javadoc plugin fails to generate javadoc jar, such as maven archetype project can not generate java doc. This one is not needed if maven javadoc plugin works properly
      • maven-gpg-plugin sign the artifacts for OSSRH requirement
      • nexus-staging-maven-plugin provides support to access staging functionality to remote Nexus server OSSRH. Note: in the following sample, the plugin is configured to immediately perform a release of staging repository (or repositories) after a successful close
      • maven-release-plugin provides support to create a release and to update the project's SCM accordingly. Note: in the following sample, git is configured to make local checkout and will not push changes to remote repository automatically during release deployment
      • sample code segment:
      • <project ...>
          ...
        
          <profiles>
            <profile>
              <id>ossrh-release</id>
                  
              <distributionManagement>
                <snapshotRepository>
                  <id>ossrh</id>
                  <url>https://oss.sonatype.org/content/repositories/snapshots</url>
                </snapshotRepository>
                <repository>
                  <id>ossrh</id>
                  <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
                </repository>
              </distributionManagement>
                  
              <properties>
                <source-plugin.version>3.0.1</source-plugin.version>
                <javadoc-plugin.version>3.0.1</javadoc-plugin.version>
                <jar-plugin.version>3.1.0</jar-plugin.version>
                <gpg-plugin.version>1.6</gpg-plugin.version>
                <nexus-staging-maven-plugin.version>1.6.8</nexus-staging-maven-plugin.version>
                <release-plugin.version>2.5.3</release-plugin.version>
              </properties>
                  
              <build>
                <plugins>
                  <!-- create a source jar for OSSRH requirement. -->
                  <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>${source-plugin.version}</version>
                    <!-- stop to add two maven files: pom.xml & pom.properties. 
                    <configuration>
                      <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                      </archive>
                    </configuration>
                    -->
                    <executions>
                      <execution>
                        <id>attach-sources</id>
                        <goals>
                          <goal>jar-no-fork</goal>
                        </goals>
                      </execution>
                    </executions>
                  </plugin>
                  <!-- create a javadoc jar for OSSRH requirement. -->
                  <!-- javadoc plugin does not work with maven archetype project. 
                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-javadoc-plugin</artifactId>
                      <version>${javadoc-plugin.version}</version>
                      <configuration>
                        <encoding>UTF-8</encoding>
                        <archive>
                          <addMavenDescriptor>false</addMavenDescriptor>
                        </archive>
                      </configuration>
                      <executions>
                          <execution>
                              <id>attach-javadocs</id>
                              <goals>
                                  <goal>jar</goal>
                              </goals>
                          </execution>
                      </executions>
                  </plugin>
                  -->
                  <!-- create a fake javadoc jar contain README.md for OSSRH requirement. -->
                  <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>${jar-plugin.version}</version>
                    <executions>
                      <execution>
                        <id>fake-javadoc-jar</id>
                        <phase>package</phase>
                        <goals>
                          <goal>jar</goal>
                        </goals>
                        <configuration>
                          <classifier>javadoc</classifier>
                          <classesDirectory>${basedir}</classesDirectory>
                          <includes>
                            <include>README.md</include>
                          </includes>
                          <archive>
                            <addMavenDescriptor>false</addMavenDescriptor>
                          </archive>
                        </configuration>
                      </execution>
                    </executions>
                  </plugin>
                  <!-- sign the components for OSSRH requirement. -->
                  <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-gpg-plugin</artifactId>
                    <version>${gpg-plugin.version}</version>
                    <executions>
                      <execution>
                        <id>sign-artifacts</id>
                        <phase>verify</phase>
                        <goals>
                          <goal>sign</goal>
                        </goals>
                      </execution>
                    </executions>
                  </plugin>
                  <!-- provide support to access staging functionality to remote Nexus server OSSRH. -->
                  <plugin>
                    <groupId>org.sonatype.plugins</groupId>
                    <artifactId>nexus-staging-maven-plugin</artifactId>
                    <version>${nexus-staging-maven-plugin.version}</version>
                    <extensions>true</extensions>
                    <configuration>
                      <serverId>ossrh</serverId>
                      <nexusUrl>https://oss.sonatype.org/</nexusUrl>
                      <autoReleaseAfterClose>true</autoReleaseAfterClose>
                    </configuration>
                  </plugin>
                  <!-- provide support to release deployment in two steps: prepare and perform. -->
                  <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-release-plugin</artifactId>
                    <version>${release-plugin.version}</version>
                    <configuration>
                      <autoVersionSubmodules>true</autoVersionSubmodules>
                      <useReleaseProfile>false</useReleaseProfile>
                      <!-- <releaseProfiles>ossrh-release</releaseProfiles>-->
                      <goals>deploy</goals>
                      <!-- git use a local checkout instead of checkout from the upstream repo -->
                      <localCheckout>true</localCheckout>
                      <!-- git will not push changes to the upstream repo -->
                      <pushChanges>false</pushChanges>
                    </configuration>
                  </plugin>
                </plugins>
              </build>
            </profile>
          </profiles>
        
          ...
        </project>
        
  • Step 2.2 - configure settings.xml
    • locate it at ${user.home}/.m2/settings.xml, create it over there if unavailable
    • configure the username and password for accessing OSSRH using Sonatype Jira account's credential
    • (Optional step) configure the passphrase for GPG key pair. Alternative, the passphrase will be prompted for during the verify phrase of maven life cycle if it is not provided by settings.xml
    • sample code of settings.xml:
    • <settings>
        <servers>
          <!-- OSSRH credential -->
          <server>
            <id>ossrh</id>
            <username>sonatype jira username</username>
            <password>sonatype jira password</password>
          </server>
          <!-- GPG passphrase -->
          <server>
            <id>gpg.passphrase</id>
            <passphrase>clear or encrypted text</passphrase>
          </server>
        </servers>
      </settings>
      

3. Publishing Steps

In this step, we release our project and publish the released artifact to OSSRH staging server.
  • Step 3.1 - prepare the release (see the official manual)
    • under maven project root directory:
    • $ mvn clean
      $ mvn release:prepare -P ossrh-release
    • at this stage, what release:prepare goal do:
      • verify that there are no uncommitted changes in the workspace
      • prompt the user for the desired tag, release and development version names
      • modify and commit release information into the pom.xml file
      • tag the entire project source tree with the new tag name
    • if the prepare stage has done successfully, there is a file called release.properties to be created within the project root directory
    • if an error occurs, or the process is cancelled, then you can do either one of the follows:
      • run this command again, it will pick up from where the last one left off:
      • $ mvn release:prepare -P ossrh-release
      • start again from scratch:
      • $ mvn release:clean release:prepare -P ossrh-release
    • (Optional step) Dry Run - since the release prepare step performs a number of operations that change the project, it may be wise to do a dry run before a big release or on a new project:
      • to do this, commit all of your files as if you were about to run a full release and run the following command, which will ask all the same questions, run the same tests, and output a copy of how the POMs will look after transformation. You can check the output and review the POMs
      • $ mvn release:prepare -P ossrh-release -DdryRun=true
      • after review the POMs, then you will remove all of the files created above, and the project will be ready to execute the proper release:
      • $ mvn release:clean -P ossrh-release
  • Step 3.2 - perform the release (see the official manual)
    • this step is where publishing to maven central repository really happened!
    • under maven project root directory:
    • $ mvn release:perform -P ossrh-release
    • in this stage, what release:perform goal do:
      • extract file revisions versioned under the new tag name
      • execute the maven build life-cycle on the extracted instance of the project
      • deploy the versioned artifacts to appropriate local and remote repositories
    • according to our POM settings, the released artifacts are deployed to OSSRH staging server and perform a release of staging repository (or repositories) after a successful close, in other word, the released artifacts will sync to maven central repository automatically in a few hours
    • if an error occurs, or the process failed, figure out what cause the failure and fix the issues, and then run this command again if the file release.properties is still present from a previous release preparation:
    • $ mvn release:perform -P ossrh-release
    • after the release is done successfully, the release.properties and other release files will be removed from the checkout

4. Checking & Troubleshooting Steps

In this step, we verify the published artifacts and finish up the whole process.
  • Step 4.1 - verify the published artifacts
    • search Sonatype OSSRH staging repository for your released artifacts. It should be available immediately after an successful release of Step 3.2
    • search Maven Central Repository for your released artifacts. It may take up to 2 hours to show up your artifacts
    • if what your open source project provided is a library, a sample application can be created to use your released artifacts as a dependency. My open source archetype archetype-modern-starter can easily create a modern maven java application for testing your library:
      • create a sample maven project with archetype-modern-starter (see my quick guide):
      • mvn archetype:generate -Dfilter=archetype-modern-starter
      • add your library as a dependency into its pom.xml under the root directory of the created project
      • delete the local copy of your library artifacts from your local repository at ${user.home}/.m2/repository/, since Step 3.2 did deploy to both local and remote repositories
      • build and package the sample project to see if your library can be used without any issue under the real scenario, under its root directory:
      • $ mvn clean package
    • if what your open source project provided is a maven archetype, you also need to check if maven central repository's archetype catalog has been updated with your new released archetype, otherwise your archetype can not be found by archetype:generate goal
      • the archetype catalog of maven central repository is rebuilt once per week (Sunday night IIRC). You may search your archetype artifact directly with the remote catalog url
      • to check if your archetype released can be found by archetype:generate goal or not:
      • mvn archetype:generate -DarchetypeCatalog=remote -Dfilter=<your archetype artifactId>
  • Step 4.2 - (Optional step) troubleshooting if something are wrong:
    • roll back the local source changes made during the release if needed (by Git):
      • undo the release (you may have to do it a second time, depending upon when the error occurred):
      • git reset --hard HEAD~1
      • delete the tag of release:
      • git tag -d <tag name>
    • ask for Sonatype support by creating the Jira issue ticket with your Jira account:
  • Step 4.3 - finish the whole publishing process if everything is fine:
    • update your Sonatype Jira ticket to inform your release has been done
    • push the local source changes (tags & commits) made during the release to remote source repository, i.e., GitHub:
    • git push --tags
      git push origin master
At this point, your open source project has been published to Maven Central Repository successfully. Next, you may consider to promote your great releases to the whole world, e.g., post it to your favorite social networks and etc.

References

Tools

Guides

Friday, 5 October 2018

Archetype-modern-starter Quick Guide


In this quick guide, I will introduce an open source tool called archetype-modern-starter. I created this tool for helping the developers to quick start the projects of modern java standalone application.

What is archetype-modern-starter?

Archetype-modern-starter is a maven archetype, which is able to easily generate a modern java project. The generated project can be used as the start point for further java application development following the best practices.

Archetype-modern-starter is under Apache License 2.0. Its source code is available on GitHub. Its artifacts has been deployed to Maven Central Repository.

Why use archetype-modern-starter?

The project generated by archetype-modern-starter does:
  • use the following modern technologies:
    • java se 8
    • apache maven 3.5.x
    • log4j 2.11.1
    • junit 4.12
  • follow the current best practices:
    • project management including dependency management supported by maven 3.x
    • unit test supported by junit 4.x
    • logging supported by log4j 2.x
    • maven resource support including the resource directories are ready
    • able to build the executable package and all-in-one package

How to use archetype-modern-starter?

Generate a modern java project

Under the command line, type the following command:
    $ mvn archetype:generate -Dfilter=archetype-modern-starter
Alternative command:
    $ mvn archetype:generate -Dfilter=io.github.coder168:

and then follows the given instructions to provide the project information, includes groupId, artifactId, version, package. The archetype will generate a corresponding java maven project under a new sub-directory of your current working directory.

Work with the generated project

Under the generated project root directory:
  • pom.xml is an XML file that contains information about the project and configuration details used by Maven to build the project. You can add or update the dependencies here
  • README.md is a manual in Markdown format
  • source code files put into the sub directory src/main/java/
  • main resource files put into the sub directory src/main/resources/
  • testing code files put into the sub directory src/test/java/
  • test resource files put into the sub directory src/test/resources/
  • to run all of unit tests:
  • $ mvn test
  • to run single unit test with specified unit test class full name, or multiple names/patterns(using wildcard):
  • $ mvn -Dtest=<test class full name, names/patterns> test
  • to do a clean compile and then run your application:
  • $ mvn clean compile exec:java -Dexec.mainClass=<main class full name>
  • to do a clean build:
  • $ mvn clean package
  • there will be two packages to be built: an executable standard jar file & the all-in-one executable file with dependencies. If all-in-one package is not needed, just delete or comment out the plugin section of maven-assembly-plugin within pom.xml
  • to execute the build:
  • $ java -jar target/<project-build-name>.jar
  • to clean up:
  • $ mvn clean

Note: under different environment, the formatting of the arguments could be little different in a tricky way, e.g. under MS Windows 10:

  • using "Command Prompt" from the system, to do a clean compile run:
  • $ mvn clean compile exec:java -Dexec.mainClass=com.group.App
  • using "PS Terminal" from VS Code, the same command need to be:
  • $ mvn clean compile exec:java -D"exec.mainClass=com.group.App"

How to work with its latest version?

In some cases, you may work with the latest version of archetype-modern-starter, i.e., the version available on GitHub but not released to maven central repository. This can be caused by various of reasons, such as new bug fixes or you just fork it and add some cool features and etc.

You can easily install the latest version(SNAPSHOT) into your local repository:
  • clone the archetype project from the original GitHub or your forked GitHub
  • under the local project directory, type the following command to deploy it into your local repository:
  • $ mvn clean install
  • and then, you can work it as normal with choosing the appropriate version (SNAPSHOT version, not the release versions)

Reference

Wednesday, 26 September 2018

GnuPG Survival Guide


GnuPG, stand for GNU Privacy Guard, which is a complete and free implementation of the OpenPGP standard as defined by RFC4880 (also known as PGP). The developers open use this tool to sign the digital products created. This guide shows the usage of some common commands of GPG.

Common Commands


# get help for gpg
$ gpg --help

# list public keys
$ gpg --list-keys

# list secret keys
$ gpg --list-secret-keys


# create a new full featured key pair (and its revocation certificate)
$ gpg --full-generate-key

# create a revocation certificate to a file
$ gpg --output <certificate file(.asc)> --generate-revocation <key id>


# revoke a key with its revocation certificate
$ gpg --import <certificate file>
# and then, update the key server as well.
# The --keyserver option is not required, when the keyserver is specified in ~/.gnupg/dirmngr.conf.
$ gpg --keyserver <key server url> --send <key id>


# delete a secret key
$ gpg --delete-secret-key <key id>

# delete a public key
$ gpg --delete-key <key id>


# export specific(or all) public key into the file "public-gpg.key"
$ gpg -a --export [<key id>] > public-gpg.key

# export specific(or all) secret key into the file "secret-gpg.key"
$ gpg -a --export-secret-keys [<key id>] > secret-gpg.key

# export owener trust into the file "ownertrust-gpg.txt"
$ gpg --export-ownertrust > ownertrust-gpg.txt


# import secret keys(which contains the public key)
$ gpg --import secret-gpg.key

# import owner trust
$ gpg --import-ownertrust ownertrust-gpg.txt


# export keys to a keyserver
$ gpg --keyserver <key server url> --send-keys <key id>
$ gpg --keyserver hkp://pool.sks-keyservers.net --send-keys <key id>

# import keys from a keyserver
$ gpg --keyserver <key server url> --receive-keys <key id>
$ gpg --keyserver hkp://pool.sks-keyservers.net --receive-keys <key id>

# update a key if your version of it is out of date
$ gpg --refresh-keys <key id>


# search keys (interactively) contains term1 & term2
$ gpg --search-key <Term1> <Term2>

# search keys with key id from a key server
$ gpg --keyserver <key server url> --search-key <key id>


# edit key
$ gpg --edit-key <key id>

Troubleshooting for Git Bash with Gpg4Win

On the Windows OS, I prefer to install both Git for Windows and Gpg4Win for version control and secure solution. However, there is a glitch between these two powerful tools:
  • git version 2.18.0.windows.1
  • gpg4win-3.1.3
The issue is that git bash has its own version of gpg available, which is much outdated than the version of gpg provided by gpg4win. Their key stores are not same, and lots of the commands and arguments are not identical.

To avoid all issues brought by 2 versions of gpg, we can simply disable the gpg provided by Git, so that git bash can work with the updated gpg provided by gpg4win:
  • go to Git installation directory, which is C:\Program Files\Git in my system
  • go to its sub-directory usr\bin, locate the file gpg.exe
  • delete gpg.exe or rename it to another name, like gpg_dsiabled.exe
  • reopen git bash, run gpg --version, the updated version of gpg provided by gpg4win should be available

References

Friday, 17 August 2018

How to Publish Your Project at GitHub

It is important for modern software developers to publish open source projects online and collaborate with other developers over the whole world. Thanks to the modern technologies includes Git and its well-known service provider GitHub, these tasks become quite easy nowadays.

This guide outlines the whole process to publish a project on GitHub. Let's start.

How-to Guide

1. Install Git

Install and setup Git in your local computer:

2. Initial a Local Git Repository

Under your project directory, to initial a local git repository as follows:
$ git init

3. Manage Personal Information

If you choose to make your personal information public on GitHub, you can simply configure as follows:
$ git config --global user.name '<your-name>'
$ git config --global user.email '<your-email>'
If you want to keep your personal information private on GitHub, this is the way to do so:
  • sign in GitHub website, Edit profile > Personal settings > Emails, check the options "Keep my email address private" and "Block command line pushes that expose my email"
  • your GitHub non-reply email will be shown in that web page
  • config personal information for GitHub hosted repositories using your GitHub non-reply email:
  • $ git config user.name '<your-GitHub-login-name>'
    $ git config user.email '<your-GitHub-nonreply-email>'
    

4. Manage .gitignore

Under your project directory, create a file called .gitignore that lists all files/patterns which should NOT be managed/tracked by Git (in other word, to be ignored). The different sorts of projects determine the different ignore list. Please check the following examples for references:

5. Manage files

Add the project files to the local repository:
  1. add all project files (except the ignored files) into staging area
  2. $ git add .
  3. commit the staged files
  4. $ git commit -m '<commit message>'

6. Create a GitHub Repository

  1. sign in or sign up a GitHub account
  2. click the plus icon beside your login icon, and then select "New repository"
  3. follow the provided instructions to fill in the required information
  4. record the GitHub repository url after it is created

7. Upload your Project to GitHub

  1. setup the new GitHub repository as the remote repository:
  2. git remote add origin <github repository url>
  3. upload your project files to GitHub repository (set up-stream remote as well):
  4. git push -u origin master

8. Polish up

You may polish your GitHub repository in the following ways:

Reference