Больше никаких генераторов, журналов или зависимостей — теперь для JavaScript!

Если вы читали мой предыдущий пост о том, как написать скрипт на Python для создания и обновления журнала изменений, или пост до о написании скрипта журнала изменений в bash, этот пост может показаться вам интересным. также. Цель состоит в том, чтобы добавить поддержку нескольких языков, чтобы разработчикам не приходилось выбирать только один, а можно было выбрать тот, который больше всего соответствует стеку, который они используют в настоящее время.

Я добавил поддержку JavaScript, чтобы расширить свой исходный сценарий журнала изменений для инженеров, предпочитающих JavaScript. Теперь вы можете использовать ту же логику скрипта с JavaScript. Если вы являетесь разработчиком JS и хотите добавить больше настроек для создания/генерации вашего журнала изменений, теперь вы можете сделать это проще благодаря этой дополнительной поддержке.

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

Сначала создайте файл changelog.js для запуска логики скрипта. Вы можете сделать этот файл исполняемым, запустив chmod +x changelog.js. При этом вы сможете запустить ./changelog.js из своей командной строки или включить его в другой скрипт, если это предпочтительнее, добавив к нему ./changelog.js.

Далее нам нужно, чтобы версия нашего проекта была синхронизирована с нашим журналом изменений. Это, вероятно, самая сложная часть кода JavaScript. Вы можете сделать одно из двух:

  1. Найдите пакет (может быть, что-то вроде этого), который можно использовать для выполнения git describe --long в файле JavaScript.
  2. Будьте пуристом и делайте все это со своим собственным кодом! Если вы идете по этому пути, у нас есть несколько шагов.

Во-первых, мы должны require выполнить то, что называется child_process, а затем запустить exec в этом дочернем процессе. Этот метод позволяет нам запускать команды в консоли и буферизовать вывод. Вот наша первая строка кода.

const exec = require('child_process').exec;

Затем нам нужно написать функцию, которая запускает дочернее выполнение, которое принимает "git describe --long" в качестве аргумента, вместе с функцией обратного вызова. Ниже приведена наша функция.

const result = (command, cb) => {
  var child = exec(command, (err, stdout, stderr) => {
    if(err != null){
      return cb(new Error(err), null);
    }else if(typeof(stderr) != "string"){
      return cb(new Error(stderr), null);
    }else{
      return cb(null, stdout);
   }
  });
  return child
}

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

Вот код.

const getTaggedVersion = () => {
  result("git describe --long", (err, response) => {
    if(!err){ 
      console.log(response);
    }else {
      console.log(err);
    }
  });
}

Это немного запутанно, но может избавить вас от необходимости устанавливать и настраивать зависимость! Теперь перейдем к остальной части нашего сценария.

В changelog.js есть места, где мы используем интерполяцию строк. В JavaScript это делается немного иначе, чем в Bash или Python. См. ниже интерполяцию строк Bash.

name="Matthew Croak"
introduction="My name is $name"
echo $introduction
> "My name is Matthew"

Наконец, интерполяция строк для JavaScript.

name="Matthew Croak"
introduction=`My name is ${name}`
console.log(introduction)
> "My name is Matthew"

Интерполяция строк важна для сценария, потому что мы будем писать и переписывать файл журнала изменений из предоставленных строк. Эти строки будут содержать обновленную информацию, такую ​​как сегодняшняя дата и версия пакета.

Далее давайте напишем нашу функцию init. Эта функция будет использоваться для определения того, хотим ли мы создать новый журнал изменений или просто обновить существующий. В JavaScript модуль fs делает обработку файлов относительно простой. Мы можем импортировать existsSync из модуля fs и проверить, существует ли указанный путь. См. ниже.

const {existsSync} = require('fs');
const path = './CHANGELOG.md'
const init = () =>{
  try {
    if (existsSync(path)) {
      newChangelogItem()
    } else {
      newChangelog()
    }
  } catch (err){
    console.log(err)
  }
}

Далее давайте рассмотрим, как мы читаем и пишем наш файл журнала изменений. В Bash вы читаете файл так:

while read line; do           
  # code performed for each line
done < CHANGELOG.md

В JavaScript мы используем readFileSync для чтения предоставленного файла и writeFileSync для записи в предоставленный файл. Обе функции обеспечиваются модулем fs. readFileSync по существу возьмет предоставленный файл и преобразует его в строку. Затем мы можем взять эту строку и split в каждой новой строке (/n).

Таким образом, мы можем создать массив строк для повторения. См. ниже.

const fileData = readFileSync("CHANGELOG.md", { encoding: "utf8" });
const fileDataArray = fileData.split("\n");

writeFileSync выглядит аналогично, но требует дополнительного аргумента (между именем файла и данными кодировки). Этот третий аргумент представляет собой предоставленную строку, которая будет записана в файл. См. ниже.

writeFileSync("CHANGELOG.md", newFileData, { encoding: "utf8" });

Прежде чем мы продолжим с readAsync и writeAsync, давайте рассмотрим еще одну функцию, предоставляемую модулем fs: appendFile.

