Saya telah memulai pekerjaan refactoring plugin auto
maven
untuk mencoba lebih konsisten dengan sisa auto
. Dalam melakukannya, saya sampai pada beberapa kesimpulan.
Persyaratan saat ini untuk auto
dengan plugin maven
adalah bahwa proyek menggunakan maven-release-plugin
. Ini memiliki beberapa konsekuensi yang membuatnya tidak cocok untuk auto
.
Fungsi utama maven-release-plugin
mengeksekusi langkah-langkah berikut melalui release:prepare
:
Dan kemudian rilis dilakukan melalui release:perform
:
deploy
site-deploy
)Untuk memastikan plugin berperilaku dengan cara yang konsisten dengan auto
, implementasi saat ini menggunakan beberapa peretasan git untuk membuang komit yang dibuat oleh tujuan release:prepare
. Dengan kata lain, maven-release-plugin
melakukan pekerjaan yang dirancang untuk auto
, dan oleh karena itu harus "dikerjakan" dengan cara yang kurang baik.
Sama pentingnya adalah metode yang digunakan untuk mengekstrak informasi repositori dan penulis - saat ini plugin maven
menggunakan bagian <scm/>
dan <developers/>
dari pom.xml
untuk diturunkan informasi itu. Ini menyimpang dari metodologi yang digunakan oleh auto
yang menggunakan metadata git. Implementasi saat ini memiliki beberapa masalah:
author
diatur melalui bagian <developers/>
dari pom.xml
, yang berarti bahwa orang yang melakukan komit MUNGKIN TIDAK sama dengan author
. Tidak ada upaya untuk menyejajarkan penulis git commit dengan informasi <developers/>
.owner
dan repo
diatur melalui bagian <scm/>
, yang mungkin berbeda dari repositori aktual dan pemilik klon saat ini.Saat menyelami plugin lebih dalam, dan membandingkannya dengan plugin gradle
, tampaknya satu-satunya tujuan dari maven-release-plugin
yang akan bermanfaat adalah release:update-versions
sasaran. Tujuan itu dapat dengan mudah diganti dengan beberapa penanganan XML sederhana.
Mengingat biaya pemeliharaan maven-release-plugin
dan keuntungan minimal, pendapat saya adalah bahwa persyaratan harus dicabut, dan plugin auto
maven
harus diimplementasikan dalam auto
lebih banyak
Saya sangat setuju!
Sebagian besar poin Anda dengan info yang saya dapatkan dari pom.xml mungkin terkait dengan kesalahpahaman saya tentang bidang tersebut. Setiap perubahan di sini lebih dari diterima.
Saya mendukung setiap perubahan yang harus kita lakukan. Kita mungkin dapat menggulung beberapa perubahan yang lebih kecil yang dirinci di # 1156
Sepertinya dua poin saya tentang <scm/>
dan <developers/>
salah. Plugin npm
menariknya dari package.json
. Apakah ini berarti bahwa mereka _harus_ ditempatkan di pom.xml
?
Jika itu adalah setara pom
dari bidang npm repository
dan author
maka ya.
Penulis diatur melalui
bagian pom.xml, yang berarti bahwa orang yang melakukan komit MUNGKIN TIDAK sama dengan penulis yang dipilih. Tidak ada upaya untuk menyejajarkan penulis git commit dengan informasi.
Ini juga berlaku untuk plugin npm. Lokal otomatis tidak akan menimpa konfigurasi git
, tetapi dalam env CI mungkin harus menyetel author
untuk melakukan`.
Informasi pemilik dan repo diatur melalui
bagian, yang mungkin berbeda dari repositori sebenarnya dan pemilik klon saat ini.
Apakah ini akan berbeda? Di dunia npm bidang repository
biasanya menunjuk ke kode untuk paket. Dalam praktiknya, seseorang biasanya tidak menjalankan auto
pada fork
dan jika demikian, saya berharap mereka memperbarui bidang repository
ke fork mereka
Oke, itu masuk akal - jadi perilaku yang tepat adalah mencari hal-hal itu (saat ini), dan jika mereka TIDAK ditemukan di pom.xml
, kembali dan anggap mereka telah disetel di .autorc
(perilaku baru).
Saat ini, plugin akan error jika tidak menemukan bagian <scm/>
dan <developers/>
di pom.xml
.
Ah ya itu pasti bug. Seharusnya tidak menimbulkan kesalahan https://github.com/intuit/auto/blob/master/plugins/npm/src/index.ts#L504
Apakah ada cara untuk mendapatkan NUMBER versi dari auto
dengan cara yang dapat dibaca mesin? Saya terkejut bahwa perintah auto version
menghasilkan TYPE of version bump, bukan nomornya.
Anda dapat menggunakan --quiet
dan itu hanya akan mencetak versi yang dihasilkan oleh perintah. atau pasangkan dengan --dry-run
dan Anda dapat melihat versi apa yang akan diterbitkan selanjutnya.
Saya mungkin bersedia menambahkan tanda untuk membuat version
mengeluarkan versi sebenarnya. Ini menjadi aneh dalam skenario multi-paket
Saya bisa melihat itu. Mungkin lebih baik menyerahkannya kepada penelepon untuk mencari tahu versi mana yang dicarinya.
Maksud Anda tentang skenario multi-paket relevan di sini - plugin maven-release-plugin mendukung jenis skenario itu, out-of-the-box. Ini membuat saya mempertanyakan apakah saya ingin mereproduksi karya itu. Saya menemukan diri saya sedikit menemui jalan buntu - di satu sisi, argumen saya untuk TIDAK menggunakan maven-release-plugin valid, sementara di sisi lain, hal-hal seperti manajemen versi submodul adalah kasus penggunaan non-sepele yang harus ditangani, dan dicakup oleh maven-release-plugin.
Saya telah menemukan dua metode menggunakan maven-release-plugin yang dapat digunakan untuk mencegah plugin maven memodifikasi repositori selama release:prepare
, dan akan mengujinya nanti hari ini.
@hipstersmoothie Saya punya pertanyaan tentang perilaku kait getAuthor
, getRepo
, dll. - RE: komentar tentang https://github.com/intuit/auto/issues/1260#issuecomment - 634280655, saya melihat tes dan tampaknya bertentangan dengan itu.
Jadi, ketika saya mengembalikan undefined
AuthorInformation
tidak ada kesalahan yang muncul.
Adakah saran tentang apa yang mungkin saya lakukan salah, atau apakah saya harus memperkenalkan kembali throw
ke penanganan kait saya?
Itu pasti salah mengingat cara kerja semua plugin lainnya. Mengembalikan tidak terdefinisi adalah cara yang benar. Dengan begitu core
dapat kembali ke pengguna git
dikonfigurasi secara lokal jika diperlukan
Gotcha - itulah yang saya pikirkan, jadi saya telah memodifikasi tes untuk memastikan kait yang gagal mengembalikan undefined
.
Sepertinya plugin gradle dan cocoapods melempar kesalahan jika mereka tidak dapat menemukan versi. Saya membuat bug untuk plugin gradle - apakah Anda ingin yang lain untuk cocoapods?
Tinggalkan saja tidak pada masalah ini. Terima kasih untuk tangkapannya!
Saya berjuang dengan metode yang baik untuk menguji inisialisasi nilai selama hooks.beforeRun
. Secara khusus, saya memiliki kode berikut, yang ketika di bawah debug berhasil mengekstrak informasi penulis selama ketukan hooks.beforeRun
, tetapi gagal dalam pengujian:
test("should get author from pom.xml", async () => {
mockRead(`
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<developers>
<developer>
<name>Andrew Lisowski</name>
<email>[email protected]</email>
</developer>
</developers>
</project>
`);
await hooks.beforeRun.promise({} as any);
expect(await hooks.getAuthor.promise()).toStrictEqual(
expect.objectContaining({
email: "[email protected]",
name: "Andrew Lisowski",
})
);
});
Apa yang terjadi adalah bahwa tes tersebut menuju ke hook getAuthor
SEBELUM hook beforeRun
dijalankan. Saya telah melihat kode lain yang menguji ini (gradle, s3), dan saya tidak beruntung.
Pada dasarnya, saya memerlukan cara untuk mengeksekusi hook beforeRun
deterministik dan tidak tahu bagaimana melakukannya.
Dorong cabang dan saya bisa memeriksanya
@hipstersmoothie inilah cabangnya: https://github.com/terradatum/auto/tree/remove-maven-release-plugin-requirement
Saya telah mengomentari kode yang akan mendorong perubahan saya ke repo pusat sehingga saya dapat menguji kode pada proyek nyata tanpa mencemari riwayat jarak jauh.
Bantuan apa pun yang dapat Anda berikan kepada saya dengan ini sangat dihargai - saya ingin dapat menggunakan tes untuk memeriksa seberapa baik saya dapat memodifikasi file pom.xml, daripada menggunakan metode sekolah lama "menjalankan kode terhadap file asli, periksa file asli, jalankan git reset --hard HEAD~1
untuk menghilangkan perubahan, bilas dan ulangi."
Juga, saya harus membuat beberapa perubahan pada package.json
yang tidak kompatibel dengan root package.json
untuk menjalankan tes lelucon di IntelliJ - apakah ada panduan yang dapat Anda berikan kepada saya tentang itu, atau haruskah itu "berhasil" di luar kotak?
Khususnya, ketika di direktori plugin maven dan menjalankan npm test
- SEMUA tes akhirnya berjalan karena "test": "jest --maxWorkers=2 --config ../../package.json"
.
Dan jika saya mencoba menggunakan IntelliJ Test Runner dari editor, saya mendapatkan:
● Test suite failed to run
SyntaxError: /home/rbellamy/Development/Terradatum/auto/plugins/maven/__tests__/maven.test.ts: Unexpected token, expected "," (15:24)
13 | }));
14 |
> 15 | const mockRead = (result: string) =>
| ^
16 | jest
17 | .spyOn(fs, "readFile")
18 | // @ts-ignore
at Parser._raise (../../node_modules/@babel/parser/src/parser/location.js:241:45)
at Parser._raise [as raiseWithData] (../../node_modules/@babel/parser/src/parser/location.js:236:17)
at Parser.raiseWithData [as raise] (../../node_modules/@babel/parser/src/parser/location.js:220:17)
at Parser.raise [as unexpected] (../../node_modules/@babel/parser/src/parser/util.js:149:16)
at Parser.unexpected [as expect] (../../node_modules/@babel/parser/src/parser/util.js:129:28)
at Parser.expect [as parseParenAndDistinguishExpression] (../../node_modules/@babel/parser/src/parser/expression.js:1293:14)
at Parser.parseParenAndDistinguishExpression [as parseExprAtom] (../../node_modules/@babel/parser/src/parser/expression.js:1029:21)
at Parser.parseExprAtom [as parseExprSubscripts] (../../node_modules/@babel/parser/src/parser/expression.js:539:23)
at Parser.parseExprSubscripts [as parseMaybeUnary] (../../node_modules/@babel/parser/src/parser/expression.js:519:21)
at Parser.parseMaybeUnary [as parseExprOps] (../../node_modules/@babel/parser/src/parser/expression.js:311:23)
Saya dapat memecahkan masalah saya dengan IntelliJ dengan menambahkan file jest.config.ts
:
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}
Dan kemudian menambahkan jest-circus
ke file root atau maven package.json
.
Perhatikan bahwa xml2js
tidak akan berfungsi karena itu akan MENGHAPUS semua komentar XML secara diam-diam selama terjemahan XML => JSON => XML. Saya sudah mencoba membuatnya bekerja, dan itu seperti mencabut gigi. Tidak ada jaminan bahwa XML akan terlihat seperti aslinya ketika bergerak melalui transformasi xml2js
, dan itu adalah pemecah kesepakatan.
Untuk menjalankan tes hanya untuk satu plugin, saya menjalankannya dari root.
yarn test plugins/maven
Ini kemudian menimbulkan pertanyaan apakah Anda dapat dengan mudah menunjukkan semua perubahan yang akan Anda buat atau artefak yang akan Anda bangun tanpa benar-benar membuat beberapa perubahan.
Itu memang tampak seperti pemecah masalah yang cukup besar. Apakah ada CLI standar yang dikirimkan di lingkungan Java yang memungkinkan untuk mengedit file itu?
Untuk plugin yang tidak memiliki parser untuk file konfigurasi (mis: ruby) auto
sebagian besar menggunakan regex untuk memperbarui file.
Apakah Anda mendapat kesempatan untuk melihat masalah beforeRun
? Saya punya solusi, tetapi rasanya benar-benar hacky ...
Saya sangat tidak menyukai gagasan menggunakan regex dengan XML - rawan kesalahan dan rapuh. Namun, tampaknya juga sangat rumit mencoba menggunakan DOMParser
atau XMLSerializer
hanya untuk memodifikasi versi, itulah sebabnya saya mencoba bekerja dengan xml2js
sejak awal.
Melihat ini sekarang!
Masalahnya adalah Anda melakukan ketukan "sinkron" dan melakukan pekerjaan asinkron di dalamnya
Ubah ini
auto.hooks.beforeRun.tap(this.name, async () => {
untuk ini
auto.hooks.beforeRun.tapPromise(this.name, async () => {
Ah, sebelum menjalankan kait disinkronkan sekarang, itulah masalah sebenarnya. Itu tidak akan mengubah apa pun jika itu menjadi AsyncSeriesHook
alih-alih SyncHook
. Saya dapat mendorong komit ke cabang Anda jika tidak jelas apa yang saya katakan
Tolong lakukan ... izinkan saya menjadikan Anda kontributor.
Lanjutkan!
Hanya didorong. Jalankan tes dan hanya dua yang gagal sekarang. kait beforeRun berfungsi seperti yang diharapkan.
@hipstersmoothie Saya tidak melihat komit ke terradatum/auto repo?
sekarang saya benar-benar telah mendorong
Apakah itu akan menyebabkan perubahan yang mengganggu untuk plugin apa pun yang saat ini menggunakan ketukan sinkron?
Tidak. keran sinkronisasi harus bekerja sama. Ini hanya menambah kemampuan untuk menyadap janji
Saya telah berhasil membuat ini berfungsi dengan regex rapuh/rawan kesalahan. Kekhawatiran saya adalah bahwa elemen <version/>
digunakan DI MANA SAJA dalam file pom.xml
- untuk versi artefak DAN untuk dependensi dan plugin. Dengan kata lain, regex kemungkinan besar akan secara tidak sengaja mengubah versi yang tidak seharusnya.
Dalam mencoba bekerja dengan XML DOM (melalui xmldom, xmldom-ts, xml2js, xml2json, dll), saya menemukan diri saya terjebak dalam rawa proporsi epik. Saya sama sekali tidak menganggap diri saya seorang ahli TypeScript atau javascript, jadi mungkin di situlah saya jatuh.
Dua hal yang menendang pantat saya:
Document
dan kemudian menggunakan xpath untuk memilih node "/project/version" dan "/project/parent/version".Di antara dua masalah itu, saya mungkin menghabiskan total 12 hingga 16 jam, dan saya menjadi sangat frustrasi. Saya memiliki # 1 yang bekerja sampai pagi ini, dan saya akan berpikir # 2 seharusnya relatif sederhana, tetapi tampaknya melawan saya di setiap kesempatan.
Saya cenderung untuk kembali menggunakan maven-release-plugin karena alasan yang sangat sederhana yang menangani pembaruan file pom.xml untuk saya.
Saya tidak tahu bagaimana membuat IntelliJ menjalankan tes maven (dan HANYA tes maven) dalam mode debug. Terkadang berhasil, terkadang tidak.
Maaf saya tidak lebih dari membantu di sini. Saya menggunakan VSCode dan jarang men-debug tes. Bisakah Anda menjalankan dari root dengan yarn test plugins/maven
?
Memuat pom.xml ke dalam Dokumen dan kemudian menggunakan xpath untuk memilih node "/project/version" dan "/project/parent/version".
Ini sepertinya metode yang bagus. Jika itu bisa berhasil, sepertinya bagus.
Saya cenderung untuk kembali menggunakan maven-release-plugin karena alasan yang sangat sederhana yang menangani pembaruan file pom.xml untuk saya.
Apakah hanya ada hal-hal berbasis plugin seperti https://stackoverflow.com/questions/5726291/updating-version-numbers-of-modules-in-a-multi-module-maven-project yang tersedia untuk maven? hal berbasis mvn tingkat rendah akan sempurna.
BTW terima kasih telah menghabiskan begitu banyak waktu untuk ini!
Terima kasih atas umpan balik dan dukungannya. Maaf untuk komentar kasar (ish) sebelumnya.
Poin bagus tentang versi-maven-plugin - Saya belum pernah bekerja dengannya sebelumnya dan tidak tahu itu ada. Itu pasti akan membuat segalanya lebih mudah bagi saya... Ini adalah kompromi sempurna antara maven-release-plugin dan mencoba mengelola file pom.xml melalui plugin otomatis.
Saya bisa mendapatkan yarn test plugins/maven
untuk bekerja. Saya juga penggemar berat menggunakan debugger untuk memeriksa berbagai hal, daripada console.log
lebih tradisional, jadi mungkin di situlah saya menyebabkan diri saya lebih mulas daripada yang saya butuhkan ...
Setelah perjalanan panjang dan sulit, saya hampir mendapatkan apa yang saya anggap sebagai solusi lengkap, yang akan memodifikasi file pom.xml
secara langsung atau menggunakan versions-maven-plugin
untuk mengatur versi.
Ada beberapa peringatan. Kode yang digunakan untuk memodifikasi pom.xml
bekerja dengan DOM, yang memiliki konsekuensi sebagai berikut:
tsconfig.json
yang mengharuskan lib "dom"
sebelum "es2017"
di "compilerOptions"
:bekerja:
"compilerOptions": [ "dom", "es2017" ]
tidak berfungsi:
"compilerOptions": [ "es2017", "dom" ]
Tanpa "perbaikan", berikut ini terjadi:
$ tsc -b tsconfig.dev.json
node_modules/@types/jsdom/index.d.ts:28:40 - error TS2304: Cannot find name 'DocumentFragment'.
28 static fragment(html: string): DocumentFragment;
~~~~~~~~~~~~~~~~
node_modules/@types/jsdom/index.d.ts:45:28 - error TS2304: Cannot find name 'Node'.
45 nodeLocation(node: Node): ElementLocation | null;
~~~~
node_modules/@types/jsdom/index.d.ts:188:19 - error TS2304: Cannot find name 'HTMLScriptElement'.
188 element?: HTMLScriptElement | HTMLLinkElement | HTMLIFrameElement | HTMLImageElement;
~~~~~~~~~~~~~~~~~
node_modules/@types/jsdom/index.d.ts:188:39 - error TS2304: Cannot find name 'HTMLLinkElement'.
188 element?: HTMLScriptElement | HTMLLinkElement | HTMLIFrameElement | HTMLImageElement;
~~~~~~~~~~~~~~~
<snip - numerous other errors>
jest
memerlukan testEnvironment: 'jsdom'
sebagai lawan dari 'node'
.Tanpa "perbaikan", berikut ini terjadi:
$ jest --runInBand plugins/maven
FAIL plugins/maven/__tests__/maven.test.ts
maven
updatePomVersion
✕ should replace the previousVersion with the newVersion (39ms)
● maven › updatePomVersion › should replace the previousVersion with the newVersion
ReferenceError: XPathEvaluator is not defined
51 | ) => {
52 | const pomDom = new jsdom.JSDOM(content, {contentType: "text/xml"}).window.document;
> 53 | const evaluator = new XPathEvaluator();
| ^
54 | const resolver = evaluator.createNSResolver(pomDom.documentElement);
55 | const expression = evaluator.createExpression("/project/version", resolver);
56 | const versionNode = expression.evaluate(pomDom.documentElement, XPathResult.FIRST_ORDERED_NODE_TYPE);
at Object.exports.updatePomVersion (plugins/maven/src/index.ts:53:21)
at Object.test (plugins/maven/__tests__/maven.test.ts:53:26)
Tak satu pun dari "perbaikan" di atas berfungsi saat disetel dalam konfigurasi root plugin, misalnya plugins/maven/tsconfig.json
maupun konfigurasi jest
di plugins/maven/package.json
. Membuat perubahan pada file konfigurasi root tampaknya tidak berdampak negatif pada pengujian atau fungsionalitas.
apakah ini ada di cabang Anda? Saya mungkin bisa memperbaiki ini
Belum... Saya memastikan semua tes (dan yang baru) lulus sebelum mendorong. Saya akan melakukan ping ketika mereka siap untuk Anda tinjau.
Saya baru saja mengubah master ke cabang saya, dan sekarang saya mendapatkan beberapa kesalahan build.
Pertama, file yarn.lock
dibor karena konflik penggabungan, jadi saya harus menghapus dan membangunnya kembali:
error Incorrect integrity when fetching from the cache for "babel-plugin-jest-hoist". Cache has "sha512-u+/W+WAjMlvoocYGTwthAiQSxDcJAyHpQ6oWlHdFZaaN+Rlk8Q7iiwDPg2lN/FyJtAYnKjFxbn7xus4HCFkg5g== sha1-EpyAulx/x1uvOkW5Pi43LVfKJnc=" and remote has "sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w==". Run `yarn cache clean` to fix the problem
Setelah saya melakukannya, sekarang saya mendapatkan kesalahan @octokit/graphql
:
$ tsc -b tsconfig.dev.json
packages/core/src/auto.ts:2018:13 - error TS2571: Object is of type 'unknown'.
2018 if (result?.[`hash_${commit}`]) {
~~~~~~
packages/core/src/auto.ts:2019:27 - error TS2571: Object is of type 'unknown'.
2019 const number = (result[`hash_${commit}`] as ISearchResult).edges[0]
~~~~~~
packages/core/src/release.ts:286:52 - error TS2769: No overload matches this call.
Overload 1 of 2, '(o: ArrayLike<unknown> | { [s: string]: unknown; }): [string, unknown][]', gave the following error.
Argument of type 'unknown' is not assignable to parameter of type 'ArrayLike<unknown> | { [s: string]: unknown; }'.
Type 'unknown' is not assignable to type '{ [s: string]: unknown; }'.
Overload 2 of 2, '(o: {}): [string, any][]', gave the following error.
Argument of type 'unknown' is not assignable to parameter of type '{}'.
286 (acc, result) => [...acc, ...(Object.entries(result) as QueryEntry[])],
~~~~~~
packages/core/src/__tests__/git.test.ts:209:12 - error TS2571: Object is of type 'unknown'.
209 expect(result!.data).not.toBeUndefined();
~~~~~~~
Found 4 errors.
error Command failed with exit code 2.
Saya sangat berharap saya dapat membuat PR untuk ini - tetapi saya khawatir ini belum siap.
Oke, saya mencari tahu apa yang perlu saya lakukan - saya baru saja memeriksa file yarn.lock
dari master
dan kemudian menjalankan ulang yarn clean && yarn install && yarn build && yarn test plugins/maven
dan saya pikir saya baik-baik saja -Pergilah.
Luar biasa! Saya akan mengulasnya hari ini. Maaf saya tidak menanggapi selama akhir pekan!
:rocket: Masalah dirilis di v9.40.0
:rocket: