From 897eb73cd735cfab9d11cf1c4e021521000469f7 Mon Sep 17 00:00:00 2001 From: di-sukharev Date: Wed, 5 Jul 2023 15:11:17 +0800 Subject: [PATCH] feat(README.md): add GitHub Hackathon winner badge to project description docs(README.md): restructure README, move CLI setup instructions to top for better visibility feat(cli.cjs): extend file exclusion list in 'getDiff' to include image files for better performance refactor(config.ts): add more model options in configValidators for flexibility refactor(config.ts): set default model to 'gpt-3.5-turbo-16k' for better performance refactor(git.ts): simplify 'getCoreHooksPath' function for readability feat(git.ts): extend file exclusion list in 'getDiff' to include image files for better performance --- .github/github-mark-white.png | Bin 0 -> 4837 bytes README.md | 53 +++++++++++++++++++--------------- out/cli.cjs | 9 ++---- src/commands/config.ts | 35 ++++++++++++++-------- src/utils/git.ts | 20 ++++++++----- 5 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 .github/github-mark-white.png diff --git a/.github/github-mark-white.png b/.github/github-mark-white.png new file mode 100644 index 0000000000000000000000000000000000000000..50b81752278d084ba9d449fff25f4051df162b0f GIT binary patch literal 4837 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 096d1b0..d692381 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,12 @@ OpenCommit logo

OpenCommit

Follow the bird -

Auto-generate meaningful commits in 1 second

Killing lame commits with AI 🤯🔫

Current version +

🪩 Winner of GitHub 2023 HACKATHON +

