Skip to content

First implementation #1

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

Merged
merged 1 commit into from
Mar 6, 2025
Merged

First implementation #1

merged 1 commit into from
Mar 6, 2025

Conversation

KuznetsovRoman
Copy link
Member

No description provided.

Copy link

github-actions bot commented Jan 16, 2025

Testplane run finisned

Testplane HTML-report is available at https://gemini-testing.github.io/gh-actions-testplane/testplane-reports/2025-02-12/13287216451/41

@KuznetsovRoman KuznetsovRoman force-pushed the TESTPLANE-389.action branch 29 times, most recently from a3354f1 to a32aff2 Compare January 21, 2025 19:46
@@ -0,0 +1,41 @@
name: GitHub action publish new version
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Флоу для релиза новой версии github action
Собирает новую версию action и коммитит ее в мастер

@@ -0,0 +1,65 @@
name: Testplane CI
Copy link
Member Author

@KuznetsovRoman KuznetsovRoman Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тестовый флоу.

  • Тестирует юнит тестами
  • Прогоняет линтер
  • Билдит action
  • Запускает этот action на тестовом проекте
  • Выкладывает html-отчет на gh-pages
  • Оставляет комментарий со ссылкой на отчет

@@ -1 +1,2 @@
node_modules
dist/dev.js
Copy link
Member Author

@KuznetsovRoman KuznetsovRoman Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Собирается с npm run build, запускается разработчиком
На самом деле, локально билдить какого-то смысла нет, кроме как "проверить, что оно собирается"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А почему в игноре не весь dist?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dist/index.js будет билдиться и комиттиться.
Так же, как в npm registry коммитится build, так же и в github коммитится сбилженный github action
Вот пример github action (https://github.com/actions/cache), у них у всех dist коммитится в VCS, откуда же и запускается, когда разработчик пишет что-то вроде "uses: actions/cache@v4"

@@ -0,0 +1 @@
v20.18.1
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Максимальная версия, поддерживаемая github actions

@@ -0,0 +1,43 @@
name: 'Testplane action'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Конфиг github action
Описывает входные и выходные параметры

return;
}

if (this.needsBrowsersCache && !cache.isFeatureAvailable()) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gh сервис кэширования может быть недоступен


core.debug(`Testplane browsers cache primary key: "${this.cachePrimaryKey}"`);

this.init = () => Promise.resolve();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Второй раз init не нужен

const commandOutput = await this.pm.getExecOutput(this.withConfig(["testplane", "--version"]));
const semverNumbers = commandOutput.split(".").map(Number) as [MajorVersion, MinorVersion, PatchVersion];

this.version = () => Promise.resolve(semverNumbers);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Результаты подобных команд не изменяются в процессе работы action, так что их кэшируем


core.debug("Running Testplane install-deps");

await this.pm.exec(this.withConfig(["testplane", "install-deps"]), { silent: false });
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

silent: false включает вывод логов команды в stdout/stderr

const dateNow = new Date();

const year = dateNow.getUTCFullYear();
const month = String(dateNow.getUTCMonth() + 1).padStart(2, "0");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По умолчанию getUTCMonth выдает значения [0, 11]

