Skip to content
Merged
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
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# Cambios

Los cambios de cada versión de `parche-cli` y de la Action `Pepo08/parche@v0`. En npm están la 0.1.1, la 0.5.1, de la 0.6.0 a la 0.7.0, la 0.7.2, la 0.7.3 y de la 0.7.5 en adelante. La 0.1.0 y de la 0.2.0 a la 0.5.0 no se publicaron en npm; lo que traían está incluido en la 0.5.1. La 0.7.1 y la 0.7.4 tampoco: salieron junto con la 0.7.2 y la 0.7.5. La fecha de cada versión es la del cambio; la de publicación figura en npm y en los [Releases](https://github.com/Pepo08/parche/releases).
Los cambios de cada versión de `parche-cli` y de la Action `Pepo08/parche@v0`. En npm están la 0.1.1, la 0.5.1, de la 0.6.0 a la 0.7.0, la 0.7.2, la 0.7.3, de la 0.7.5 a la 0.8.0 y de la 0.8.5 en adelante. La 0.1.0 y de la 0.2.0 a la 0.5.0 no se publicaron en npm; lo que traían está incluido en la 0.5.1. La 0.7.1 y la 0.7.4 tampoco: salieron junto con la 0.7.2 y la 0.7.5. De la 0.8.1 a la 0.8.4, tampoco: salieron juntas con la 0.8.5. La fecha de cada versión es la del cambio; la de publicación figura en npm y en los [Releases](https://github.com/Pepo08/parche/releases).

## 0.8.5 — 2026-11-04

`fix` y `pr` frenan con un flag que no conocen, antes de tocar nada. En npm, esta versión trae también todo lo de la 0.8.1 a la 0.8.4.

### Corregido
- **`parche fix . --dry-run` escribía en el código sin avisar.** `--dry-run` es de `pr`, y la CLI aceptaba cualquier flag en cualquier comando. Ahora `fix` lo rechaza y dice qué usar: `parche scan` para ver qué cambiaría, o `parche pr --dry-run` para armar la rama sin abrir el PR.
- **Un flag mal escrito ya no pasa de largo en `fix` ni en `pr`.** `fix --pakc <id>` aplicaba todos los packs y `pr --dryrun` podía abrir el PR de verdad. Ahora frenan y listan las opciones. El resto de los comandos lee los flags como antes, y la Action no cambia.
## 0.8.4 — 2026-11-04

Mercado Pago: el checklist del PR deja de pedir un mail de prueba que la documentación oficial no pide. La detección y el arreglo no cambian.
Expand Down
18 changes: 18 additions & 0 deletions bin/parche.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,23 @@ function parseArgs(argv) {
return args;
}

// Los comandos que cambian algo: un flag que no conocen (`fix --dry-run`, que es de `pr`; `pr --dryrun`) frena antes de tocar nada.
const WRITE_FLAGS = {
fix: ['pack'],
pr: ['pack', 'dry-run', 'verify', 'push-remote', 'author'],
};

function checkFlags(cmd, args) {
const known = WRITE_FLAGS[cmd];
const unknown = known ? Object.keys(args).filter((k) => k !== '_' && !known.includes(k)) : [];
if (!unknown.length) return;
if (cmd === 'fix' && unknown.includes('dry-run')) {
throw new Error('`parche fix` no tiene --dry-run: escribe en el código. No se tocó nada. Para ver qué cambiaría, usá `parche scan`; para armar la rama sin abrir el PR, `parche pr --dry-run`.');
}
const list = (keys) => keys.map((k) => `--${k}`).join(', ');
throw new Error(`\`parche ${cmd}\` no conoce ${list(unknown)}. No se tocó nada. Opciones: ${list(known)}.`);
}

function summary(findings) {
const c = counts(findings);
return ['auto', 'needs-review', 'needs-input', 'blocked', 'detect-only']
Expand Down Expand Up @@ -164,6 +181,7 @@ async function main() {
return 0;
}
if (!cmd || args.help) { console.log(HELP); return 0; }
checkFlags(cmd, args);

if (cmd === 'packs') {
for (const p of loadPacks()) {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "parche-cli",
"version": "0.8.4",
"version": "0.8.5",
"description": "Dependabot para APIs: detecta cambios de cualquier API de terceros en tu código (ARCA, Mercado Pago, OpenAI, Anthropic) y abre el PR con el arreglo.",
"keywords": [
"api",
Expand Down
89 changes: 89 additions & 0 deletions test/flags-cli.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// 0.8.5: `fix` y `pr` cambian cosas, y `parseArgs` acepta cualquier flag. `parche fix . --dry-run` (el flag es de `pr`)
// escribía en el código sin avisar, `fix --pakc <id>` aplicaba todos los packs y `pr --dryrun` podía abrir el PR de verdad.
// Ahora un flag que no conocen frena antes de tocar nada; el resto de los comandos lee los flags como antes.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { execFileSync, spawnSync } from 'node:child_process';

const HERE = path.dirname(fileURLToPath(import.meta.url));
const BIN = path.join(HERE, '..', 'bin', 'parche.js');
const ARCA = 'arca.wsfe.condicion-iva-receptor';
const AUTHOR = 't <t@users.noreply.github.com>';
const VOUCHER = "export const emitir = (afip) => afip.ElectronicBilling.createVoucher({\n CbteTipo: 6,\n DocTipo: 99,\n DocNro: 0,\n});\n";

function repo() {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'parche-flags-'));
fs.mkdirSync(path.join(root, 'src'));
fs.writeFileSync(path.join(root, 'src', 'f.js'), VOUCHER);
const g = (...a) => execFileSync('git', a, { cwd: root, encoding: 'utf8' });
g('init', '-q', '-b', 'main');
g('-c', 'user.name=t', '-c', 'user.email=t@t', 'add', '-A');
g('-c', 'user.name=t', '-c', 'user.email=t@t', 'commit', '-q', '-m', 'init');
return { root, g };
}
const parche = (...a) => spawnSync('node', [BIN, ...a], { encoding: 'utf8' });

function untouched({ root, g }) {
assert.equal(fs.readFileSync(path.join(root, 'src', 'f.js'), 'utf8'), VOUCHER);
assert.equal(g('status', '--porcelain').trim(), '');
assert.equal(g('branch', '--format=%(refname:short)').trim(), 'main');
assert.ok(!fs.existsSync(path.join(root, '.parche')));
}

test('fix --dry-run no toca nada y dice qué usar', () => {
const r = repo();
const out = parche('fix', r.root, '--dry-run');
assert.equal(out.status, 1);
assert.match(out.stderr, /`parche fix` no tiene --dry-run/);
assert.match(out.stderr, /`parche scan`/);
assert.match(out.stderr, /`parche pr --dry-run`/);
untouched(r);
});

test('fix con un flag mal escrito no aplica todos los packs', () => {
const r = repo();
const out = parche('fix', r.root, '--pakc', ARCA);
assert.equal(out.status, 1);
assert.match(out.stderr, /`parche fix` no conoce --pakc/);
assert.match(out.stderr, /--pack/);
untouched(r);
});

test('pr con un flag mal escrito no arma ninguna rama', () => {
const r = repo();
const out = parche('pr', r.root, '--dryrun', '--author', AUTHOR);
assert.equal(out.status, 1);
assert.match(out.stderr, /`parche pr` no conoce --dryrun/);
assert.match(out.stderr, /--dry-run/);
untouched(r);
});

test('fix --pack sigue aplicando el arreglo', () => {
const { root } = repo();
const out = parche('fix', root, '--pack', ARCA);
assert.equal(out.status, 0, out.stderr);
assert.notEqual(fs.readFileSync(path.join(root, 'src', 'f.js'), 'utf8'), VOUCHER);
});

test('pr acepta lo que le pasa la Action (--pack, --verify y --dry-run) y --author', () => {
const { root } = repo();
const out = parche('pr', root, '--pack', ARCA, '--verify', '--dry-run', '--author', AUTHOR);
assert.doesNotMatch(out.stderr, /no conoce/);
assert.equal(out.status, 0, out.stderr);
});

test('el flag de pr para pushear a un fork no se toma como desconocido', () => {
const { root } = repo();
const out = parche('pr', root, '--pack', ARCA, '--dry-run', '--push-remote', 'fork', '--author', AUTHOR);
assert.doesNotMatch(out.stderr, /no conoce/);
});

test('scan sigue sin fijarse en los flags que no usa', () => {
const { root } = repo();
const out = parche('scan', root, '--dry-run');
assert.equal(out.status, 0, out.stderr);
});
Loading