--- @@ -18,6 +19,26 @@ All the commits in this repo are authored by OpenCommit — look at [the commits](https://github.com/di-sukharev/opencommit/commit/eae7618d575ee8d2e9fff5de56da79d40c4bc5fc) to see how OpenCommit works. Emojis and long commit descriptions are configurable. +## Setup OpenCommit as a CLI tool + +You can use OpenCommit by simply running it via the CLI like this `oco`. 2 seconds and your staged changes are committed with a meaningful message. + +1. Install OpenCommit globally to use in any repository: + + ```sh + npm install -g opencommit + ``` + +2. Get your API key from [OpenAI](https://platform.openai.com/account/api-keys). Make sure that you add your payment details, so the API works. + +3. Set the key to OpenCommit config: + + ```sh + opencommit config set OCO_OPENAI_API_KEY= + ``` + + Your API key is stored locally in the `~/.opencommit` config file. + ## Setup OpenCommit as a GitHub Action 🔥 OpenCommit is now available as a GitHub Action which automatically improves all new commits messages when you push to remote! @@ -74,26 +95,6 @@ Make sure you exclude public collaboration branches (`main`, `dev`, `etc`) in `b Interactive rebase (`rebase -i`) changes commits' SHA, so the commit history in remote becomes different from your local branch history. This is okay if you work on the branch alone, but may be inconvenient for other collaborators. -## Setup OpenCommit as a CLI tool - -You can use OpenCommit by simply running it via the CLI like this `oco`. 2 seconds and your staged changes are committed with a meaningful message. - -1. Install OpenCommit globally to use in any repository: - - ```sh - npm install -g opencommit - ``` - -2. Get your API key from [OpenAI](https://platform.openai.com/account/api-keys). Make sure that you add your payment details, so the API works. - -3. Set the key to OpenCommit config: - - ```sh - opencommit config set OCO_OPENAI_API_KEY= - ``` - - Your API key is stored locally in the `~/.opencommit` config file. - ## Usage You can call OpenCommit directly to generate a commit message for your staged changes: @@ -149,9 +150,9 @@ To remove preface emojis: oco config set OCO_EMOJI=false ``` -### Switch to GPT-4 +### Switch to GPT-4 or other models -By default, OpenCommit uses GPT-3.5-turbo (ChatGPT). +By default, OpenCommit uses `gpt-3.5-turbo-16k` model. You may switch to GPT-4 which performs better, but costs ~x15 times more 🤠 @@ -159,6 +160,12 @@ You may switch to GPT-4 which performs better, but costs ~x15 times more 🤠 oco config set OCO_MODEL=gpt-4 ``` +or for as a cheaper option: + +```sh +oco config set OCO_MODEL=gpt-3.5-turbo +``` + Make sure that you spell it `gpt-4` (lowercase) and that you have API access to the 4th model. Even if you have ChatGPT+, that doesn't necessarily mean that you have API access to GPT-4. ## Locale configuration diff --git a/out/cli.cjs b/out/cli.cjs index df2dd58..2ceca63 100755 --- a/out/cli.cjs +++ b/out/cli.cjs @@ -18717,10 +18717,7 @@ var getOpenCommitIgnore = () => { return ig; }; var getCoreHooksPath = async () => { - const { stdout } = await execa("git", [ - "config", - "core.hooksPath" - ]); + const { stdout } = await execa("git", ["config", "core.hooksPath"]); return stdout; }; var getStagedFiles = async () => { @@ -18764,11 +18761,11 @@ var gitAdd = async ({ files }) => { }; var getDiff = async ({ files }) => { const lockFiles = files.filter( - (file) => file.includes(".lock") || file.includes("-lock.") + (file) => file.includes(".lock") || file.includes("-lock.") || file.includes(".svg") || file.includes(".png") || file.includes(".jpg") || file.includes(".jpeg") || file.includes(".webp") || file.includes(".gif") ); if (lockFiles.length) { ce( - `Some files are '.lock' files which are excluded by default from 'git diff'. No commit messages are generated for this files: + `Some files are excluded by default from 'git diff'. No commit messages are generated for this files: ${lockFiles.join( "\n" )}` diff --git a/src/commands/config.ts b/src/commands/config.ts index 830d093..5cea43d 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -1,10 +1,10 @@ -import { command } from 'cleye'; -import { join as pathJoin } from 'path'; -import { parse as iniParse, stringify as iniStringify } from 'ini'; -import { existsSync, writeFileSync, readFileSync } from 'fs'; -import { homedir } from 'os'; import { intro, outro } from '@clack/prompts'; import chalk from 'chalk'; +import { command } from 'cleye'; +import { existsSync, readFileSync, writeFileSync } from 'fs'; +import { parse as iniParse, stringify as iniStringify } from 'ini'; +import { homedir } from 'os'; +import { join as pathJoin } from 'path'; import { COMMANDS } from '../CommandsEnum'; import { getI18nLocal } from '../i18n'; @@ -20,7 +20,7 @@ export enum CONFIG_KEYS { OCO_EMOJI = 'OCO_EMOJI', OCO_MODEL = 'OCO_MODEL', OCO_LANGUAGE = 'OCO_LANGUAGE', - OCO_MESSAGE_TEMPLATE_PLACEHOLDER = 'OCO_MESSAGE_TEMPLATE_PLACEHOLDER', + OCO_MESSAGE_TEMPLATE_PLACEHOLDER = 'OCO_MESSAGE_TEMPLATE_PLACEHOLDER' } export const DEFAULT_MODEL_TOKEN_LIMIT = 4096; @@ -121,8 +121,13 @@ export const configValidators = { [CONFIG_KEYS.OCO_MODEL](value: any) { validateConfig( CONFIG_KEYS.OCO_MODEL, - ['gpt-3.5-turbo', 'gpt-4','gpt-3.5-turbo-16k'].includes(value), - `${value} is not supported yet, use 'gpt-4' or 'gpt-3.5-turbo' (default)` + [ + 'gpt-3.5-turbo', + 'gpt-4', + 'gpt-3.5-turbo-16k', + 'gpt-3.5-turbo-0613' + ].includes(value), + `${value} is not supported yet, use 'gpt-4', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-0613' or 'gpt-3.5-turbo' (default)` ); return value; }, @@ -145,13 +150,16 @@ const configPath = pathJoin(homedir(), '.opencommit'); export const getConfig = (): ConfigType | null => { const configFromEnv = { OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY, - OCO_OPENAI_MAX_TOKENS: process.env.OCO_OPENAI_MAX_TOKENS ? Number(process.env.OCO_OPENAI_MAX_TOKENS) : undefined, + OCO_OPENAI_MAX_TOKENS: process.env.OCO_OPENAI_MAX_TOKENS + ? Number(process.env.OCO_OPENAI_MAX_TOKENS) + : undefined, OCO_OPENAI_BASE_PATH: process.env.OCO_OPENAI_BASE_PATH, OCO_DESCRIPTION: process.env.OCO_DESCRIPTION === 'true' ? true : false, OCO_EMOJI: process.env.OCO_EMOJI === 'true' ? true : false, - OCO_MODEL: process.env.OCO_MODEL || 'gpt-3.5-turbo', + OCO_MODEL: process.env.OCO_MODEL || 'gpt-3.5-turbo-16k', OCO_LANGUAGE: process.env.OCO_LANGUAGE || 'en', - OCO_MESSAGE_TEMPLATE_PLACEHOLDER: process.env.OCO_MESSAGE_TEMPLATE_PLACEHOLDER || '$msg' + OCO_MESSAGE_TEMPLATE_PLACEHOLDER: + process.env.OCO_MESSAGE_TEMPLATE_PLACEHOLDER || '$msg' }; const configExists = existsSync(configPath); @@ -161,7 +169,10 @@ export const getConfig = (): ConfigType | null => { const config = iniParse(configFile); for (const configKey of Object.keys(config)) { - if (!config[configKey] || ['null', 'undefined'].includes(config[configKey])) { + if ( + !config[configKey] || + ['null', 'undefined'].includes(config[configKey]) + ) { config[configKey] = undefined; continue; } diff --git a/src/utils/git.ts b/src/utils/git.ts index f8510df..3acd79a 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -25,13 +25,11 @@ export const getOpenCommitIgnore = (): Ignore => { return ig; }; -export const getCoreHooksPath = async(): Promise => { - const { stdout } = await execa('git', [ - 'config', - 'core.hooksPath']); +export const getCoreHooksPath = async (): Promise => { + const { stdout } = await execa('git', ['config', 'core.hooksPath']); return stdout; -} +}; export const getStagedFiles = async (): Promise => { const { stdout: gitDir } = await execa('git', [ @@ -83,12 +81,20 @@ export const gitAdd = async ({ files }: { files: string[] }) => { export const getDiff = async ({ files }: { files: string[] }) => { const lockFiles = files.filter( - (file) => file.includes('.lock') || file.includes('-lock.') + (file) => + file.includes('.lock') || + file.includes('-lock.') || + file.includes('.svg') || + file.includes('.png') || + file.includes('.jpg') || + file.includes('.jpeg') || + file.includes('.webp') || + file.includes('.gif') ); if (lockFiles.length) { outro( - `Some files are '.lock' files which are excluded by default from 'git diff'. No commit messages are generated for this files:\n${lockFiles.join( + `Some files are excluded by default from 'git diff'. No commit messages are generated for this files:\n${lockFiles.join( '\n' )}` );