How to create a GitHub Packages for typescript projects
Tags: npm, githubactions, typescript, javascript
Published: 2023-09-29 08:46:19

🌟 **What’s the Buzz About GitHub npm Packages?**

In the grand universe of code, GitHub Packages is like your friendly neighborhood supermarket, but for code packages! 🏪 It's where your code’s grocery list finds everything it needs - all neatly shelved under one big GitHub roof. It’s your one-stop-shop for hosting and managing packages, bringing together your source code and dependencies, and making sure only the folks you want can access them. 🛒 And the billing? All tied up in a neat bow within GitHub, keeping your software development sleek and centralized. It's the superhero your code didn’t know it needed! 🦸‍♂️

🚀 **Ready to Start a New Project Adventure? Follow Me!**

1 - **Summon Your Terminal:** Pop open your terminal - think of it as opening the doors to your coding kingdom. 👑
2 - **Create a New Kingdom:** Now, let’s carve out a new land for your project. You can create a new folder (I named mine `github-package-example`, feel free to get creative! 🎨) with a simple command, and crown it as the new realm of your code.
  
```
mkdir github-package-example
```

3 - **Initiate the Magic of npm:** Inside your new kingdom, initiate the npm with the sacred `npm init` command. It's like casting a spell to summon the npm spirits to prepare your land for coding greatness! 🧙‍♂️
    
```
cd github-package-example
npm init
```
    
4 - **A Path of Questions:** The npm spirits will now ask you a series of questions about your project. Fear not! You can bravely press enter for all options. (Worry not about the details for now; we’ll shape and chisel them in the next steps.) 🗿

5 - 🌐 **Next Step, Forge a GitHub Repository:**
Embark on a new adventure by creating your own GitHub Repository. It’s like crafting a treasure chest where you’ll keep all your precious code gems. Navigate to [GitHub](https://github.com/), click the '+' on the upper-right corner and choose ‘New repository’. Give it a worthy name and bring it to life!


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7rgq4f10u7jh3rneuboo.png)


6 - 🛡️ **Connect Your Local Realm to the Remote Kingdom:**
It's time to build a magical bridge between your local project and your newfound GitHub Repository! Copy the remote URL from your repository on GitHub. Head back to your terminal in the directory of your project and paste the commands to connect the two realms together.
    
```
git remote add origin YOUR_REMOTE_URL
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uozn8smzdwd2frju6ei4.png)

7 - 🌟 **Initialize Your GitHub Kingdom:**
Inside your project folder, initiate GitHub by entering the command below. It's like laying the cornerstone for your GitHub kingdom right in your local project!

```
git init
```

8 - 📜 **Update Your Treasure Map (`package.json`):**
Now, let’s make sure everyone knows where your treasure (code) lies! Update your `package.json` by adding the repository info. It’s like marking your treasure on a map, guiding fellow adventurers to your project’s repository on GitHub!
    
```
"repository": {
  "type": "git",
  "url": "git+https://github.com/your-username/github-package-example.git"
}
```

And lo! Your local project is now in sync with your GitHub Repository, a beacon shining brightly in the GitHub universe, calling out to fellow coders and adventurers! 🌌 

9 - 📚 **Install TypeScript:**
Before you embark further, arm yourself with TypeScript! It's like learning an ancient language to cast more powerful code spells. In your terminal, within your project directory, run the command:
    
```
yarn add typescript -D
```    

10 - 🛠️ **Install the Tsup Toolkit:**
Next, equip yourself with `tsup`, a mighty tool for building your library. In the realm of your terminal, unleash the command:

```
yarn add tsup -D
```

11 - 🧙‍♂️ **Update the `package.json` Scroll:**
Time to update your magical scroll, `package.json`. It's like drawing a new rune to enhance your project's power. Remember to add your organization or user in the name property to ensure your package's successful journey in the world.

Here's a tip from a fellow adventurer: if you're not part of any organization, use your username as a prefix. For example:

```
"name": "@vitoraguila/github-package-example",
```

The packege.json will be:

```
{
  "name": "@vitoraguila/github-package-example",
  "version": "1.0.0",
  "description": "",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "type": "module",
  "scripts": {
    "build": "npx tsup --dts"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/vitoraguila/github-package-example.git"
  },
  "author": "",
  "license": "ISC"
}
```

Let’s explain

### **`"main"`**

- **What it is:** The entry point file for your project.
- **What it means:** When others use your project as a module, it will load from the **`./dist/index.cjs`** file.

### **`"module"`**

- **What it is:** Specifies the file that should be used as the module entry point.
- **What it means:** This field is used by tools that work with ES modules, and it points to **`./dist/index.js`**.

### **`"types"`**

- **What it is:** The path to the type definitions for this project.
- **What it means:** If your project is written in TypeScript, this field points to the file (**`./dist/index.d.ts`**) containing the type definitions.

### **`"type"`**

- **What it is:** Specifies the type of the module.
- **What it means:** This project is an ES module, so you can use import and export syntax in your JavaScript files.

### **`"scripts"`**

- **What it is:** A script to build your project.
- **What it means:** By running **`yarn build`**, it will execute **`npx tsup --dts`**, which builds your project and generates type definitions.

### **`"repository"`**

- **What it is:** Information about the project repository.
- **What it means:** The code for this project is stored in a git repository located at the given URL.

if you need to generate the declaration typescript files please add `--dts`

to the command `build` being `npx tsup --dts`

12 - 📜 **Craft a `.gitignore` :**
Create a `.gitignore` scroll in your project’s realm. It's like setting up a magical barrier that keeps unnecessary files from entering your repository's sacred grounds.

In the terminal, conjure the scroll with a touch of a command:

```
touch .gitignore
```

Then, write down the names of the files or directories you wish to guard against, like the `node_modules/`.

13 - 🧙‍♂️ **Forge Your `tsup.config.ts`:**
Now, craft a `tsup.config.ts` in your project directory. It’s like inscribing a powerful spell to guide the building of your project. Use it to hold your `tsup` configuration and make your building process a breeze.
    
Example:

```
// tsup.config.ts
import "dotenv/config";
import { defineConfig } from "tsup";