@KuznetsovRoman KuznetsovRoman force-pushed the TESTPLANE-389.action branch 3 times, most recently from 431cf70 to 8939450 Compare January 27, 2025 01:56
"type": "module",
"scripts": {
"build-base": "rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
"build": "npm run build-base -- --file dist/dev.js",
Copy link
Member Author

@KuznetsovRoman KuznetsovRoman Feb 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Билдит action, чтобы "проверить, что билдится". Запускается локально.
Локально нет возможности запустить из-за тесной интеграции с @actions модулями

package.json Outdated
"scripts": {
"build-base": "rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
"build": "npm run build-base -- --file dist/dev.js",
"build-action": "npm run build-base -- --file dist/index.js",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

так может и назвать ci:build ? (не критично)

sourcemap: false,
plugins: [terser()],
},
plugins: [typescript(), nodeResolve(), json(), commonjs()],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Просто интересно: а зачем плагин commonjs, если вся репа — ESM?

Copy link
Member Author

@KuznetsovRoman KuznetsovRoman Feb 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это супер неочевидно, но для того, чтобы собирать esm нужен плагин commonjs.
В данном случае он у нас из commonjs делает esm (например, @actions/core - CJS: https://github.com/actions/toolkit/blob/main/packages/core/package.json)
Вот попробовал запустить без этого плагина: https://github.com/gemini-testing/gh-actions-testplane/actions/runs/13285834186/job/37094200943?pr=1

import { Testplane, TestplaneCache } from "./testplane/index.js";
import { writeFailureSummary, writeSuccessSummary } from "./summary.js";

async function main() {
Copy link
Member

@shadowusr shadowusr Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Детально прочитав весь код, у меня остался главный верхне-уровневый вопрос — в чем ключевое преимущество кастомного action VS страница с докой и примерами флоу, как запустить Testplane (которые можно вставить без изменений и получить готовый флоу).

Судя по коду, задачи этого action:

  • Кэширование зависимостей
  • Установка зависимостей
  • Запуск testplane
  • Доп. обработка вывода, улучшение читаемости результатов — summary, структурирование логов

Меня беспокоят такие моменты:

Захватывание установки зависимостей работы с пакетными менеджерами в область ответственности нашего action.

  • Я думаю, что это довольно опасный и дорогой подход, потому что пакетных менеджеров много, у каждого множество своих тонкостей и мы 100% что-то не учли.
  • Уже сейчас мы захардкодили npm, yarn, pnpm. Если вдруг появится что-то еще, нужно тратить время на поддержку/внедрение.
  • На каждом релизе нужно тестировать во всех 3 пакетных менеджерах = лишние сложности.

При этом какой получаем профит? Я как понимаю хотим получить максимально коробочное решение, но какой ценой? Выглядит так, что это в этом месте это может нанести больше вреда, чем пользы.

Решение недоработок интерфейса Testplane абстракциями со стороны action

Если запустить Testplane из CLI и читать его вывод сложно, то может стоит инвестировать в улучшение этого в самом инструменте? Может нам нужен summary-репортер? Если артефакты testplane сложно кэшировать обычным actions/cache, может упросить этот момент?

Дороговизна поддержки + необходимость реализовывать фичи в этом кубике повторно

Пример: помимо реализации шардирования в Testplane, нужно реализовывать его и здесь. Помимо реализации перезапуска только упавших тестов в Testplane, нужно реализовывать его и здесь. И т.д.

Опыт коллег

Ребята из playwright прошли схожий путь (длиной в 5 лет) с action здесь: https://github.com/microsoft/playwright-github-action

И в итоге пришли к выводу, что лучше всего не иметь action. А просто использовать CLI и написать в доке пример флоу + генерить его при создании проекта


Для меня эти минусы перевешивают простоту и гибкость написания обычного флоу с помощью композиции готовых action'ов типа actions/checkout, actions/setup-node, actions/cache и т.д. При этом юзерам не надо сочинять это каждый раз, если предоставить несколько готовых рецептов под наиболее популярные кейсы.

Возможно у меня тут странная позиция и она идет вразрез с мнением остальных, я не говорю, что это единственный правильный путь.

Но ревью это в том числе про взгляд со стороны, поэтому я предлагаю еще раз обратить внимание на эти моменты и вопросы, и подумать о них.

Однако я не настаиваю на этом пути. Просто озвучиваю свои мысли и взгляд со стороны. Сама задумка крутая и по коду замечаний у меня особо нет.

await cache.saveCache([this.testplaneCachePath], this.getCachePrimaryKey());
}

private async init(): Promise<void> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я считаю, что init-методы — небольшой code-smell, поскольку само их наличие означает, что объект может находиться в невалидном состоянии. Как правило, если извлечь логику init из класса и подавать готовые данные в конструктор, то всё становится сильно проще — не нужны проверки, не надо перезаписывать init, и т.д.

.write({ overwrite: true });
};

export const writeFailureSummary = async (postMortemData: PostMortemData) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это прикольная штука 🔥

Copy link
Member

@shadowusr shadowusr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По коду все супер. Перед влитием предлагаю только подумать над тезисами выше

@KuznetsovRoman KuznetsovRoman force-pushed the TESTPLANE-389.action branch 3 times, most recently from e704906 to fefabe4 Compare February 12, 2025 13:03
@KuznetsovRoman KuznetsovRoman merged commit 63f08cc into master Mar 6, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants