Giter Club home page Giter Club logo

github-label-sync's Introduction

GitHub Label Sync NPM version MIT licensed

Synchronise your GitHub labels with as few destructive operations as possible โ€“ similar labels get renamed.

Table Of Contents

Requirements

You'll need Node.js 12+ installed to run GitHub Label Sync. You'll also need a GitHub access token ready so that the tool will have access to your repositories. You can generate an access token here, be sure to allow the "repo" scope.

Command-Line Interface

Install GitHub Label Sync globally with npm:

npm install -g github-label-sync

This installs the github-label-sync command-line tool:

Usage: github-label-sync [options] <repository>

Options:

  -h, --help                  output usage information
  -V, --version               output the version number
  -a, --access-token <token>  a GitHub access token (also settable with a GITHUB_ACCESS_TOKEN environment variable)
  -l, --labels <path>         the path or URL to look for the label configuration in. Default: labels.json
  -d, --dry-run               calculate the required label changes but do not apply them
  -A, --allow-added-labels    allow additional labels in the repo, and don't delete them

Run GitHub Label Sync on a repo (reading label data from a local labels.json):

github-label-sync --access-token xxxxxx myname/myrepo

Run GitHub Label Sync using a different label config file:

github-label-sync --access-token xxxxxx --labels my-labels.json myname/myrepo

Label config file can be also specified as YAML:

github-label-sync --access-token xxxxxx --labels my-labels.yml myname/myrepo

Perform a dry run, only making safe "read" requests to the GitHub API:

github-label-sync --access-token xxxxxx --dry-run myname/myrepo

Normally any additional labels found on the repo are deleted. Run GitHub label sync and ignore additional labels, leaving them as-is:

github-label-sync --access-token xxxxxx --allow-added-labels myname/myrepo

JavaScript Interface

Install GitHub Label Sync with npm or add to your package.json:

npm install github-label-sync

Require GitHub Label Sync:

var githubLabelSync = require('github-label-sync');

The githubLabelSync function returns a promise that resolves to a JSON diff between the labels found on GitHub, and the labels in your label config.

Run GitHub Label Sync on a repo (passing in options):

githubLabelSync({
	accessToken: 'xxxxxx',
	repo: 'myname/myrepo',
	labels: [
		// label config
	]
}).then((diff) => {
	console.log(diff);
});

The available options are documented below.

When the promise resolves successfully, its value will be set to a diff between the labels found on GitHub, and the labels in your label config. The diff will look like this:

[
	// This is a "missing" diff, it indicates that a label
	// present in your local config is not present on GitHub.
	{
		name: 'local-label-name',
		type: 'missing',
		actual: null,
		expected: {
			name: 'local-label-name',
			color: 'ff0000'
		}
	},
	// This is a "changed" diff, it indicates that a label
	// present on GitHub has diverged from your local config.
	// This could mean that either somebody has modified the
	// label manually on GitHub, or the local config has
	// been updated.
	{
		name: 'local-label-name',
		type: 'changed',
		actual: {
			name: 'remote-label-name',
			color: '00ff00'
		},
		expected: {
			name: 'local-label-name',
			color: 'ff0000'
		}
	},
	// This is an "added" diff, it indicates that a label
	// is present on GitHub but not in your local config.
	{
		name: 'remote-label-name',
		type: 'added',
		actual: {
			name: 'remote-label-name',
			color: 'ff0000'
		},
		expected: null
	}
]

Label Config File

The labels to sync with are defined as an array in either JavaScript, JSON or YAML. The array must contain only label objects, which look like this:

As JSON:

{
	"name": "mylabel",
	"color": "ff0000",
	"aliases": [],
	"description": "optional description",
	"delete": false
}

As YAML:

- name: mylabel
  color: "ff0000"
  aliases: []
  description: optional description
  delete: false
  • The name property refers to the label name.
  • The color property should be a hex code, with or without the leading #.
  • The delete property is optional. When set to true, matches for this label will always be deleted. This can be used in conjunction with allowAddedLabels to flag specific labels for deletion while leaving non-specified labels intact. Defaults to false.

The aliases property is optional. When GitHub Label Sync is determining whether to update or delete/create a label it will use the aliases property to prevent used labels from being deleted.

For example, given the following config, GitHub Label Sync will look for labels on GitHub named either "feature" or "enhancement" then update them to match the newer config rather than deleting them.

{
	"name": "type: feature",
	"color": "00ff00",
	"aliases": [
		"enhancement",
		"feature"
	]
}

You can find a full example label configuration in this repository (JSON / YAML).

Configuration

accessToken

String. The GitHub access token to use when fetching/updating labels. This must be an access token that has permission to write to the repository you want to sync labels with.

githubLabelSync({
	accessToken: 'xxxxxx'
});

On the command-line this can be set with either the access-token flag or the GITHUB_ACCESS_TOKEN environment variable:

github-label-sync --access-token xxxxxx
GITHUB_ACCESS_TOKEN=xxxxxx github-label-sync

allowAddedLabels

Boolean. Whether to allow labels on GitHub which are not specified in your label config. If true, they are allowed and will be left alone. If false, they will be deleted. Default: false.

githubLabelSync({
	allowAddedLabels: true
});

The command-line allow-added-labels flag corresponds to this option:

github-label-sync --allow-added-labels

dryRun

Boolean. Whether to perform a dry run, only making safe "read" requests to the GitHub API. If true, label changes will not be executed on GitHub. If false, label changes will be executed. Default: false.

githubLabelSync({
	dryRun: true
});

The command-line dry-run flag corresponds to this option:

github-label-sync --dry-run

labels

Array. Your label configuration. See the section on label config file.

githubLabelSync({
	labels: []
});

On the command-line this can be set with the labels flag which should point to a JSON or YAML file.

repo

String. The GitHub repo to sync labels to. This should include the user and repo names, e.g. "Financial-Times/ft-origami".

githubLabelSync({
	repo: 'Financial-Times/ft-origami'
});

The command-line accepts the repo as an argument after the options:

github-label-sync Financial-Times/ft-origami

Contributing

To contribute to GitHub Label Sync, clone this repo locally and commit your code on a separate branch.

Please write unit tests for your code, and check that everything works by running the following before opening a pull-request:

npm test               # run the full test suite
npm run lint           # run the linter
npm run test-unit      # run the unit tests
npm run test-coverage  # run the unit tests with coverage reporting

License

This software is published by the Financial Times under the MIT licence.

github-label-sync's People

Contributors

36degrees avatar callahad avatar carlo-quinonez avatar chasenlehara avatar chee avatar danielwerg avatar dependabot-preview[bot] avatar dependabot[bot] avatar gvonkoss avatar jakechampion avatar jurooravec avatar kenperkins avatar lismi avatar notlee avatar o0 avatar owenvoke avatar per1234 avatar rowanmanning avatar sgnn7 avatar snyk-bot avatar srealmoreno avatar thomas-mcdonald avatar turbo87 avatar vandyand avatar wheresrhys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

github-label-sync's Issues

Add more validations to labels name and description

What

The Github api has some validations besides character length.

  • Label Name:

    1. Must contain more than native emojis

      When using a name that only contains emojis, this error occurs:
      image

  • Description:

    1. 4-byte characters are not allowed

      image

Details

my labels.yml

- name: ๐Ÿ˜€ ๐Ÿ˜ƒ ๐Ÿ˜„ ๐Ÿ˜
  color: "536266"
  description: This is a name only contains emojis

- name: bug ๐Ÿž
  color: d73a4a
  description: 
    This is a description that contains emojis 4-byte unicode ๐Ÿž

With that file, the script will fail with the following message:

GitHub Error:
POST /repos/srealmoreno/test-label-sync/labels
422: Validation Failed

It would be great if you showed the error with --dry-run option.

Similar issues #42 #135

Support for description

That would be nice.

Label description is a new GitHub feature: https://blog.github.com/2018-02-22-label-improvements-emoji-descriptions-and-more/

Add descriptions to your labels to provide even more context and help your contributors apply the right ones to their issues or pull requests. Descriptions will appear when you hover your mouse over labels around GitHub.

API documentation

Related to popomore/github-labels#26

Enable multiple label files

I'd love to be able run with multiple labels files, but not using the --allow-added-labels flag:

github-label-sync --access-token xxxxx  --labels labels-common.json --labels labels-specific.json myorg/myrepo

This would allow me to have a standard set of labels I apply across repos, and repo-specific labeling, all in one execution, having confidence it can merge before validating, and then run as one process.

Change dependencies version

When I run npm install on this repository npm shows a message that there're some vulnerabilities in dependencies. Some of them are important or even critical. Running npm audit fix --force should solve this issue by moving all the dependencies versions further to the point where all of them are safe.

npm-install

npm-audit

Error: API responded with 307 status

What

When the GitHub API returns a 307 (temporary redirect), an error is thrown:

Error: API responded with 307 status
    at /Users/rjackson/.npm/_npx/86941/lib/node_modules/create-rwjblue-release-it-setup/node_modules/github-label-sync/lib/github-label-api.js:88:20
    at Client.errorHandle (/Users/rjackson/.npm/_npx/86941/lib/node_modules/create-rwjblue-release-it-setup/node_modules/octonode/lib/octonode/client.js:206:14)
    at Request._callback (/Users/rjackson/.npm/_npx/86941/lib/node_modules/create-rwjblue-release-it-setup/node_modules/octonode/lib/octonode/client.js:338:24)
    at Request.self.callback (/Users/rjackson/.npm/_npx/86941/lib/node_modules/create-rwjblue-release-it-setup/node_modules/request/request.js:185:22)
    at Request.emit (events.js:196:13)
    at Request.<anonymous> (/Users/rjackson/.npm/_npx/86941/lib/node_modules/create-rwjblue-release-it-setup/node_modules/request/request.js:1161:10)
    at Request.emit (events.js:196:13)
    at IncomingMessage.<anonymous> (/Users/rjackson/.npm/_npx/86941/lib/node_modules/create-rwjblue-release-it-setup/node_modules/request/request.js:1083:12)
    at Object.onceWrapper (events.js:284:20)

Details

Per the GitHub V3 API Documentation:

API v3 uses HTTP redirection where appropriate. Clients should assume that any request may result in a redirection. Receiving an HTTP redirection is not an error and clients should follow that redirect. Redirect responses will have a Location header field which contains the URI of the resource to which the client should repeat the requests.

Instead of throwing an error here:

if (status !== 200) {
return reject(new Error(`API responded with ${status} status`));
}

We should use the Location header and make another request.

Would you accept to migrate from octonode?

Hey! ๐Ÿ‘‹

The library octonode installs bluebird and request packages.

Since request is deprecated, it triggers a warning every time we install it.
It is also really heavy.

I believe bluebird is not useful anymore since any JavaScript runtimes support Promises.

GitHub made a library to request their REST or their GraphQL endpoint.

I propose that we switch to one of those libraries instead of relying on octonode.

Merging labels doesn't seem to work

If the repo contains labels a and b and my config defines label a with a different color and aliases: ['b'] then the script will only change the color of a, but not touch b at all.

This is probably a limitation of the underlying API, but maybe it is possible to work around it? I'm not sure if that is viable, but reassigning all issues with label b to label a and then delete label b might be an option ๐Ÿค”

YAML support

It would be great if additionally to supporting .json files, YAML files (i.e. .yml and .yaml) would also be supported. This should be fairly simple to add.

Support for GitLab

While the project name suggests that this is only meant to be used with GitHub it would be quite nice to make it work with GitLab too. Since labels work roughly the same in both platforms it shouldn't be that difficult to do, but I guess then we would likely have to rename the project.

If this sounds interesting to you please let me know then I'll start working on this.

/cc @rowanmanning

Validation Failed error when there is more than one alias

Steps to reproduce:

  1. Have a repo that contains the labels "Broken Tests" and "Tests".
  2. Create a label config file and include the sample below.
  3. Run the script.
  4. Run the script again.

Sample label config:

    {
        "name": "category: tests",
        "color": "3e4b9e",
        "aliases": [
            "Broken Tests",
            "Tests"
        ],
        "description": "Related to any kind of testing."
    }

Result: the second alias is never updated and the following error appears if the script has been executed at least once before:

GitHub Error:
PATCH /repos/myname/myrepo/labels/Tests
422: Validation Failed

Tested with github-label-sync 2.0.0 using --allow-added-labels on macOS 10.15.6 with Node.js v16.0.0 (also tried with v12.22.1).

Validate label description length

What

It'd be neat if the script was able to validate label description lengths.

Details

Currently, if you have a label with a description greater than 100 characters (I think), the GitHub API will reject it, causing the script to exit in the middle of syncing with:

GitHub Error:
PATCH /repos/alphagov/design-system-team-internal/labels/effort%3A%20days
422: Validation Failed

Because this validation is happening when making the API requests, it won't be picked up when running github-label-sync with the --dry-run flag.

I understand you may not wish to implement validation in the script, in which case it'd be great if the validation errors were outputted as well as the 422: Validation Failed, so that the user understands what needs fixing.

Additional information

Thank you for open-sourcing this โ€“ we're trying it out over at https://github.com/alphagov/design-system-team-labels ๐Ÿ™Œ

Fetching labels from GitHub -> label.toLowerCase is not a function

[Bug]

What

At the Fetching labels from GitHub step,
The node app raise an error TypeError: label.toLowerCase is not a function.

Details

You can check the repository that contain all my work on the branch named change-techno here
There is a YAML file that contain the labels I use.

I tried to apply them with the following command : (labels.yaml is a file located in /home/user/labels.yaml)

github-label-sync --access-token 7******1  --labels ./labels.yaml shiipou/labelset

Here the error raised :

Syncing labels for "shiipou/labelset"
Fetching labels from GitHub
TypeError: label.toLowerCase is not a function
    at /Users/flavien.cadet/.nvm/versions/node/v12.18.3/lib/node_modules/github-label-sync/lib/calculate-label-diff.js:15:78
    at Array.map (<anonymous>)
    at /Users/flavien.cadet/.nvm/versions/node/v12.18.3/lib/node_modules/github-label-sync/lib/calculate-label-diff.js:15:59
    at Array.filter (<anonymous>)
    at /Users/flavien.cadet/.nvm/versions/node/v12.18.3/lib/node_modules/github-label-sync/lib/calculate-label-diff.js:11:33
    at Array.forEach (<anonymous>)
    at calculateLabelDiff (/Users/flavien.cadet/.nvm/versions/node/v12.18.3/lib/node_modules/github-label-sync/lib/calculate-label-diff.js:8:19)
    at /Users/flavien.cadet/.nvm/versions/node/v12.18.3/lib/node_modules/github-label-sync/lib/github-label-sync.js:41:16
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

URL for POST broken?

I get the following when the tool tries to adjust the labels:

GitHub Error:
POST /repos/martinstreicher/test/labels
404: Not Found

Add an option to run for all repositories in a user or organisation

What

I sometimes find myself manually running github-label-sync on each of my repositories when I update my configuration file. It would be useful to be able to do that automatically.

Details

A command-line option such as --all-repos <user or org>.

Essentially, just fetch a list of repositories within the given user or organisation and loop through them, running the program for each.

Provide a config schema for categorization of labels

I've been thinking about my label use cases, and I find that on most of my repositories, I've gotten into the habit of a label schema if you will. Things like type/xxxx or area/yyyy, status/zzz, and so on.

I'm trying to think of a forwards compatible mode where you could adorn a label with a property, and if that property matches an optional input file schema, would get color and prefix from the input schema.

Here's an off-the-cuff example:

{
  "config": {
    "delimiter": "/",
    "allow-added-labels": false,
    "categories": [
      {
        "name": "type",
        "delimiter": "@",
        "color": "aaccff",
        "aliases": [ "type:", "type=", "type/" ]
      },
      {
        "name": "status",
        "color": "3377aa",
        "aliases": [ "status:" ]
      }
    ]
  }  
}

Then, in my label file, we'd have a new optional property called category:

[
	{
		"name": "bug",
                "category": "type",
		"aliases": [
			"bug"
		]
	},
	{
		"name": "breaking",
		"category": "type",
		"aliases": [
			"breaking",
			"breaking-change"
		]
	},
	{
		"name": "wontfix",
                "category": "status",
		"aliases": [
			"wont-fix",
			"won't fix",
			"wont fix"
		]
	}
]

The merged labels would look like this:

[
	{
		"name": "type@bug",
                "color": "aaccff",
		"aliases": [
			"bug",
			"type:bug",
			"type/bug",
			"type=bug"
		]
	},
	{
		"name": "type@breaking",
		"color": "aaccff",
		"aliases": [
			"breaking",
			"breaking-change",
			"type:breaking",
			"type:breaking-change",
			"type/breaking",
			"type/breaking-change",
			"type=breaking",
			"type=breaking-change",
		]
	},
	{
		"name": "status/wontfix",
                "color": "3377aa",
		"aliases": [
			"wont-fix",
			"won't fix",
			"wont fix"
			"status:wont-fix",
			"status:won't fix",
			"status:wont fix"
		]
	}
]

I would perhaps call this like so:

$ github-label-sync --config myconfig.json --labels source1.json --labels source2.json
Loading myconfig.json
  allow-added-labels: false
  delimiter: "/"

Thoughts?

Support for GitHub Enterprise

I would like to add a configuration option to use GitHub Enterprise instead of GitHub. Adding support is trivial since you're using octonode by passing in hostname as an option during initialization. For example:

class ApiClient {

	constructor (accessToken) {
		this.apiClient = github.client(accessToken, { hostname: 'ghe.example.com/api/v3' });
	}
...
}

How would you like this option passed in? (e.g. --hostname option, GITHUB_HOSTNAME environment variable, etc.)

Validate the labels before execution

I had non-valid color specified in my YAML and your tool executed without any validation which resulted in partly executed synchronization as GitHub rejected to accept the label with the invalid color and thrown error:

GitHub Error:
PATCH /repos/ethersphere/bee-js/labels/help%20wanted
422: Validation Failed

Feature Request: Allow specifying --labels more than once

What

It would be great if the --labels flag could be specified more than once, with all occurrences being merged together and duplicate keys from later occurrences overwriting earlier occurrences.

Details

This would be helpful when using the syncer in larger organization contexts. A common org-wide set of labels could be specified centrally and each repository could specify dedicated overwrites.

please make -A the default setting

What

-A should be defaulted to true - destructive actions should not happen by default

Details

I accidentally forgot -A and wiped all of my labels + correlations to issues, and voila, they're gone.

feat: delete labels

Feature request:

What

Sync is cool, but if I have many repositories with different labels and I want to automate:

  • list no1) the creation of a shared list of labels
  • list no2) the removal of a shared list of legacy labels

it is not possible by using the CLI - because it would delete all the labels not listed in the list no1

Details

It would be great if the labels.json could support an additional parameter:

{
  "name": "npm-minor",
  "delete": true
}

When this label is found:

  • if the github repository has the label: it will be deleted
  • if the github repository does not contain the label: it will be ignored

Support for updating

Feature Request

What

It'd be great if we could use the update api in order to change existing labels. At present if we don't allow changes to existing labels. For example renaming one in the labels.json file would lead to deletion of the old and creation of the new which subsequently removes the original label from any issues to which it was assigned.

Details

What prompted the request
I renamed an issue in my labels.json under the assumption (foolishly) that it would apply the change as an update to the existing label but obviously it didn't and it created a new label and removed the label from the existing issues.

Obviously it couldn't rename the issue without me providing the old name and the new name so i don't really know why I expected it.

Given that the API allows for PATCHing labels using the :current_name in the URL, perhaps if we were to provide the :current_name with the label in labels.json we could update that label rather than deleting/adding.

For example

    {
        "name": "bug :bug:",
        "color": "9b221b",
        "aliases": [":bug:"],
        "current_name": "bug"
    },

I have a script which runs periodically and on ci on a label change which keeps all of the repos with issue support in sync so I don't really want to enable allow-added-labels as that'll allow the repos to get out of sync.

Support leading `#` in hexadecimal color strings

Feature: Support the leading # when specifying label colors

What

Currently colors are specified in the same format that's expected by the GitHub API - without a leading #.

Details

I'd like to see the color preview in VSCode when I'm editing the yaml files. There are plugins for VSCode
that automatically colorize hex color strings that start with a #.

image

It would be easy to strip a leading # from the color string if present.

Additional information

I can submit a PR for this.

Feature Request: Download labels via CLI

Feature Request

Using the CLI, I would like to be able to download the existing set of labels from a repository or from the organization's repository defaults (https://github.com/organizations/<org>/settings/repository-defaults) to use as the basis for the labels to set. It is fine with me if the CLI would simply output the list in a format the CLI would accept as input, allowing me to then edit it. I would prefer the option to have it emitted in JSON or YAML.

Details

We consider the GitHub organization's Repository Defaults to be the "source of truth" and like that we can update it via a nice UI. We would like to use github-label-sync to propagate changes to the defaults to any existing repositories in an automated way by reading the defaults and applying them.

In another org, I would like to download the defaults, manually remove outdated labels, and then sync them.

As it is, I have to manually create a configuration that matches the defaults, which is tedious and error prone.

# Read org defaults and output as YAML
github-label-sync --read-only --format yaml myname

# Read repo labels and output as JSON
github-label-sync --read-only  myname/repo

Throw when not passing `labels`.

Invoking the function without passing the labels property, automatically assumes no labels, so it kills all existing labels in the target repository. Would be great if it threw an error instead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.