Мы можем использовать appendFile, чтобы, как следует из названия, добавить данные файла в файл. Предоставив имя файла, данные файла (в виде строки) и функцию обратного вызова, мы можем легко создать наш файл журнала изменений. См. ниже.

const newChangelog = () => {
  appendFile("CHANGELOG.md", changelogStart, (err) => {
    if (err) throw err;
    console.log('Changelog is created successfully.');
  })
}

Эта функция создаст новый файл (CHANGELOG.md), заполнив его changelogStart (строка, которая доступна в файле changelog.js на Github). Теперь, когда мы создали нашу функцию, которая создаст для нас журнал изменений, если он не существует, мы можем перейти к нашей функции, чтобы добавить новый элемент журнала изменений в существующий журнал изменений!

Теперь, прежде чем мы перейдем к коду вставки строки, давайте посмотрим, какой код нам нужен, чтобы определить, должны ли мы добавлять элемент. Помните, что элементы нашего журнала изменений соответствуют версии проекта и дате. Если у нас уже есть элемент журнала изменений для текущей версии и даты, нам не нужно создавать новый.

Ниже приведен код, который мы будем использовать, чтобы проверить, нужен ли нам новый элемент.

const newChangelogItem = () => {
  if (checkIfItemExists(item)){
    console.log(`Changelog item already exists for \n   ${item}`)
  } else {
    writeChangelog()
  }
}

Мы скоро доберемся до writeChangelog, но сначала checkIfItemExists.

const checkIfItemExists = (str) => {
  const contents = readFileSync('CHANGELOG.md', 'utf-8');
  return contents.indexOf(str) > -1;
}

Эта функция использует readFileAsync. Это создаст строковую версию нашего журнала изменений. Как только это строка, мы можем использовать проверку индекса нашего элемента журнала изменений. Если он больше -1, то он существует и нам не нужно добавлять новый. В противном случае добавьте новый. Просто, нет?

Теперь, когда мы решаем, можем ли мы добавить новый элемент журнала изменений, давайте проверим, как мы можем его добавить. Для этого мы будем использовать readFileAsync и writeFileAsync. Мы преобразуем наш файл в массив строк (как упоминалось ранее), а затем пройдемся по этому массиву, если строки. Перебирая наши строки, мы ищем строку, в которую мы будем вставлять наш новый элемент. Эта линия обозначена как "## [Unreleased]".

Мы можем проверить это, снова воспользовавшись indexOf. Если fileDataArray[i].indexOf(“## [Unreleased]”) > -1, то мы знаем, что это — это строка, в которую мы вставляем наш элемент. Как мы можем вставить наш элемент в JavaScript? Используя splice.

splice позволяет нам добавлять новые элементы вместо существующего в наш массив. Мы можем просто splice добавить наш новый элемент в наш массив сразу после строки “## [Unreleased]”. См. ниже.

iterateArr = [...fileDataArray)
for (var i = 0; i < iterateArr.length; i++){
  if (fileDataArray[i].indexOf("## [Unreleased]") > -1){
    fileDataArray.splice(i + 1, 0, `\n${item}\n### Added\n- ADD CHANGE HERE!`)
     const newFileData = fileDataArray.join("\n");
     writeFileSync("CHANGELOG.md", newFileData, { encoding: "utf8" })
     break
  }
}

iterateArr создается из fileDataArray с помощью оператора распространения. Мы делаем это, потому что не хотим перебирать массив, с которым манипулируем. Как только мы spliced добавим наш новый элемент в массив строк, мы можем join соединить их в одну строку. Затем мы можем предоставить эту строку writeFileAsync и записать ее в наш файл CHANGELOG.md.

Какой из них вы должны использовать?

Учитывая, что это поколение списка изменений теперь поддерживает Bash, Python и JavaScript, какой из них вам следует использовать? Я лично нашел Python более предпочтительным. Я чувствую, что кривая обучения Bash была немного шире, чем Python (по крайней мере, для меня), и хотя в Bash меньше строк кода, я больше боролся с отладкой.

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

Но если вы являетесь знатоком JavaScript (?) насквозь, теперь у вас есть чистый скрипт, который можно включить в ваше приложение для создания журнала изменений и добавления элементов журнала изменений. Он также обеспечивает гибкость в отношении формата и содержимого журнала изменений без необходимости в генераторах, журналах или других зависимостях.

Полный код находится на GitHub.

Обновите бесплатную подписку на Medium и получайте неограниченное количество статей без рекламы от тысяч авторов в самых разных изданиях. Это партнерская ссылка, и часть вашего членства помогает мне получать вознаграждение за контент, который я создаю.

Вы также можете подписаться по электронной почте и получать уведомления, когда я публикую что-то новое!

Спасибо!

Рекомендации

Как написать Bash-скрипт для создания и обновления журнала изменений

GitHub — macro6461/changelog-python: скрипт Python для создания и обновления списка изменений

GitHub — macro6461/changelog-bash: Чистый скрипт bash для создания и добавления элементов списка изменений

git-описать

Дочерние процессы Node.js — javaTpoint

changelog-js/changelog.js в основном · macro6461/changelog-js

Array.prototype.splice() — JavaScript | МДН

GitHub — macro6461/changelog-js: код JavaScript для создания и обновления журнала изменений