-
Notifications
You must be signed in to change notification settings - Fork 994
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
Add option to setup TailwindUI with TailwindCSS #1408
Conversation
4055fc7
to
343d559
Compare
Unless I missed them, it seems there are actually no tests for this part of the code? Should we add some, or is it assumed that the |
Nice! This option makes a ton of sense. We do need a little coordination here. I've been working with the author of #1407 for several weeks (see issue #1301), although the PR just came through with yours. He spent a lot of time getting the --force option to work correctly, which is going to conflict with this file. My preference is to get #1407 merged first. Open to suggestions, but how about this for a plan:
OK? Too much? Thoughts either way? |
@thedavidprice sounds perfect! I've had a first look at the other PR and it seems it's going to fix what I was pulling my hair off on yesterday 😅 I thought I had broken something that made |
Yeah, this one is a double gotcha 💥
|
Ah! Both things I had issues with then! ^_^ |
343d559
to
25dad5d
Compare
All right, the branch is rebased! |
Actually @thedavidprice what do you think the testing strategy should be? I don't have a lot of practice testing that kind of codebase... I'm reluctant to mock That might be a bit too much (and slow!) for tests? ^^ |
Agreed with those points — this is an ongoing theme regarding the CLI and unit tests. And I don't think it makes sense to test yarn install or the tailwindcss CLI. I just looked at the test for Auth generator as an example. Turns out there's not much going on, but it could be a template to start with: One thing we've done in the past is to isolate specific tasks in Listr for tests. See my comment here and the resulting tests for the Destroy command: What if we try to test:
Where these tests are the most helpful is cross-platform, e.g. in the case of Window. Open to any/all suggestions. Especially if you feel the scope is too large and or not viable. |
OK so, if I understand correctly:
I guess I can reproduce this and apply it to Here's the test plan I had written down last week. → On pristine app
→ On already setup app, without
→ On already setup app, with
What do you think? As to "mocking" an app structure that the tasks could work on, do you think I should use fixtures (I'd say so), or some heavy use of I'll get started and adjust depending on your feedback ^^ |
25dad5d
to
9b84ca4
Compare
@thedavidprice as a first step, I have reorganized the code to support the test plan and move in the direction you were hinting at in your comment for the destroy command tests. I don't feel like running the complete tasks set at once for each test, I don't think it makes a lot of sense.
So I went with this:
I'd say it has the merit to increase testability and improve code legibility by keeping files small and scoped to a single thing at once. It should also make tests slightly clearer as I'll be able to call just the task function I'd like to test, instead of the all set of tasks over and over again like in the I have pushed the changes to the branch, so you can have a look. |
9b84ca4
to
dc6a667
Compare
@olance given @thedavidprice is away for a few days -- and I have been using (and have purchased Tailwind UI), do you need me to review or test this so we can push the PR forward in his absence? If, so, let me know what you need. |
Hey @dthyresson! Thanks, you could start reviewing but it's not fully ready yet. It took me some time to understand the testing architecture & helpers and to reorganize the code to make it testable, but now it's just a matter of writing the last few tests ^^ As I'm working on it burst by burst, I might need a few more days before completing everything. I can request you as reviewer once it's done if you'd rather review the full thing at once! |
👍 |
Regarding the stalling tests, I have an intuition this does not come from my own tests, but others from I've been able to run the Github action locally with nektos/act and got the same issue as what's happening here.
There are tens of them, on two tests for the scaffold generator: @Tobbe @dthyresson dunno if you're familiar with those parts of the code? I'll try to run my tests—and only them—within my local Github Actions sim and see how things go; then continue investigating depending on the results 🙂 |
Ohh, I remember having timeout issues when I was messing around with the generators. I think I even PRed an increase in the timeout. Indeed! #845 I never dove deeper into it than that. What happens if you increase it to 20? If so, it might be worth it to see if we can understand exactly why that's needed. Are there new tests added that take longer to run? Or is it just that the total amount of tests have increased? If so, why does that matter? Or is it just that different hardware are slower/faster executing the tests? |
So many questions 😅 |
@olance Yes, this makes sense to me to have four options: v1 without ui, v1 with ui, v2 without ui, and v2 with ui. Those who bought TailwindUI before Tailwind v2 was released still have access to the old TailwindUI code where Tailwind v1 was used. |
Hey there! I'm back 😅 Work has been crazy for weeks, I can finally dive into these failing tests again. I think I've got a fix for the stalled tests, but it might need the scrutiny of @thedavidprice or someone else from the core team maybe? Here goes:
So when running the test file that's not a test file, the search for a To fix this, I have thus corrected the - testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/*.test.[jt]s?(x)'],
+ testMatch: ['**/__tests__/**/*.test.[jt]s?(x)', '**/*.test.[jt]s?(x)'], This worked locally and seems to be a reasonable change. |
@Tobbe looks like the tests aren't being run... had you deactivated something at the PR level when they were stalling? ^^ |
@olance This one seems to have been lost in the black hole of the holidays. Apologies! I'm taking a look at it now. FYI: Tobbe just reworked the command |
@olance OK, I just attempted to merge this with main and handle both conflicts and updates from a recent PR — admittedly it was a hurried process and I have not yet tested the results. But the CI is now running again. @Tobbe just did a huge lift to correct multiple types of path issues. See #1648 I attempted to confirm the changes, now in main, are now reflected in this PR. Please assume I missed things @olance and scrutinize my merge against Tobbe's PR. Especially take a look at the "Add CSS Imports" task and respective code. The tests you've added would be really helpful. You might have some other test ideas based on Tobbe's path work as well. Keep me posted as to what you'd like to do from here. Thanks again! |
FWIW unless i'm wrong this isn't needed anymore. according to upstream it seems that
|
@AntonioMeireles yes, indeed! It's way up in the thread now, but based on that change Olivier was going to take a different approach here. See above: Wanted to see if I could help get that going again. But understood either way. |
ah, ok. missed that bit. OTOH, and while on this not too sure if that is best approach from a UX and from a mantainability PoV... preferable to ship with a "recommended"/close to tip way and allow a plugable / separate 'legacy one' if it really needs to be (i.e. being clearly another option from cli and not just an install flag) with clear warnings that is not that well mantained/etc. otherwise when one bumps postcss/webpack we'll still have a legacy tail to grasp / handle [one completelly EoLed upstream] (/me is just thinking loud) |
Hey there, long time no see 😅 @thedavidprice yeah I think it got kinda "lost", and I became extra busy at work, and with TailwindUI 2 out in the middle of that and the tests failing/stalling mysteriously this PR became much longer and heavier than anticipated, for something that's supposed to be quite simple in the end... Now that time has passed, and following @AntonioMeireles lead, what do you think about simplifying this to just a v2 install? People wanting v1 can do it manually I guess... |
@olance Hey there! Understood how things go and never any expectations otherwise. Just never wanted to put you in the spot of waiting on me. So, about this PR... There have been a lot of changes to the Setup command itself as well as several iterations on That said, I'm not sure about either "if" or "how" to proceed. We have completed step 1 of the new Setup command: move existing, applicable commands under Specific to this PR, I'm not sure if it makes sense to add Tailwind UI as a flag given that we don't know how the Setup command will ultimately handle flags. The other option would be to create a separate command, e.g. Now having written all the above, I think the highest priority here is not the Tailwind UI but helping finish the structure of the Setup command itself (along with the current commands, which can only be run one at a time right now). Welcome any/all thoughts. And, of course, no expectations or pressure. |
Hey! Thanks for the big update! 🙂 Il with you on the priority. Given all that's been going on, focus more energy on this seems wasted/not worth it. I'm OK to close the PR. Regarding this:
I used a tool named phpbrew recently and i loved how easy it was to do exactly that kind of quick setup (but for configure options/libs to be built with the requested PHP version): For instance to build & install PHP 7.3 with xdebug and json support:
In our case, that could be:
(Yeah I find the Then, if you need flags, you can use global ones after
What do you think? |
Wanted to mention this issue on the yargs repo about enabling exactly this kind of structure for the setup command: yargs/yargs#1821. Just to show that it might be implemented one day. But @olance I like that style a lot; the global flags for the command coming before the subcommands also makes sense and is how deno does it. |
To show what we're up against, here's a step-by-step description of tweaking export const command = 'setup <commmand>'
export const description = 'Initialize project config and install packages'
export const handler = (argv) => console.log(argv)
{
_: [ 'setup', '+tailwind' ],
force: '+deploy:netlify',
ui: '+i18n',
fr: true,
'$0': 'rw',
commmand: '+auth:supabase'
} There's a lot of problems with the way this is being parsed. For one, export const command = 'setup <commmand>'
export const description = 'Initialize project config and install packages'
+export const builder = (yargs) => yargs.option('force', { type: 'boolean' })
export const handler = (argv) => console.log(argv) {
_: [ 'setup', '+auth:supabase', '+tailwind' ],
force: true,
ui: '+i18n',
fr: true,
'$0': 'rw',
commmand: '+deploy:netlify'
} Better, but -export const command = 'setup <commmand>'
+export const command = 'setup [commmand..]'
export const description = 'Initialize project config and install packages'
export const builder = (yargs) => yargs.option('force', { type: 'boolean' })
export const handler = (argv) => console.log(argv) {
_: [ 'setup' ],
force: true,
ui: '+i18n',
fr: true,
'$0': 'rw',
commmand: [ '+deploy:netlify', '+auth:supabase', '+tailwind' ]
} Much better! But we still haven't addressed that This is where we start to run up against the limit of what we can do just by tweaking the yargs exports (command/description/builder/handler). So where do we go from here? make it so that the builder knows all the subcommand's optionsWhy don't we just add write some gnarly middleware to reparse argv before it hits the handlerYargs has the concept of middleware; it runs before organizing arguments into nested objects
To see this in action, let's tweak @olance's command string and run it: -yarn rw setup --force +deploy:netlify +auth:supabase +tailwind --ui +i18n --fr
+yarn rw setup --force --deploy netlify --auth supabase --tailwind.ui --i18n.fr _: [ 'setup' ],
force: true,
deploy: 'netlify',
auth: 'supabase',
tailwind: { ui: true },
i18n: { fr: true },
'$0': 'rw'
} That actually looks amazing! We can just iterate through the object properties; the subcommands are already organized with their arguments. To really drive the point home, let's add an option to -yarn rw setup --force --deploy netlify --auth supabase --tailwind.ui --i18n.fr
+yarn rw setup --force --deploy netlify --deploy.data-migrate --auth supabase --tailwind.ui --i18n.fr {
_: [ 'setup' ],
force: true,
deploy: [ 'netlify', { 'data-migrate': true }, { dataMigrate: true } ],
auth: 'supabase',
tailwind: { ui: true },
i18n: { fr: true },
'$0': 'rw'
} That looks near perfect. And our setup command looks like this; it's as vanilla as it gets (I even took out export const command = 'setup'
export const description = 'Initialize project config and install packages'
export const handler = (argv) => console.log(argv)
conclusionSo I'm not sure what to do from here; I just wanted to illustrate that there's a "native" syntax yargs understands. Whether or not we like that syntax is the question now. As @mojombo says, computers should do what we want, so we should probably just pick the syntax we like and code for it. But with the dot syntax, it's a downhill battle/most of the work's already done. |
Woa thanks for the analysis @jtoar ! :) I must say I'm not a fan of this dotted syntax, it looks weird for what we'd want to do... like, does Can't dive into it tonight, but when I see something like this: I'm wondering: couldn't we replace |
FYI I'll explore the above tomorrow! |
@jtoar There you go! 🙂 I've setup a PoC repo here: https://github.com/olance/poc-redwood-yargs-parsing With the following params:
The {
force: true,
deploy: [ 'netlify', { 'migrate-data': true }, { migrateData: true } ],
auth: 'supabase',
tailwind: { ui: true, version: 2 },
i18n: { lang: 'en,fr' },
} The code is pretty simple, it only walks through the args and transforms them to the dotted notation const argv = yargs(processArgs(hideBin(process.argv))).argv function processArgs(argv) {
console.log("Input argv:", argv)
let args = argv.reverse()
let currentScope = null
let newArgs = []
while (args.length > 0) {
let arg = args.pop()
// Beginning a new scope?
if (arg[0] === SCOPE_TOKEN) {
// Extract scope name.
// That would be 'deploy' for '+deploy:netlify' and 'tailwind' for '+tailwind'
// TODO: should we handle multi-level scopes, i.e. +deploy:gcp:cloud-run / +deploy:gcp:appengine? (seems unlikely)
const scopeComponents = arg.substr(1).split(SCOPE_VALUE_SEPARATOR)
currentScope = scopeComponents[0]
// If it's a "parameterized" scope ('+deploy:netlify') we need to issue an arg for the scope value
if (scopeComponents.length === 2) {
newArgs.push(`--${currentScope}=${scopeComponents[1]}`)
}
continue
}
// Down here means we're _within_ a scope, possibly null (global scope)
const argName = arg.substr(2) // Assuming args always start with '--'
let newArg = '--'
if (currentScope !== null) {
newArg += `${currentScope}.`
}
// We now have newArg ==
// -> '--force' for a global '--force' flag
// -> '--tailwind.ui' for something like '+tailwind --ui'
// -> '--i18n.lang=en,fr' for something like '+i18n --lang=en,fr'
newArg += argName
// If the arg needs a value and it's been passed like '--lang en,fr' it's not covered by the above, we need to look
// ahead and consume the next arg if needed
const nextArg = args[args.length - 1]
if (argName.indexOf('=') < 0 && nextArg[0] !== SCOPE_TOKEN && nextArg.substr(0, 2) !== '--') {
newArg += `=${args.pop()}`
}
newArgs.push(newArg)
}
console.log('Transformed argv:', newArgs)
return newArgs
} |
Maybe it's time to take this discussion to some other place? |
moved "test structure" discussion over here: #1913 |
moved "setup command" discussion over here #1930 |
Thanks, all! I'm closing this one out. It might not have been merged, but it's definitely created a lot of momentum. |
Added a
--ui
option to thesetup tailwind
command to automatically setup/configure TailwindUI along with TailwindCSS.👉 It installs
@tailwindcss/ui
and requires it in thetailwind.config.js
configuration file(still missing tests)