export default defineConfig({
  entry: {
    index: "src/index.ts",
  },
  external: [],
  format: ["esm", "cjs"],
  esbuildPlugins: [],
  dts: "src/index.ts",
});
```

Inside the **`defineConfig`** function, several configuration options are defined:

### **`entry: { index: "src/index.ts" }`**

- **What it is:** Entry point for the project.
- **What it means:** It tells **`tsup`** that **`src/index.ts`** is the entry file for the project.

### **`external: []`**

- **What it is:** An array of external modules.
- **What it means:** It is used to specify modules that should remain external to the bundle. Currently, it's an empty array, so no modules are marked as external.

### **`format: ["esm", "cjs"]`**

- **What it is:** Output formats.
- **What it means:** **`tsup`** will bundle the project into both ES module (**`esm`**) and CommonJS (**`cjs`**) formats.

### **`esbuildPlugins: []`**

- **What it is:** An array of ESBuild plugins.
- **What it means:** Allows you to use ESBuild plugins in the bundling process. Currently, no plugins are being used as it's an empty array.

### **`dts: "src/index.ts"`**

- **What it is:** Generation of declaration file.
- **What it means:** Tells **`tsup`** to generate a declaration file (**`d.ts`**) based on the **`src/index.ts`** file, which includes type definitions for the project.

This breakdown provides an understanding of each section of the **`tsup.config`** file, helping readers to know what each part does and how it contributes to the configuration of the TypeScript bundling process with **`tsup`**.

14 - 🌟 **Equip Additional Magical Artifacts:**
For additional capabilities like using environment variables or styling with SCSS/SASS, you may need to call upon extra libraries or plugins. It's like seeking the aid of mythical creatures for your journey!

Even though we won't dive deep into the enchanted forests of environment variables in this tutorial, a trusted companion would be the `dotenv` library for managing environment variables.

To enlist its aid, summon it with the following incantation:

```
yarn add dotenv
```

And Lo! Your project now stands tall, armored with a `.gitignore` scroll, empowered by a `tsup.config.ts`, and ready to call upon additional allies for further enhancement! The path ahead is bright and clear, venture forth into the realms of coding with courage and joy! 🌟 #OnwardAndUpward

15 - 📁 **Crafting the Source File:**
In the sacred `source` folder, create a file to export a simple sum function. This humble beginning will serve as an example to illuminate the path of library creation. Just imagine, a single incantation capable of summing two numbers! 🧮
    
Example:
    
```
// src/index.ts
export const sum = (a: number, b: number) => a + b;
```

16 - 🏃‍♂️ **Embark on the Run:**
Now, valiant coder, you are primed to set your creation into motion. With a flourish of a command, breathe life into your project:

```
yarn build
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmgjy1iuv9yxnviv7spm.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7pqc8lzzdzgjq9ztw097.png)


