Skip to content

zetkin/lyra

Repository files navigation

Lyra web app

Lyra is a translation management system that integrates with source code repositories of internationalized applications.

  • Lyra can extract messages and translations from source code repositories.
  • Lyra is an editor for translating messages.
  • Lyra can create pull requests to merge updated translations into the source code repository.

Warning

A party who controls a source code repository branch which Lyra is set up to translate will also have a lot of control over the Lyra process. That control probably includes reading files from the operating system and possibly includes arbitrary code exection.

For each repository Lyra is set up to translate, Lyra needs control over a file system directory.

Warning

A party who controls the contents of a local repository directory will also have a lot of control over the Lyra process, probably including arbitrary code execution.

Setup

  1. Install npm
  2. Install dependencies: npm install

Visual Studio Code

If you are using Visual Studio Code, there are a few more optional steps you can take to setup your develop environment.

Prettier

Install the recommended extension Prettier - Code formatter.

PlantUML

  1. Install the extension PlantUML (Id: jebbs.plantuml).
  2. Follow its documentation for setting up its requirments.

Running in development

In the root folder (outside webapp) create file ./config/projects.yaml with example content:

projects:
  - name: example-unique-name
    base_branch: main
    project_path: . # relative path of the project from repository root
    owner: amerharb
    repo: zetkin.app.zetkin.org
    host: github.com
    github_token: << github token >>

⚠️ Note that repo must not have the same value for two different projects.

Multiple projects are supported, and they're all stored within the lyra-projects folder on the same level as the lyra repository itself.

The project repository (client repository) will be cloned locally (if it does not exist yet) and needs to have a lyra configuration file .lyra.yaml in the root of the repository. This lyra configuration file looks like this:

version: 1 # version of the lyra configuration file
projects:
  - path: . # relative path to project in repo
    messages:
      format: ts
      path: src # relative path of messages folder relative from above project path
    translations:
      path: src/locale # relative path of translations folder relative from above project path
    languages: # list of language codes supported in the project
      - sv
      - de
      - en

Start the server with npm run dev in webapp.

Open the URL provided in the terminal to view projects.

Click on projects to view project pages or click on languages to view translation pages.

Dependencies

Lyra runs on Node and likely uses its HTTP-server to serve requests from Internet. This HTTP server will process data before any authentication or validation: it is fully exposed. A vulnerability in Node can have a severe impact of Lyra, including compromise of GitHub authentication tokens, and through those, compromise of at least the targeted repositories.

https://nodejs.org/

Under Node, Lyra runs on the framework Next.js, while not as exposed, or as privileged as Node, it still processes data before authentication and a lot of that data has not been validated by any other program before being processed by Next.js. The framework does not have quite as much privileges as Node but once we are confident in Node being fully patched and known vulnerabilities being mitigated, we should do the same for Next.js

https://nextjs.org/

We have several other direct dependencies that are used by Lyra but a vulnerability in any of these will most likely be less severe than a vulnerability in Node or in Next.

Our direct dependencies pull in more transivite dependencies. Some of these could be more sensitive than our direct dependencies but we will likely never have enough resources to analyze them all. With some luck, the projects producing our direct dependencies takes some responsibility for their dependencies. Keeping our direct dependencies patched reduces the risk somewhat of us being affected by public vulnerabilities in our transitive dependencies.

Lyra's build and test programs have even more dependencies. These will not typically have access to production data or production credentials, but they will very likely have access to very powerful developer credentials. Tracking published vulnerabilities in all these is beyond all hope and feasibility but we can try to keep them somewhat up to date.

Standalone build (monorepo)

We enable Next.js standalone output to keep Docker images tiny. Because this package lives in a workspace, we must widen dependency tracing.

next.config.js

const path = require('path');

/** @type {import('next').NextConfig} */
module.exports = {
  output: 'standalone',
  experimental: {
    // trace files from the repository root
    outputFileTracingRoot: path.join(__dirname, '../..'),
  },
};

Gotchas

  • Place every module that is imported at runtime in this package’s dependencies (not devDependencies). Example: typescript required by src/utils/readTypedMessages.ts.

  • After upgrading Next.js or adding workspace packages, check the bundle:

    npm run build
    node --check webapp/.next/standalone/lyra/webapp/server.js

References

Docker setup

To run Lyra in a docker container, you need to build the Docker image using the Dockerfile in the root of this repository. The docker-compose.yaml file in the root of this repository can be used to build the image and run the image as a container in one command:

$ docker compose up

or in a detached mode:

$ docker compose up -d

Docker volume mounts

SSH key

Note that in order for the running docker container to be able to interact with the client repository, you need to mount a private SSH key of a user with access to the repository into the Docker container. Currently, this is achieved by mounting the private SSH key at ~/.ssh/id_rsa into the container at /home/nodeuser/.ssh/id_rsa. If your SSH key is located elsewhere on your local machine, you will need to adjust the path in the docker-compose.yaml file accordingly. ⚠️ Note that encrypted private keys are not supported for now.

When mounting the SSH key into the container, the file ownership and permissions from your local system are preserved. Since the container runs as the nodeuser user (UID 1001), but the mounted key is owned by your local user, it’s important to ensure that the SSH key has the correct permissions. SSH requires that private keys are not accessible by others. To avoid permission issues, you should set the permissions of your private key to 600 on your local machine:

$ chmod 600 ~/.ssh/id_rsa

This ensures that the private key is only readable by the owner, which is sufficient for SSH to accept it inside the container.

File permissions for the private key and lyra-store.json on your local machine also need to allow access for a user ID of 1001.

Lyra Store

Before running the container, ensure the file lyra-store.json exists on the host system. This file is the store for lyra projects and is mounted into the container via docker volume mounts. You can copy this via cp ./webapp/store.json ~/lyra-store.json to this location or just change it to use webapp/store.json.

Release a new container image

The GitHub Actions workflow build-and-push-image.yaml is designed to automate the process of building, tagging, and pushing a Docker image to the GitHub Container Registry (ghcr.io) whenever a new tag is pushed to the repository. The tags must follow semantic versioning, while release candidates are supported as well.

Do not forget to document your changes within the CHANGELOG.md file and adjusting the version within the ./webapp/package.json file.

Use built image from the container registry

In case you want to use the already built image that is pushed to the GitHub Container Registry, you can adjust the docker-compose.yaml file as follows (replace ${version} with the version of your preference):

services:
  lyra:
    container_name: lyra
-   build:
-     context: .
+   image: ghcr.io/zetkin/lyra:${version}
    ports:
      - "3000:3000"
    environment:
      - GIT_USER_EMAIL=lyra@zetk.in
      - GIT_USER_NAME="Lyra Translator Bot"
    volumes:
      - ~/.ssh/id_github:/home/nodeuser/.ssh/id_rsa:ro
      - ~/lyra-store.json:/app/webapp/store.json
      - ./config:/app/config

About

No description, website, or topics provided.

Resources

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 12