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 #8

Closed
wants to merge 23 commits into from
8 changes: 3 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:
pull_request:
branches: [master, develop]

permissions:
contents: write

jobs:
test:
name: Test
Expand Down Expand Up @@ -34,11 +37,6 @@ jobs:
- name: Type check
run: pnpm type-check

- name: Setup Git # Only used by the last test
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "<>"

- name: Build
run: pnpm build

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"clean-pkg-json": "^1.2.0",
"cleye": "^1.3.2",
"execa": "^8.0.1",
"fs-fixture": "^2.5.0",
"fs-fixture": "^2.6.0",
"lintroll": "^1.10.0",
"manten": "^1.3.0",
"npm-packlist": "^5.1.1",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 9 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@
const localTemporaryBranch = `git-publish/${publishBranch}-${Date.now()}`;
let success = false;

// Validate remote exists
let remoteUrl;
try {
const getRemoteUrl = await execa('git', ['remote', 'get-url', remote]);
remoteUrl = getRemoteUrl.stdout.trim();
} catch {
throw new Error(`Git remote ${stringify(remote)} does not exist`);
}

// In the try-finally block in case it modifies the working tree
// On failure, they will be reverted by the hard reset
try {
Expand Down Expand Up @@ -202,7 +211,7 @@

const { stdout: trackedFiles } = await gitStatusTracked();
if (trackedFiles.length === 0) {
console.warn('⚠️ No new changes found to commit.');

Check warning on line 214 in src/index.ts

View workflow job for this annotation

GitHub Actions / Test

Unexpected console statement
} else {
// -a is passed in so it can stage deletions from `git restore`
await execa('git', ['commit', '--no-verify', '-am', `Published branch ${stringify(currentBranch)}`]);
Expand Down Expand Up @@ -258,14 +267,6 @@
}

if (success) {
let remoteUrl = remote;

// If the "remote" flag contains an alias, resolve it to a URL
try {
const { stdout } = await execa('git', ['remote', 'get-url', remoteUrl]);
remoteUrl = stdout.trim();
} catch {}

const parsedGitUrl = remoteUrl.match(/github\.com:(.+)\.git$/);

if (parsedGitUrl) {
Expand All @@ -277,7 +278,7 @@
},
);
})().catch((error) => {
console.error('Error:', error.message);

Check warning on line 281 in src/index.ts

View workflow job for this annotation

GitHub Actions / Test

Unexpected console statement

process.exit(1);
});
81 changes: 21 additions & 60 deletions tests/index.ts
Original file line number Diff line number Diff line change
@@ -1,102 +1,63 @@
import path from 'path';
import { execa, type Options } from 'execa';
import path from 'node:path';
import fs from 'node:fs/promises';
import { describe, expect } from 'manten';
import { createFixture } from 'fs-fixture';

const gitPublish = path.resolve('./dist/index.js');

const createGit = async (cwd: string) => {
const git = (
command: string,
args?: string[],
options?: Options,
) => (
execa(
'git',
[command, ...(args || [])],
{
cwd,
...options,
},
)
);

await git(
'init',
[
// In case of different default branch name
'--initial-branch=master',
],
);

await git('config', ['user.name', 'name']);
await git('config', ['user.email', 'email']);

return git;
};
import { createGit } from './utils/create-git.js';
import { gitPublish } from './utils/git-publish.js';

describe('git-publish', ({ describe, test }) => {
describe('Error cases', ({ test }) => {
test('Fails if not in git repository', async () => {
const fixture = await createFixture();
await using fixture = await createFixture();

const gitPublishProcess = await execa(gitPublish, {
cwd: fixture.path,
reject: false,
});
const gitPublishProcess = await gitPublish(fixture.path);

expect(gitPublishProcess.exitCode).toBe(1);
expect(gitPublishProcess.stderr).toBe('Error: Not in a git repository');

await fixture.rm();
});

test('Fails if no package.json found', async () => {
const fixture = await createFixture();
await using fixture = await createFixture();

await createGit(fixture.path);

const gitPublishProcess = await execa(gitPublish, {
cwd: fixture.path,
reject: false,
});
const gitPublishProcess = await gitPublish(fixture.path);

expect(gitPublishProcess.exitCode).toBe(1);
expect(gitPublishProcess.stderr).toBe('Error: No package.json found in current working directory');

await fixture.rm();
});

test('Dirty working tree', async () => {
const fixture = await createFixture({
await using fixture = await createFixture({
'package.json': '{}',
});

const git = await createGit(fixture.path);
await git('add', ['package.json']);

const gitPublishProcess = await execa(gitPublish, {
cwd: fixture.path,
reject: false,
});
const gitPublishProcess = await gitPublish(fixture.path);

expect(gitPublishProcess.exitCode).toBe(1);
expect(gitPublishProcess.stderr).toBe('Error: Working tree is not clean');

await fixture.rm();
});
});

test('Publishes', async ({ onTestFail }) => {
// Requires git config author to be set
// This is set on the GitHub Action because locally, an author already exists

const gitPublishProcess = await execa(gitPublish, {
reject: false,
const fixture = await createFixture(process.cwd(), {
templateFilter: cpPath => !(
cpPath.endsWith(`${path.sep}node_modules`)
|| path.basename(cpPath) === '.git'
|| path.basename(cpPath) === 'dist'
),
});

await fs.symlink(path.resolve('node_modules'), fixture.getPath('node_modules'), 'dir');
await fs.symlink(path.resolve('.git'), fixture.getPath('.git'), 'dir');

const gitPublishProcess = await gitPublish(fixture.path);

onTestFail(() => {
console.log(gitPublishProcess);

Check warning on line 60 in tests/index.ts

View workflow job for this annotation

GitHub Actions / Test

Unexpected console statement
});

expect(gitPublishProcess.exitCode).toBe(0);
Expand Down
33 changes: 33 additions & 0 deletions tests/utils/create-git.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { execa, type Options } from 'execa';

export const createGit = async (
cwd: string,
) => {
const git = (
command: string,
args?: string[],
options?: Options,
) => (
execa(
'git',
[command, ...(args || [])],
{
cwd,
...options,
},
)
);

await git(
'init',
[
// In case of different default branch name
'--initial-branch=master',
],
);

await git('config', ['user.name', 'name']);
await git('config', ['user.email', 'email']);

return git;
};
16 changes: 16 additions & 0 deletions tests/utils/git-publish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import path from 'node:path';
import { execa } from 'execa';

const gitPublishPath = path.resolve('./dist/index.js');

export const gitPublish = (
cwd: string,
) => execa(gitPublishPath, {
cwd,
reject: false,
// Remove CI env var which prevents Ink from rendering
env: {
PATH: process.env.PATH,
},
extendEnv: false,
});
Loading