17 - 🏰 **Behold Your Creation:**
Upon running, a new dominion named `/dist` shall emerge in your project’s kingdom. Within its walls, you will find the artifacts of your creation, the generated files standing tall and resolute, ready to embark on adventures across the realm of code. 🗺️

📜 **Glimpse into the Future:**

As this chapter of the tome closes, fear not! In the forthcoming verses, prepare yourself to traverse the paths of publishing your noble package. Arm yourself with the might of GitHub Actions to build sturdy pipelines, ensuring your project’s enduring legacy in the annals of code! 🏹


---

# GitHub Workflows


1 - 📂 **Create a Home for GitHub Workflows:**
Unveil the gates to automation by manifesting a new bastion within your kingdom! Within your project’s realm, conjure forth a directory named `.github/workflows/`. This fortress shall safeguard the blueprints of your automated tasks and workflows, guarding the order within your code kingdom. 🏰
2 - 📜 **Craft the Scrolls of Automation:**
Within this stronghold, breathe life into two sacred scrolls:
- `master-release.yaml`: This scroll shall heed the call whenever a pull request merges into the master branch. It shall inscribe a new release, bestowing a tag upon the merged changes and preparing the ground for a bountiful harvest of updates. 🌱
- `publish.yaml`: This mighty scroll shall awaken upon the publication of a release. It shall brandish the powers of build and publish, propelling your package into the grand library of npm, ready to be summoned by other code-wielders across the realms. 📚

```
# .github/workflows/master-release.yaml

name: Create Release

on:
  pull_request:
    types:
      - closed
    branches:
      - master

jobs:
  release:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Get latest release details
      run: |
        RECENT_RELEASES_ARRAY=$(curl -qsSL \
          -H "Accept: application/vnd.github+json" \
          -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
          -H "X-GitHub-Api-Version: 2022-11-28" \
          "${{ github.api_url }}/repos/${{ github.repository }}/releases")

        RECENT_RELEASE=$(echo "$RECENT_RELEASES_ARRAY" | jq '.[0]')

        IS_DRAFT=$(echo "$RECENT_RELEASE" | jq -r '.prerelease')
        echo "IS_PRE_RELEASE=$(echo "$RECENT_RELEASE" | jq -r '.prerelease')" >> $GITHUB_ENV
        echo "IS_DRAFT=$IS_DRAFT" >> $GITHUB_ENV
        echo "TAG_NAME=$(echo "$RECENT_RELEASE" | jq -r '.tag_name')" >> $GITHUB_ENV

        if [[ "$IS_DRAFT" == "true" ]]; then
          echo "The most recent release is a draft. Skipping tag/release creation."
          echo "SKIP=true" >> $GITHUB_ENV
        else
          echo "Proceeding with tag/release creation."
          echo "SKIP=false" >> $GITHUB_ENV
        fi    

    - name: Create new tag
      id: newtag
      if: env.SKIP != 'true'
      env:
        GH_TOKEN: ${{ github.token }}
      run: |
        LABELS=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }} --jq '.labels.[].name')
        echo ${{ env.TAG_NAME }}

        # If there's no latest release (meaning it's the first release)
        if [[ -z "${{ env.TAG_NAME }}" ]] || [[ "${{ env.TAG_NAME }}" == "null" ]]; then
          NEW_TAG="v1.1.0"
          TYPE="MINOR"
          echo "type=$TYPE" >> $GITHUB_OUTPUT
          echo "tag=$NEW_TAG" >> $GITHUB_OUTPUT
          exit 0
        fi

        # Check if the latest release was a draft or pre-release
        if [[ "${{ env.IS_DRAFT }}" == "true" || "${{ env.IS_PRE_RELEASE }}" == "true" ]]; then
          echo "Latest release was a draft or pre-release. Skipping."
          exit 0
        fi

        CURRENT_TAG=${{ env.TAG_NAME }}
        IFS='.' read -ra VERSION <<< "$(echo $CURRENT_TAG | tr -d 'v')"

        MAJOR=${VERSION[0]}
        MINOR=${VERSION[1]}
        PATCH=${VERSION[2]}

        TYPE="PATCH"

        for LABEL in "${LABELS[@]}"; do 
          if [[ "$LABEL" == "major" ]]; then
            MAJOR=$((MAJOR + 1))
            MINOR=0
            PATCH=0
            TYPE="MAJOR"
            break
          elif [[ "$LABEL" == "minor" ]]; then
            MINOR=$((MINOR + 1))
            PATCH=0
            TYPE="MINOR"
            break
          fi
        done

        if [[ "$TYPE" == "PATCH" ]]; then
            PATCH=$((PATCH + 1))
        fi

        NEW_TAG="v$MAJOR.$MINOR.$PATCH"

        echo "type=$TYPE" >> $GITHUB_OUTPUT
        echo "tag=$NEW_TAG" >> $GITHUB_OUTPUT

    - name: Create GitHub Release
      if: steps.newtag.outputs.tag
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: ${{ steps.newtag.outputs.tag }}
        release_name: "[${{ steps.newtag.outputs.type }}] Release ${{ steps.newtag.outputs.tag }}"
        draft: true
        prerelease: true
```

