# GitLab CI/CD

> Automate your frequent localization tasks such as uploading source files and downloading translations.

URL: https://store.crowdin.com/gitlab-ci
Identifier: gitlab-ci
Category: Development
Type: Guide
Author: Andrii Bodnar

Use [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) to automate your common localization tasks such as uploading source files, downloading translations or anything else you can do with Crowdin CLI.

### Preparing the repository

Push the `crowdin.yml` [configuration file](https://developer.crowdin.com/configuration-file/) to the repository.

Use [Environment Variables](https://developer.crowdin.com/configuration-file/#api-credentials-from-environment-variables) for API Credentials:

```yml
"project_id_env": "CROWDIN_PROJECT_ID"
"api_token_env": "CROWDIN_PERSONAL_TOKEN"
```

See the [GitLab CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) to learn more about defining variables in GitLab CI/CD.

### Pipeline configuration

You need to set up the `.gitlab-ci.yml` configuration file for GitLab CI/CD (or extend the existing one):

```yml
stages:
  - translations

variables:
    CROWDIN_PROJECT_ID: $CROWDIN_PROJECT_ID
    CROWDIN_PERSONAL_TOKEN: $CROWDIN_PERSONAL_TOKEN

translations:
  stage: translations
  image: crowdin/cli:latest
  script:
    - crowdin -V
    - crowdin download --no-progress
```

**Tip**: It's recommended to use the `--no-progress` flag for the CLI execution in CI/CD environment.

There is a possibility to store the downloaded translations as an artifacts using the `--keep-archive` option with the [`crowdin download`](https://crowdin.github.io/crowdin-cli/commands/crowdin-download) command:

```yml
stages:
  - translations

variables:
    CROWDIN_PROJECT_ID: $CROWDIN_PROJECT_ID
    CROWDIN_PERSONAL_TOKEN: $CROWDIN_PERSONAL_TOKEN

translations:
  stage: translations
  image: crowdin/cli:latest
  script:
    - crowdin download --no-progress --keep-archive
  artifacts:
    paths:
      - CrowdinTranslations_*.zip
```

The examples above use the official [`crowdin/cli`](https://hub.docker.com/r/crowdin/cli) Docker image. Alternatively, you can use the Node.js CLI package:

```yml
stages:
  - translations

variables:
    CROWDIN_PROJECT_ID: $CROWDIN_PROJECT_ID
    CROWDIN_PERSONAL_TOKEN: $CROWDIN_PERSONAL_TOKEN

translations:
  stage: translations
  image: node:latest
  script:
    - npm install -g @crowdin/cli
    - crowdin -V
    - crowdin status --no-progress
```

In this example, the job runs on the Node image and installs the [Crowdin CLI NPM package](https://www.npmjs.com/package/@crowdin/cli) globally. Once the CLI is installed, you can run any CLI command.

For more information about Crowdin CLI commands, please visit the official [Crowdin CLI website](https://crowdin.github.io/crowdin-cli/).

### Creating Merge Requests with Translations

You can automate the process of creating merge requests with downloaded translations. This example shows how to download translations, commit them to a new branch, and create a merge request automatically.

Set up the following environment variables in your GitLab project:

- `CROWDIN_PROJECT_ID` - Your Crowdin project ID
- `CROWDIN_PERSONAL_TOKEN` - Your Crowdin personal access token
- `GITLAB_API_TOKEN` - GitLab token with API access and write permissions (`api`, `write_repository` scopes)

Add the job to your `.gitlab-ci.yml`:

```yml
stages:
  - translations

variables:
    CROWDIN_PROJECT_ID: $CROWDIN_PROJECT_ID
    CROWDIN_PERSONAL_TOKEN: $CROWDIN_PERSONAL_TOKEN
    GITLAB_API_TOKEN: $GITLAB_API_TOKEN

download_translations:
  stage: translations
  image: node:latest
  before_script:
    - npm install -g @crowdin/cli
  script:
    - git config user.email "translations-bot@example.com"
    - git config user.name "Translations Bot"
    - git remote set-url origin "https://gitlab-ci-token:${GITLAB_API_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
    - export NEW_BRANCH_NAME="translations-update-${CI_COMMIT_REF_NAME}"
    - git checkout -b $NEW_BRANCH_NAME
    - echo "Downloading translations..."
    - crowdin download --no-progress
    - |
      if [[ -z $(git status --porcelain) ]]; then
        echo "No translation updates. Exiting."
        exit 0
      fi
    - git add .
    - git commit -m "chore: update translations"
    - |
      if git ls-remote --exit-code --heads origin $NEW_BRANCH_NAME >/dev/null 2>&1; then
        git push origin $NEW_BRANCH_NAME -f
      else
        git push origin $NEW_BRANCH_NAME
        curl --request POST "https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/merge_requests" \
          --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
          --header "Content-Type: application/json" \
          --data '{
            "source_branch": "'"${NEW_BRANCH_NAME}"'",
            "target_branch": "'"${CI_COMMIT_REF_NAME}"'",
            "title": "Update translations",
            "description": "This merge request is automatically created by the GitLab CI/CD pipeline.",
            "labels": "translations,ci",
            "remove_source_branch": true
          }'
      fi
    - echo "Translations updated successfully."
  only:
    - main
```

This workflow will:

1. Install Crowdin CLI on a Node.js image (which includes git and curl)
2. Configure git with bot credentials
3. Create a new branch for translations
4. Download all translations from Crowdin
5. Commit changes if any translations were updated
6. Push to the remote branch
7. Create a merge request automatically (or update existing branch if MR already exists)

## Resources

- [Console Client (CLI)](https://crowdin.github.io/crowdin-cli/)
- [Configuration File](https://developer.crowdin.com/configuration-file/)
- [Environment Variables](https://developer.crowdin.com/configuration-file/#api-credentials-from-environment-variables)
