diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 5bd37c9..c5483a8 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,4 +6,22 @@ on: [pull_request] jobs: build: - uses: ryansonshine/ryansonshine/.github/workflows/pr.yml@main + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup Node.js Environment + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: Install Dependencies + run: npm i + - name: Build Project + run: npm run build + - name: Run Test Suite + run: npm run test + - name: Upload Code Coverage + uses: codecov/codecov-action@v3.1.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 81056d8..7840e83 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,16 +1,37 @@ -# Reusable workflow for releases; to eject, you can replace this file with -# https://github.com/ryansonshine/ryansonshine/blob/main/.github/workflows/release.yml name: Release + on: push: branches: - main + workflow_call: + secrets: + NPM_TOKEN: + required: true + jobs: release: - permissions: - contents: write - issues: write - pull-requests: write - uses: ryansonshine/ryansonshine/.github/workflows/release.yml@main - secrets: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + name: Release to NPM + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup Node.js Environment + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: Install Dependencies + run: npm i + - name: Build Project + run: npm run build + - name: Run Test Suite + run: npm run test + - name: Semantic Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release + - name: Upload Code Coverage + uses: codecov/codecov-action@v3.1.0 diff --git a/README.md b/README.md index fe4b551..2fd6f58 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,42 @@ -# **repoverse** +# **Repoverse** ![version](https://img.shields.io/badge/version-1.0.0-blue) ![license](https://img.shields.io/badge/license-MIT-green) -## Table of Contents: +`Repoverse` is a powerful tool designed for distributed systems and microservices. It automates the propagation of relevant commits across multiple repositories, ensuring consistency and saving you time. -- [Overview](#overview) -- [Key Features](#key-features) -- [Prerequisites](#prerequisites) -- [Configuration](#configuration) -- [**Installation**](#installation) -- [**Usage**](#usage) - - [**1. As a GitHub Action**](#1-as-a-github-action) - - [**2. Programmatically in Your Code**](#2-programmatically-in-your-code) -- [**Workflow**](#workflow) -- [**Contributing**](#contributing) -- [License](#license) +## 📖 Table of Contents -## Overview - -`repoverse` is a tool for distributed systems and microservices where some part of the code needs to be synchronized across multiple repositories. Repoverse automates the propograiton of relavent commits across multiple repositories, ensuring consistency and saving you time. +- [**Repoverse** ](#repoverse--) + - [📖 Table of Contents](#-table-of-contents) + - [🌐 Overview](#-overview) + - [⭐ Key Features](#-key-features) + - [📚 Prerequisites](#-prerequisites) + - [⚙️ Configuration](#️-configuration) + - [📦 Installation](#-installation) + - [🚀 Usage](#-usage) + - [As a GitHub Action](#as-a-github-action) + - [Programmatically in Your Code](#programmatically-in-your-code) + - [🔄 Workflow](#-workflow) + - [🤝 Contributing](#-contributing) + - [📄 License](#-license) -## Key Features +## 🌐 Overview -- Automated synchronization: Propagates commits across all configured repositories, keeping them up-to-date. -- Flexible usage: Works as a GitHub Action or directly in your Node.js applications. -- Precise control: Synchronize specific paths and branches within repositories. -- Seamless integration: Integrates effortlessly into your development workflows. -- Collaborative synchronization: Raises pull requests for review and approval, ensuring code quality and alignment. +`Repoverse` is designed to keep your code synchronized across multiple repositories. It's perfect for distributed systems and microservices where some part of the code needs to be consistent. -## Prerequisites +## ⭐ Key Features + +- **Automated synchronization**: Propagates commits across all configured repositories, keeping them up-to-date. +- **Flexible usage**: Works as a GitHub Action or directly in your Node.js applications. +- **Precise control**: Synchronize specific paths and branches within repositories. +- **Seamless integration**: Integrates effortlessly into your development workflows. +- **Collaborative synchronization**: Raises pull requests for review and approval, ensuring code quality and alignment. + +## 📚 Prerequisites - Node.js (version 14 or higher) - npm (or another package manager) - A GitHub personal access token with access to all the repositories -## Configuration +## ⚙️ Configuration Repoverse requires a configuration object to specify the repositories to sync and other settings. Here's an example: @@ -42,8 +46,8 @@ Repoverse requires a configuration object to specify the repositories to sync an { "owner": "example-user", "repo": "repo-to-sync-1", - "path": "models/", - "branch": "dev" + "path": "models/", + "branch": "dev" }, { "owner": "example-user", @@ -57,8 +61,7 @@ Repoverse requires a configuration object to specify the repositories to sync an } ``` - -## **Installation** +## 📦 Installation To install `repoverse`, run the following command: @@ -66,11 +69,11 @@ To install `repoverse`, run the following command: npm install repoverse ``` -## **Usage** +## 🚀 Usage `repoverse` can be used in two different ways: -### **1. As a GitHub Action** +### As a GitHub Action Automate synchronization based on GitHub push events: @@ -79,7 +82,9 @@ Automate synchronization based on GitHub push events: - Use the `repoverse` action within your job to perform synchronization. Example workflow: + - Make sure that the `REPOVERSE_CONFIG` secret is created in your repository's settings, containing the synchronization configuration in `JSON` format. + ```yaml name: Repository Sync @@ -91,7 +96,7 @@ on: - 'path/to/sync/**' jobs: - repo-sync: + repoverse: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -119,7 +124,7 @@ jobs: " ``` -### **2. Programmatically in Your Code** +### Programmatically in Your Code Synchronize code on-demand or with more control: @@ -162,24 +167,23 @@ const commits = [ }, ]; -repoverse.synchronize(sourceRepo, commits) +repoverse + .synchronize(sourceRepo, commits) .then(() => console.log('Synchronization successful')) .catch(error => console.error('Synchronization failed:', error)); ``` -## Workflow +## 🔄 Workflow - Repoverse identifies changes in a source repository(one of the repo in config). - Creates corresponding branches (prefixed with a configured value) in target(reamining) repositories. - Applies the changes to those branches and commits them. - Raises pull requests in the target repositories, inviting review and approval before merging. -## **Contributing** +## 🤝 Contributing Contributions to `repoverse` are highly encouraged! If you have a suggestion, fix, or enhancement, please open an issue or a pull request. Help us make repository synchronization seamless for developers. -## License +## 📄 License Repoverse is licensed under the MIT License. - - diff --git a/package.json b/package.json index 1e46c89..c6c6ff2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "repoverse", - "version": "0.0.1-development", + "version": "0.0.2-development", "description": "Tool for syncronising common code across multiple repositories", "main": "./lib/index.js", "files": [ diff --git a/src/services/repoSync.service.ts b/src/Repoverse.ts similarity index 97% rename from src/services/repoSync.service.ts rename to src/Repoverse.ts index 9e481f0..242adab 100644 --- a/src/services/repoSync.service.ts +++ b/src/Repoverse.ts @@ -1,6 +1,6 @@ import { Octokit } from '@octokit/rest'; -import { GitHubCommitInfo } from '../types/github'; -import { BlobData, CommitData } from '../types/octokit'; +import { GitHubCommitInfo } from './types/github'; +import { BlobData, CommitData } from './types/octokit'; interface RepositoryConfig { owner: string; @@ -16,16 +16,15 @@ interface CommitDataCache { }; } -class RepoSyncService { +class Repoverse { private config: { repositories: RepositoryConfig[]; syncBranchPrefix: string; accessToken: string; }; private octokit: Octokit; - repoSyncService: any; - constructor(config: typeof RepoSyncService.prototype.config) { + constructor(config: typeof Repoverse.prototype.config) { this.config = config; this.octokit = new Octokit({ auth: this.config.accessToken, @@ -35,7 +34,7 @@ class RepoSyncService { /** * Process the action of syncing the commits from one repository to rest of the repositories */ - public async execute( + public async synchronize( sourceRepository: string, commits: GitHubCommitInfo[] ): Promise { @@ -74,7 +73,7 @@ class RepoSyncService { } } - public getConfig(): typeof RepoSyncService.prototype.config { + public getConfig(): typeof Repoverse.prototype.config { return this.config; } @@ -478,4 +477,4 @@ class RepoSyncService { } } -export default RepoSyncService; +export default Repoverse; diff --git a/src/index.ts b/src/index.ts index cc0b5cf..f9b5642 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,2 @@ -import RepoSyncService from './services/repoSync.service'; -export default RepoSyncService; +import Repoverse from './Repoverse'; +export default Repoverse; diff --git a/test/index.spec.ts b/test/index.spec.ts index 6e457c2..be78134 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -1,6 +1,6 @@ import { faker } from '@faker-js/faker'; import { Octokit } from '@octokit/rest'; -import RepoSyncService from '../src'; +import Repoverse from '../src'; const mocks = { repos: { @@ -87,26 +87,26 @@ function generateFakeConfig() { }; } -describe('RepoSyncService', () => { +describe('Repoverse', () => { const exampleConfig = generateFakeConfig(); describe('constructor', () => { it('should create an instance with the given configuration', () => { - const repoSyncService = new RepoSyncService(exampleConfig); - expect(repoSyncService).toBeDefined(); + const repoverse = new Repoverse(exampleConfig); + expect(repoverse).toBeDefined(); // Check if the config is set correctly - expect(repoSyncService.getConfig()).toEqual(exampleConfig); + expect(repoverse.getConfig()).toEqual(exampleConfig); // Check if octokit has been initialized with the accessToken expect(Octokit).toHaveBeenCalledWith({ auth: exampleConfig.accessToken }); }); }); - describe('execute', () => { - let repoSyncService: RepoSyncService; + describe('synchronize', () => { + let repoverse: Repoverse; const exampleConfig = generateFakeConfig(); beforeEach(() => { - repoSyncService = new RepoSyncService(exampleConfig); + repoverse = new Repoverse(exampleConfig); // Reset all mocks jest.clearAllMocks(); }); @@ -158,7 +158,7 @@ describe('RepoSyncService', () => { } }); - await repoSyncService.execute(sourceRepository, commits); + await repoverse.synchronize(sourceRepository, commits); const targetRepositoryConfigs = exampleConfig.repositories.filter( (_, index) => index !== sourceRepositoryIndex @@ -248,7 +248,7 @@ describe('RepoSyncService', () => { const invalidSourceRepository = 'invalidformat'; const commits = [generateFakeGitHubCommitInfo({})]; await expect( - repoSyncService.execute(invalidSourceRepository, commits) + repoverse.synchronize(invalidSourceRepository, commits) ).rejects.toThrow( "The source repository must be in the format 'owner/repo'" ); @@ -258,7 +258,7 @@ describe('RepoSyncService', () => { const nonConfiguredRepo = 'nonexistent/owner-repo'; const commits = [generateFakeGitHubCommitInfo({})]; await expect( - repoSyncService.execute(nonConfiguredRepo, commits) + repoverse.synchronize(nonConfiguredRepo, commits) ).rejects.toThrow( 'Source repository nonexistent/owner-repo is not in the list of repositories to sync' );