Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: V3 #879

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .prettierrc.cjs → .prettierrc.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
singleQuote: true,
trailingComma: 'es5',
printWidth: 100,
Expand Down
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,17 @@ hooks:
should_migrate:
- ls .eslintrc # Check that this file actually exists in the repo
- git log -1 --format=%cd | grep 2018 --silent # Only migrate things that have seen commits in 2018
should_create_issue:
- node $SHEPHERD_MIGRATION_DIR/should_create_issue.js
post_checkout: npm install
apply: mv .eslintrc .eslintrc.json
pr_message: echo 'Hey! This PR renames `.eslintrc` to `.eslintrc.json`'
issues:
title: 'this is my first updated issue'
description: 'this is my first updated issue'
labels: ['ENHANCEMENT', 'BUG']
state: closed
state_reason: completed
```

### Fields
Expand Down Expand Up @@ -113,6 +121,11 @@ Hooks define the core functionality of a migration in Shepherd.
- **Description**: Commands to determine if a repo requires migration.
- **Behavior**: Non-zero exit values indicate the repo should not be migrated.

- `should_create_issue`:

- **Description**: Commands to determine if issue needs to be posted in the repo.
- **Behavior**: Non-zero exit values indicate the issue should not be posted to repo.

- `post_checkout`:

- **Description**: Commands executed after a repo passes `should_migrate` checks.
Expand All @@ -124,12 +137,22 @@ Hooks define the core functionality of a migration in Shepherd.
- **Note**: This can range from simple to complex sequences, depending on migration needs.

- `pr_message`:

- **Description**: Commands to generate a pull request message.
- **Output**: Anything written to `stdout` is used for the message. Multiple commands will have their outputs concatenated.

- `issue`:

- **Description**: Command to create, update, or close issues.
- **Output**: Depending on the details provided in migration scripts, the issues will be created, updated or closed.

- `list-issues`:
- **Description**: Commands to list all issues associated with a migration.
- **Output**: All the posted issues are listed in the table format.

### Requirements

- Optional: `should_migrate`, `post_checkout`
- Optional: `should_migrate`, `post_checkout`, `should_create_issue`
- Required: `apply`, `pr_message`

### Environment Variables
Expand Down Expand Up @@ -180,6 +203,8 @@ There are a number of commands that must be run to execute a migration:
- `pr-preview`: Prints the commit message that would be used for each repository without actually creating a PR; uses the `pr_message` hook.
- `pr`: Creates a PR for each repo with the message generated from the `pr_message` hook.
- `version`: Prints Shepherd version
- `issue`: Create, update, or close issues across multiple repository.
- `list-issues`: List all issues associated with a migration.

By default, `checkout` will use the adapter to figure out which repositories to check out, and the remaining commands will operate on all checked-out repos. To only checkout a specific repo or to operate on only a subset of the checked-out repos, you can use the `--repos` flag, which specifies a comma-separated list of repos:

Expand Down
91 changes: 30 additions & 61 deletions e2e/__snapshots__/cli.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,77 +4,46 @@ exports[`CLI End-to-End Tests should display help information 1`] = `
"Usage: cli [options] [command]

Options:
-h, --help display help for command
-h, --help display help for command

Commands:
checkout [options] <migration> Check out any repositories that are
candidates for a given migration
apply [options] <migration> Apply a migration to all checked out
repositories
commit [options] <migration> Commit all changes for the specified
migration
reset [options] <migration> Reset all changes for the specified
migration
push [options] <migration> Push all changes for the specified
migration
pr-preview [options] <migration> View a preview of the PR messages for the
specified migration
pr [options] <migration> Create PRs for the specified migration
pr-status [options] <migration> Check the status of all PRs for the
specified migration
list <migration> List all checked out repositories for the
given migration
version Print Shepherd version
help [command] display help for command
checkout [options] <migration> Check out any repositories that are
candidates for a given migration
apply [options] <migration> Apply a migration to all checked out
repositories
commit [options] <migration> Commit all changes for the specified
migration
reset [options] <migration> Reset all changes for the specified
migration
push [options] <migration> Push all changes for the specified
migration
pr-preview [options] <migration> View a preview of the PR messages for the
specified migration
pr [options] <migration> Create PRs for the specified migration
pr-status [options] <migration> Check the status of all PRs for the
specified migration
list <migration> List all checked out repositories for the
given migration
issue [options] <migration> open an issue for the specified repos
list-issues [options] <migration> List all opened issues using migration
version Print Shepherd version
help [command] display help for command
"
`;

exports[`CLI End-to-End Tests should successfully checkout using repos flag 1`] = `
"Using 2 selected repos
exports[`CLI End-to-End Tests should successfully run apply on a migration 1`] = `""`;

