# Connecting External CI

Limio uses AWS CodeCommit to store and manage versions of your Custom Components. If you use another platform, such as GitHub or GitLab, you can continue using it, but you must mirror your changes to Limio's AWS CodeCommit repository.

To automate this process and make sure all your continuous changes to Custom Components are in Limio, you should set up a CI pipeline using GitHub Actions or CircleCI.

In this tutorial, we will be using **GitHub Actions** and [**CircleCI**](https://circleci.com/) with **GitHub**.

### Prerequisite

To connect an external CI in GitHub, you will need to have the following:

* Cloned the **Limio Components Repository.** If you haven't done this yet, go [**here**](https://docs.limio.com/developers/custom-components/custom-components). As part of this setup, you will have:
  * Securely stored the **credentials** (username and password).
    * If you don't have this, contact the person who initially cloned the repository or contact <support@limio.com> to request credentials.
  * The URL of the **AWS CodeCommit** repository to mirror. For example:
    * ```
      https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/{tenant}-components
      ```
* For GitHub Actions, you have access to **Github Actions**.
* For CircleCI, you have connected **CircleCI** to GitHub.
  * You have **GitHub API key** to the repository you wish to use for the mirroring.
  * You have **GitHub Admin access.**
* Be familiar with YAML files

### Mirroring Your Repository with a CI Pipeline

To mirror your repository, Limio recommends using a [**Cron Job**](https://www.hostinger.co.uk/tutorials/cron-job) in your CI pipeline. Alternatively, some tools may support [Triggers](https://circleci.com/docs/triggers-overview/), which also allow you to automatically duplicate the repository when pushing to specific branches of your GitHub repository.

Regardless of the method you choose, you will need to use the **Limio-provided credentials** along with your **GitHub API key** to run a scripted process. Tools like **Python** can be used to automate cloning and syncing your repository.

The key step is to commit a **YAML file** in the source repository you intend to use for Limio. In this tutorial, we'll explain how you can do this in GitHub Actions or CircleCI.

{% hint style="info" %}
Use another tool? Contact <support@limio.com> for help.
{% endhint %}

#### **GitHub Actions**

To set this up, you should follow [this guide](https://docs.github.com/en/actions/writing-workflows/quickstart#creating-your-first-workflow) from GitHub. When you need to provide a YAML file, you can use this template below. Make sure to:

* Modify `${{ secrets.CODECOMMIT_USER }}` and `${{ secrets.CODECOMMIT_PASS }}` with your credentials
* Modify the `https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/{tenant}-components` URL with your tenant's URL.

You can see also see an example of a mirrored public repository in Github with Github Actions [here](https://github.com/innovate42/saas-demo-components/tree/saas-dev).

```yaml
name: Mirror Repository to CodeCommit via HTTPS

on:
  push:
    branches:
      - saas-dev

jobs:
  mirror:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Mirror to CodeCommit Repository (HTTPS)
        env:
          CODECOMMIT_USER: ${{ secrets.CODECOMMIT_USER }}
          CODECOMMIT_PASS: ${{ secrets.CODECOMMIT_PASS }}
        run: |
          git remote add codecommit https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/{tenant}-components
          git push --all -f https://${{ secrets.CODECOMMIT_USER }}:${{ secrets.CODECOMMIT_PASS }}@git-codecommit.eu-central-1.amazonaws.com/v1/repos/{tenant}-components
```

#### **CircleCI**

To do this, you should be familiar with Circle CI YAML file (see [here](https://circleci.com/docs/introduction-to-yaml-configurations/)). We've prepared an example YAML configuration, though you should double-check it meets your company's practices.

The YAML file will run two files, setup-ssh.sh and clone.js, also described below

```yaml
jobs:
  clone:
    working_directory: ~/repositories
    docker:
      - image: circleci/node:5.1
    steps:
      - checkout
      - restore_cache:
          key: v1-dependencies-{{ checksum "<<YOUR DEPENDENCY LOCK FILE>>" }}
      - run:
          name: Install Dependencies
          command: |
            <<YOUR CHOSEN DEPENDENCY MANAGEMENT INSTALL>>
      - save_cache:
          key: v1-dependencies-{{ checksum "<<YOUR DEPENDENCY LOCK FILE>>" }}
          paths:
            - "~/.local/share/virtualenvs"
      - run:
          name: Setting up SSH access
          command: |
            chmod +x ./scripts/setup-ssh.sh
            ./scripts/setup-ssh.sh $SSH_KEY_ID
      - run:
          name: Mirror Limio Repository to AWS CodeCommit
          command: node ./clone.js

workflows:
  version: 2
  nightly:
    jobs:
      - clone
    triggers:
      - schedule:
          cron: "0 0 * * *"  # Runs every night at 00:00 UTC
          filters:
            branches:
              only:
                - master
```

**setup-ssh.sh**

This file sets up your credentials for the Limio Components Repository and should be structured as follows:

```sh
# Add CodeCommit to SSH Configuration
# see https://docs.aws.amazon.com/codecommit/latest/userguide/setting-up-without-cli.html#setting-up-without-cli-configure-client
 echo "Host git-codecommit.*.amazonaws.com
 User $1
 IdentityFile /home/circleci/.ssh/id_rsa" >> /home/circleci/.ssh/config

# Add CodeCommit Server as Known Host
ssh-keyscan -H git-codecommit.us-east-1.amazonaws.com >> ~/.ssh/known_hosts
```

**clone.js**

This file handles the cloning of the repository. While this example uses Node, any scripting language can be used. It also includes a cleanup job to delete the local repository after the sync is complete. Here’s an example:

```javascript
import { execSync } from "node:child_process"

// Enables synchronous execution
async function executeCommand(command) {
    try {
        return execSync(command, { stdio: `inherit` })
    } catch (e) {
        console.error(e); // should contain code (exit code) and signal (that caused the termination).
    }
}

const repositoryName = <<YOUR REPOSITORY NAME>>

async function cloneRepo() {
    console.log(`Cloning repository ${repositoryName}`)
    await executeCommand(`git clone --mirror https://github.com/${repositoryName}/`)
}

async function deleteRepo() {
    console.log(`Deleting repository ${repositoryName}`)
    await executeCommand(`rm -Rf ${repositoryName}`)
}
    
async function syncRepo() {
    console.log(`Pushing changes from repository ${repositoryName} to Limio")
    await executeCommand(`cd ${repositoryName} && git remote add sync https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/${repositoryName}`)
    await executeCommand(`cd ${repositoryName} && git push sync --mirror`)
}

async function run() {
    await cloneRepo()
    await syncRepo()
    await deleteRepo()
}

run()
```

### **Next steps**

Once you've set up the repository mirroring, you can manage the repository as per your coding convention. Other developers can also clone the mirrored repository to their local machine.

To make sure everything work, you should create your first Custom Components. Go the **README file** in the repository and follow the guidance there. You can also find it [here](https://github.com/innovate42/limio-components).

Once you push a change to a Custom Component, your repository will be updated. All the **Custom Components** in your repository will be automatically built and made available in the Component selector under the "**Custom Component**" category in **Limio Page Builder.**

<figure><img src="https://github.com/innovate42/innovate42-service-template/blob/docs/docs/_external/.gitbook/assets/image%20(4).png" alt=""><figcaption><p>Custom Components in the Component selector in the Limio application</p></figcaption></figure>

<figure><img src="https://github.com/innovate42/innovate42-service-template/blob/docs/docs/_external/.gitbook/assets/image%20(1).png" alt=""><figcaption><p>Custom Component in Page Builder in the Limio application</p></figcaption></figure>

If you version your components, you can also check the version of your **Custom Component** matches your expectation.

<figure><img src="https://github.com/innovate42/innovate42-service-template/blob/docs/docs/_external/.gitbook/assets/Screenshot%202025-02-06%20at%2012.21.41.png" alt=""><figcaption></figcaption></figure>
