Skip to content
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 "default" Option for "external" Environment Vars #989

Merged
merged 3 commits into from
Jan 9, 2024
Merged

Add "default" Option for "external" Environment Vars #989

merged 3 commits into from
Jan 9, 2024

Conversation

ObliviousHarmony
Copy link
Contributor

There may be cases where a caller doesn't want to pass an "external" environment variable. In those cases, rather than relying on the script to handle the default case, wireit can support a "default" option. This option is used when no value is passed for an "external" variable.

There may be cases where a caller doesn't want to pass an "external"
environment variable. In those cases, rather than relying on the script
to handle the default case, `wireit` can support a "default" option.
This option is used when no value is passed for an "external" variable.
@aomarks
Copy link
Member

aomarks commented Dec 11, 2023

Hi @ObliviousHarmony! Could you elaborate a bit? I think I'm missing something. Maybe an example?

@ObliviousHarmony
Copy link
Contributor Author

Thanks for the prompt reply @aomarks!

There are some cases where you may have tasks that are nearly identical except for an environment variable being different. This can be solved by using "external", however, if you do that your script either needs to handle a default case or any caller needs to set the environment variable. By setting a default you can remove the need for superfluous environment variables set in scripts when they aren't needed. As a more tangible example, here are three configuration files that all do the same thing when you run build and build:dev.

Separate Commands

{
	"scripts": {
		"build": "wireit",
		"build:dev": "wireit"
	},
	"wireit": {
		"build": {
			"command": "webpack",
			"env": {
				"NODE_ENV": "development"
			}
		},
		"build:dev": {
			"command": "webpack",
			"env": {
				"NODE_ENV": "production"
			}
		}
	}
}

Extra Command

{
	"scripts": {
		"build": "cross-env NODE_ENV=production npm run build:real",
		"build:dev": "cross-env NODE_ENV=development npm run build:real",
		"build:real": "wireit"
	},
	"wireit": {
		"build:real": {
			"command": "webpack",
			"env": {
				"NODE_ENV": {
					"external": true
				}
			}
		}
	}
}

With "default" Option

{
	"scripts": {
		"build": "wireit",
		"build:dev": "cross-env NODE_ENV=development npm run build"
	},
	"wireit": {
		"build": {
			"command": "webpack",
			"env": {
				"NODE_ENV": {
					"external": true,
					"default": "production"
				}
			}
		}
	}
}

At least in our use-case, the only difference in build scripts come from environment variables. In my opinion this feature makes the configuration easier to maintain without adding unnecessary commands and superfluous environment variables. This even becomes more tedious with extra environment variables that are sometimes set and sometimes not.

@ObliviousHarmony
Copy link
Contributor Author

Any follow-up here @aomarks?

@aomarks
Copy link
Member

aomarks commented Dec 19, 2023

I think your idea makes sense. So the 3 patterns are:

  1. Use FOO in the fingerprint:
{
  "env": {
    "FOO": {
      "external": true
    }
  }
}
  1. Set FOO to "bar" and use it in the fingerprint:
{
  "env": {
    "FOO": "bar"
  }
}
  1. Set FOO to "bar", unless it's already set to something, and in either case use it in the fingerprint:
{
  "env": {
    "FOO": {
      "external": true,
      "default": "foo"
    }
  }
}

What would this case mean? It could either be an error, it could act like 2, or it could add like 3. I wonder if calling it "value" and making it act like 2 would make sense?

{
  "env": {
    "FOO": {
      "default": "foo"
    }
  }
}

@ObliviousHarmony
Copy link
Contributor Author

When we consider that the object value of environment variables comes across as configuration options for it, I think a "value" option that behaves like "FOO": "bar" makes the most sense @aomarks. I'd be agreeable to this change.

@ObliviousHarmony
Copy link
Contributor Author

I took another look today and "value" feels a little confusing. The name "value" when paired with "external" doesn't have as clear a meaning as "default". At the same time, "default" without "external" also isn't clear because it isn't so much a default as it is the value.

I actually think it might be better to provide an error for #3 @aomarks. Since this PR currently provides an error in that way, I'm happy with this PR as-is.

@ObliviousHarmony
Copy link
Contributor Author

Any thoughts @aomarks?

@aomarks
Copy link
Member

aomarks commented Jan 9, 2024

I took another look today and "value" feels a little confusing. The name "value" when paired with "external" doesn't have as clear a meaning as "default". At the same time, "default" without "external" also isn't clear because it isn't so much a default as it is the value.

I actually think it might be better to provide an error for #3 @aomarks. Since this PR currently provides an error in that way, I'm happy with this PR as-is.

Yeah, that makes sense to me. And I agree that this code will already error in the way we discussed. Thanks for the PR, merging!

@aomarks aomarks enabled auto-merge (squash) January 9, 2024 19:18
@ObliviousHarmony
Copy link
Contributor Author

I merged trunk to fix the CI issues @aomarks.

@aomarks aomarks merged commit 8560882 into google:main Jan 9, 2024
11 checks passed
@ObliviousHarmony ObliviousHarmony deleted the add/external-env-var-default branch January 10, 2024 19:44
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