[aorinevo/shepherd-test-repo-1] 1/2
> Running should_migrate steps
✔ Completed all should_migrate steps successfully
> Running post_checkout steps
✔ Completed all post_checkout steps successfully

[aorinevo/shepherd-test-repo-2] 2/2
> Running should_migrate steps
✔ Completed all should_migrate steps successfully
> Running post_checkout steps
✔ Completed all post_checkout steps successfully

Checked out 2 out of 2 repos
"
`;

exports[`CLI End-to-End Tests should successfully run apply on a migration 1`] = `
"
[NerdWalletOSS/shepherd] 1/1
ℹ Running apply steps
$ touch $SHEPHERD_REPO_DIR/testfile.js && echo "some content" > $SHEPHERD_REPO_DIR/testfile.js
Step "touch $SHEPHERD_REPO_DIR/testfile.js && echo "some content" > $SHEPHERD_REPO_DIR/testfile.js" exited with 0
✔ Completed all apply steps successfully
"
`;

exports[`CLI End-to-End Tests should successfully run apply on a migration 2`] = `
"On branch 2024.10.06-test-migration
Untracked files:
(use "git add <file>..." to include in what will be committed)
testfile.js
exports[`CLI End-to-End Tests should successfully run checkout on a migration targeting a single repo 1`] = `
"Loading candidate repos
Loaded 1 repos
Checking out repos

nothing added to commit but untracked files present (use "git add" to track)
"
`;