### **When Does the Workflow Run?**

The GitHub Actions workflow outlined is designed to automatically create a new release when certain conditions are met. Here are the details regarding the circumstances under which the workflow is triggered and runs:

### Trigger Points

1. **Event Type: Pull Request Closure**
    - The workflow is activated when a pull request (PR) is closed. It listens for the **`closed`** event type under the **`pull_request`** event category.
    - **`on:`**
        
        ```
        pull_request:
          types:
            - closed
        ```
        
2. **Specific Branch: Master**
    - The closed PR must be targeted to the **`master`** branch. The workflow does not trigger for PRs closed on other branches.
    - **`branches:`**
        
        ```
        branches:
          - master
        ```
        
### Jobs

- The workflow comprises a single job named **`release`**. This job is responsible for the entire process of fetching the latest release details, creating a new tag, and creating a GitHub release.

### Conditional Steps within the Job

1. **Fetching the Latest Release Details**
    - Unconditionally, it fetches the most recent release's details to check whether it's a draft and the tag name.
    - If the latest release is a draft, a **`SKIP`** environment variable is set to **`true`**, halting the further steps.
2. **Creating a New Tag**
    - This step is conditional: it will only execute if **`SKIP`** is not **`true`**.
    - It fetches the labels of the closed PR and calculates the new tag based on the current tag and the labels (which indicate whether it's a major, minor, or patch release).
    - It sets the new tag and type in the outputs.
3. **Creating a GitHub Release**
    - This step is also conditional: it only runs if a new tag is successfully created in the previous step.
    - It creates a new GitHub release with the new tag and marks it as a draft and pre-release.

### **When Does the Workflow Not Run?**

1. **For PRs on Other Branches**
    - The workflow will not trigger for PRs that are closed on branches other than **`master`**.
2. **When the Latest Release is a Draft**
    - If the most recent release is a draft, the **`SKIP`** variable is set to **`true`**, and the subsequent steps (creating a new tag and GitHub release) are not executed.

### **Conclusion**

In essence, this GitHub Actions workflow is specifically tailored to run when a PR is closed on the **`master`** branch. It then checks the details of the latest release, and based on the condition whether the latest release is a draft or not, it either proceeds to create a new tag and GitHub release or skips these steps. This automation ensures streamlined and consistent release creation, aiding in efficient project management and version control.

---

### **Version Bumping Logic in GitHub Actions Workflow**

In the GitHub Actions workflow described, an important step is the automatic version bumping. The version number follows a typical semantic versioning pattern: major.minor.patch (for example, v1.2.3).

1. **Initial Assumptions**:
    - If there’s no previous release, it starts with a default version of v1.1.0.
    - It assumes a patch release unless indicated otherwise.
2. **Fetching the Current Tag**:
    - The script fetches the latest release tag from the GitHub API, which is stored in **`CURRENT_TAG`**.
3. **Extracting Version Numbers**:
    - The major, minor, and patch numbers are extracted from **`CURRENT_TAG`**.
4. **Checking Labels for Version Bump Type**:
    - The script then checks the labels on the closed pull request.
        - If it finds a **`major`** label, it increments the major version and resets minor and patch versions to 0.
        - If it finds a **`minor`** label, it increments the minor version and resets the patch version to 0.
5. **Default to Patch Version Bump**:
    - If no **`major`** or **`minor`** labels are found, it defaults to a patch version bump, incrementing only the patch version number.

Here’s the breakdown of the version bumping logic:

```
bashCopy code
# Extract the current version numbers
MAJOR=${VERSION[0]}
MINOR=${VERSION[1]}
PATCH=${VERSION[2]}

# Assume a patch release by default
TYPE="PATCH"

# Iterate through the labels
for LABEL in "${LABELS[@]}"; do
  # If the label is "major"
  if [[ "$LABEL" == "major" ]]; then
    # Increment the major version, reset minor and patch to 0
    MAJOR=$((MAJOR + 1))
    MINOR=0
    PATCH=0
    TYPE="MAJOR"
    break
  # Else, if the label is "minor"
  elif [[ "$LABEL" == "minor" ]]; then
    # Increment the minor version, reset patch to 0
    MINOR=$((MINOR + 1))
    PATCH=0
    TYPE="MINOR"
    break
  fi
done

# If it’s still a patch release
if [[ "$TYPE" == "PATCH" ]]; then
    # Increment the patch version
    PATCH=$((PATCH + 1))
fi

# Construct the new tag
NEW_TAG="v$MAJOR.$MINOR.$PATCH"
```

**Conclusion**:

In this part of the script, the version number is automatically bumped based on the labels on the pull request. Labeling a pull request with **`major`** or **`minor`** will influence the versioning logic, ensuring the new release tag reflects the type of changes introduced. This approach automates the versioning process, saving time and reducing the potential for human error in version numbering.

---

## The Publish workflow

```
# .github/workflows/publish.yaml

name: build

on:
  release:
    types: [published]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        
      - name: Set env
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          echo "RELEASE_VERSION=$(gh release list --repo https://github.com/${{ github.repository }} --limit 3 | grep -o 'v.*' | sort -r | awk 'NR==1  {print $3}' | sed 's/^v//g; s/[^0-9\.]//g')" >> $GITHUB_ENV

      - name: Debug
        run: |
          echo "Release version: ${{env.RELEASE_VERSION}}"

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 16.x
          registry-url: 'https://npm.pkg.github.com'
          scope: '@vitoraguila'

      - name: Create release branch 
        run: |
          git checkout -b release/${{env.RELEASE_VERSION}}

      - name: Install dependencies
        run: yarn && yarn install

      - name: Build
        run: yarn build

      - name: Patch version
        run: |
          git config --global user.name ${GITHUB_ACTOR}
          git config --global user.email "github-actions@github.com"
          git remote add publisher "https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"

          echo "Release version: ${{env.RELEASE_VERSION}}"

          yarn config set version-git-tag false
          yarn version --new-version ${{env.RELEASE_VERSION}}

          git commit package.json -m "Updated package.json version to version released ${{env.RELEASE_VERSION}}"
          git push publisher HEAD:release/v${{env.RELEASE_VERSION}}

      - name: Publish
        run: yarn publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

### **When Does the Workflow Run?**

### Trigger Points

1. **Event Type: Release Publication**
    - The workflow is activated when a release is published.
    - **`on:`**
        
        ```yaml
        release:
          types: [published]
        ```
        

### **Steps within the Workflow**

### 1. **Checkout**

- Uses the **`actions/checkout@v3`** action to checkout the repository code to the runner, allowing the workflow to access the repository content.

### 2. **Set Environment Variables**

- Uses the GitHub CLI to fetch the latest release version from the repository and sets it as an environment variable **`RELEASE_VERSION`**.
- This version is used in subsequent steps for creating a release branch and patching the version.

### 3. **Debug**

- Echoes the release version to the log for debugging purposes, ensuring that the **`RELEASE_VERSION`** is set correctly.

### 4. **Setup Node**

- Sets up the Node.js environment using **`actions/setup-node@v3`**.
- Specifies Node version **`16.x`** and configures the npm registry URL and scope for GitHub Packages.

### 5. **Create Release Branch**

- Checks out a new branch named **`release/${RELEASE_VERSION}`**, where **`${RELEASE_VERSION}`** is the version number fetched earlier.
- This branch is used for making changes to **`package.json`** and pushing the updated version back to the repository.

### 6. **Install Dependencies**

- Installs project dependencies using Yarn to ensure that the project can be built successfully.

### 7. **Build**

- Executes the **`yarn build`** command to build the project.

### 8. **Patch Version**

- Configures **`git`** with the GitHub actor's name and email.
- Adds a new remote named **`publisher`** to **`git`**, which is used for pushing changes to the repository.
- Updates the version in **`package.json`** to the release version and commits the changes to the newly created release branch.
- Pushes the changes to the **`release/v${RELEASE_VERSION}`** branch in the repository.

### 9. **Publish**

- Publishes the package using **`yarn publish`**.
- Uses a GitHub token for authentication when publishing the package.

### **When Does the Workflow Not Run?**

- The workflow will not trigger for other types of release events such as **`created`**, **`edited`**, or **`deleted`**.
- It only runs when a release is **`published`**.

### **Conclusion**

In essence, the **`build`** workflow is a comprehensive automated process for handling the release cycle after a release is published. It efficiently manages the tasks of setting up the environment, creating a release branch, building the project, patching the version, and publishing the package, ensuring a smooth and consistent release process.

### **1. Set env Step**

In the “Set env” step, the goal is to determine the version number of the most recent release and assign it to an environment variable. Here is the breakdown:

### Logic:

- The GitHub CLI (**`gh`**) is used to fetch the list of releases for the repository.
- The **`grep`** command is used to find the version number, which is expected to be in a format starting with 'v' (for example, **`v1.2.3`**).
- The **`awk`** command fetches the third column, which is the version number.
- The **`sed`** command is used to remove the 'v' prefix and any non-numeric or non-dot characters, leaving only the numeric version (for example, **`1.2.3`**).
- This version number is then echoed as **`RELEASE_VERSION`** into the GitHub environment variable file (**`$GITHUB_ENV`**), making it accessible to subsequent steps in the workflow as **`env.RELEASE_VERSION`**.

### Script Breakdown:

```
echo "RELEASE_VERSION=$(gh release list --repo https://github.com/${{ github.repository }} --limit 3 | grep -o 'v.*' | sort -r | awk 'NR==1  {print $3}' | sed 's/^v//g; s/[^0-9\.]//g')" >> $GITHUB_ENV
```

This one-liner script is performing the following tasks sequentially:

- List the last three releases of the repository.
- Search for version patterns and extract them.
- Sort the versions in reverse order to get the latest first.
- Use **`awk`** to print the third field (version number).
- Use **`sed`** to format the version number by removing the 'v' and keeping only the numbers and dots.
- Set the formatted version number as **`RELEASE_VERSION`** in the environment variables.

### **2. Patch version Step**

The “Patch version” step is responsible for updating the version number in **`package.json`** and pushing the changes to a new release branch. Here is the detailed explanation:

### Logic:

- Git configuration is set up with the GitHub actor’s name and a generic email.
- A new remote named **`publisher`** is added for pushing changes to the repository. The URL for the remote includes authentication information.
- The **`yarn config set version-git-tag`** command is used to prevent Yarn from creating a git tag for the new version.
- **`yarn version --new-version`** is used to update the version in **`package.json`** to the **`RELEASE_VERSION`** fetched earlier.
- These changes (the updated version in **`package.json`**) are committed with a commit message indicating the updated version number.
- The changes are then pushed to a new branch in the format **`release/v${RELEASE_VERSION}`**.

### Script Breakdown:

```
git config --global user.name ${GITHUB_ACTOR}
git config --global user.email "github-actions@github.com"
git remote add publisher "https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"

echo "Release version: ${{env.RELEASE_VERSION}}"

yarn config set version-git-tag false
yarn version --new-version ${{env.RELEASE_VERSION}}

git commit package.json -m "Updated package.json version to version released ${{env.RELEASE_VERSION}}"
git push publisher HEAD:release/v${{env.RELEASE_VERSION}}
```

This script:

- Configures git with a user name and email.
- Adds a new remote for pushing, with the URL containing the GitHub token for authentication.
- Prevents Yarn from creating a git tag for the version.
- Updates the **`package.json`** version to the **`RELEASE_VERSION`**.
- Commits the updated **`package.json`** file.
- Pushes the commit to a new release branch named **`release/v${RELEASE_VERSION}`**.

### **Conclusion**

Both "Set env" and "Patch version" steps are crucial for ensuring the project version is consistently and accurately managed in the release process. The “Set env” step fetches and sets the latest release version, while the “Patch version” step uses this version to update **`package.json`** and push the changes to a dedicated release branch.

---

### GitHub repository configuration

🔐 **Empower Your Repository:**

Embark on a quest to the heart of your GitHub repository. Within the sanctum of settings, bestow upon your workflows the permission to read and write. Arm them well for the automated adventures that lie ahead. 🛡️

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/05zcpcxmmn9d828c3a34.png)

🤝 Create **a New PR:**

With your repository empowered, manifest a new Pull Request (PR). This can be a mere scroll of introduction, inscribing a few words in your README. It's but a step to awaken the magic within the GitHub actions. 📜

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0mp4jadhn7az8assgip.png)

🏷️ **Label the Milestones:**

In the bustling bazaar of your PR screen, forge the labels to mark the milestones of your package's journey. These tokens shall command the tides of versioning, guiding your package's growth and evolution. 🌊

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p0xm7ub19xaqugg0yk1v.png)

🚶‍♂️**Proceed With No Version?**

Fear not the path unknown. Venture forth without a version label and behold as the default pact of a patch release unfolds, shepherding your package with gentle embrace. 🌌

⚔️**Merge and Unleash the Magic:**

Merge your PR! Feel the surge of magic as the first workflow springs to life, etching the annals of its quest within the GitHub realms. ✨

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ds1osqiat6c5cyk5ntld.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hypf194vbn20ddq9lzz1.png)

🗺️ **Discover Your Draft Release:**

Embark upon the trails of your repository and venture into the “Release”. Lo! A draft release, freshly crafted, awaits your gaze. 📜

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jh8u6b9ue2r5ddmfwn9n.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26q7bmo5djzt04nyfq0z.png)

📝 **Bestow Your Words:**

Adorn your draft release with tales and descriptions of your package's voyage. Unveil it to the world, unchecking the `pre-release` charm, and let it sail the cosmic rivers as a published release. 🌟

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kao0ol4euowzfzjolgbz.png)

📜 **The publish.yaml:**

With the release set forth into the world, the `publish.yaml` pipeline awakens from its slumber, ready to unfurl its magic.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7cjtcaub7ndf4l5h8w0.png)

🎉**Celebration in Packages:**

Upon the completion of this sacred rite, your package is born anew in the hallowed halls of GitHub Packages, eager to embark on countless adventures in the realms of code and computation.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nledv6bsyiip9xrz95qe.png)

🧙‍♂️ **Beholding Your Creation:**

In the Packages sanctum of your GitHub repository, gaze upon your package, resplendent and ready to weave its magic in the world of code.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zgdccm9y5bo2knpjxop.png)

🗝️ **The Key to Installation:**

Heed these words, O noble coder! The `GITHUB_ACCESS_TOKEN` is the key to installing your package. Guard it well, in local realms and the ethereal expanse of GitHub Actions in other repositories.

In another repository, yearning for the magic of your package? Bestow upon it your personal access token as an environment elixir, named **`$GITHUB_ACCESS_TOKEN`**. Whisper these ancient words before the installation rite:

```
echo //npm.pkg.github.com/:_authToken=$GITHUB_ACCESS_TOKEN >> ~/.npmrc
```

In conclusion, I extend my heartfelt gratitude for accompanying me on this enlightening journey through the world of GitHub, workflows, and packages. Your time and engagement throughout this expedition is deeply valued.

While embarking on the path to demystify the technical intricacies, I endeavoured to infuse an element of light-hearted humor and creativity in the narration. My sincerest hope is that this endeavour has not only been a source of valuable insight but also a fountain of joy and amusement.

For a more tangible exploration, you are cordially invited to peruse the repository that bears the code of this endeavour. Embark on this link to navigate to the **[GitHub Repository](https://github.com/vitoraguila/github-package-example)**.

May your own journey in the vast universe of code be filled with exploration, learning, and countless successes. Your quest continues, noble reader, and the world of code and innovation eagerly awaits your contributions.

With warm regards and a sprinkle of coding magic!

Follow me on [Github](https://github.com/vitoraguila)
Follow me on [Linkedin](https://www.linkedin.com/in/vitoraguila/)