exports[`CLI End-to-End Tests should successfully run checkout on a migration 1`] = `
"
[NerdWalletOSS/shepherd] 1/1
Checked out repo
> Running should_migrate steps
Completed all should_migrate steps successfully
Completed all should_migrate steps successfully
> Running post_checkout steps
Completed all post_checkout steps successfully
Completed all post_checkout steps successfully

Checked out 1 out of 1 repos
"
Expand Down
29 changes: 19 additions & 10 deletions e2e/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ describe('CLI End-to-End Tests', () => {
);
});

afterAll(() => {
const testMigrationDir = path.resolve(os.homedir(), '.shepherd', '2024.10.06-test-migration');
fs.rmSync(testMigrationDir, { recursive: true });
});

const cliPath = path.resolve(__dirname, '../lib/cli.js');

const runCLI = (args: string) => {
Expand All @@ -33,22 +38,26 @@ describe('CLI End-to-End Tests', () => {
expect(output.split('.').length).toEqual(3);
});

it('should successfully run checkout on a migration', async () => {
it('should successfully run checkout on a migration targeting a single repo', async () => {
const output = runCLI(`checkout ${path.join(__dirname, './assets/checkout-apply')}`);
expect(output).toMatchSnapshot();
});

it('should successfully run checkout on a migration targeting multiple repos', async () => {
const output = runCLI(
`checkout ${path.join(__dirname, './assets/checkout-apply')} --repos="aorinevo/shepherd-test-repo-1,aorinevo/shepherd-test-repo-2"`
);
expect(output).toContain('shepherd-test-repo-1');
expect(output).toContain('shepherd-test-repo-2');
});

it('should successfully run apply on a migration', async () => {
const output = runCLI(`apply ${path.join(__dirname, './assets/checkout-apply')}`);
expect(output).toMatchSnapshot();
const gitDiffOutput = execSync(`cd ${shepherdRepoDir} && git status`, { encoding: 'utf-8' });
expect(output).toContain('shepherd-test-repo-1');
expect(output).toContain('shepherd-test-repo-2');
expect(output).toContain('NerdWalletOSS/shepherd');
const repoDir = path.resolve(shepherdRepoDir, '../../aorinevo/shepherd-test-repo-1');
const gitDiffOutput = execSync(`cd ${repoDir} && git diff`, { encoding: 'utf-8' });
expect(gitDiffOutput).toMatchSnapshot();
});

it('should successfully checkout using repos flag', async () => {
const output = runCLI(
`checkout --repos "aorinevo/shepherd-test-repo-1,aorinevo/shepherd-test-repo-2" ${path.join(__dirname, './assets/checkout-apply')}`
);
expect(output).toMatchSnapshot();
});
});
10 changes: 5 additions & 5 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import globals from 'globals';
import tseslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import importPlugin from 'eslint-plugin-import';
import preferArrowPlugin from 'eslint-plugin-prefer-arrow'; // Correct import for prefer-arrow
import preferArrowPlugin from 'eslint-plugin-prefer-arrow';

export default [
{
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
languageOptions: {
ecmaVersion: 2020, // Supports ES6+ features
sourceType: 'module', // ES6 module support
globals: globals.browser, // Browser globals
parser: tsParser, // Use TypeScript parser
ecmaVersion: 2020,
sourceType: 'module',
globals: globals.browser,
parser: tsParser,
},
plugins: {
'@typescript-eslint': tseslint,
Expand Down
16 changes: 7 additions & 9 deletions examples/eslintrc-yml/shepherd.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
id: 2018.08.15-eslintrc-yml
title: Rename all .eslintrc files to .eslintrc.yml
id: 2024.10.06-test-migration
title: |
feat: test migration
adapter:
type: github
search_query: repo:NerdWalletOSS/shepherd-demo path:/ filename:.eslintrc
search_query: repo:NerdWalletOSS/shepherd path:/
hooks:
should_migrate:
- ls .eslintrc
apply:
- mv .eslintrc .eslintrc.yml
pr_message:
- echo "Hey! This PR renames `.eslintrc` to `.eslintrc.yml`"
apply: 'touch $SHEPHERD_REPO_DIR/testfile.js && echo "some content" > $SHEPHERD_REPO_DIR/testfile.js'
pr_message: |
echo "e2e test suite"
6 changes: 3 additions & 3 deletions jest.config.cjs → jest.config.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
module.exports = {
export default {
preset: 'ts-jest',
testEnvironment: 'node',
extensionsToTreatAsEsm: ['.ts', '.mts'],
coveragePathIgnorePatterns: ['\\.mock\\.ts$'],
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
moduleFileExtensions: ['ts', 'mts', 'tsx', 'js', 'mjs', 'jsx', 'json', 'node'],
testRegex: '(/(__tests__|e2e)/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?|mts)$',
transform: {
'^.+\\.(ts|mts|tsx|js|mjs)?$': 'babel-jest',
'^.+\\.js$': 'babel-jest',
},
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1', // Map ".js" to ".ts" in imports
'^(\\.{1,2}/.*)\\.js$': '$1',
},
// Explicitly transform the ES module dependencies
transformIgnorePatterns: [
'/node_modules/(?!(@octokit|before-after-hook|universal-user-agent|bottleneck|@octokit/core|@octokit/plugin-retry|@octokit/plugin-rest-endpoint-methods|@octokit/plugin-throttling|chalk)/)', // Ensure these node_modules are transformed
],
Expand Down
6 changes: 3 additions & 3 deletions jest.e2e.config.cjs → jest.e2e.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
preset: 'ts-jest',
testEnvironment: 'node',
extensionsToTreatAsEsm: ['.ts', '.mts'],
Expand All @@ -10,10 +10,10 @@ module.exports = {
'^.+\\.js$': 'babel-jest',
},
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1', // Map ".js" to ".ts" in imports
'^(\\.{1,2}/.*)\\.js$': '$1',
},
transformIgnorePatterns: [
'/node_modules/(?!(@octokit|before-after-hook|universal-user-agent|bottleneck|@octokit/core|@octokit/plugin-retry|@octokit/plugin-rest-endpoint-methods|@octokit/plugin-throttling|chalk)/)', // Ensure these node_modules are transformed
],
collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx}'], // Collect coverage from src directory
collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx}'],
};
3 changes: 3 additions & 0 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
beforeEach(() => {
process.env.SHEPHERD_GITHUB_ENTERPRISE_URL = 'https://github.com';
});
Loading