-
Notifications
You must be signed in to change notification settings - Fork 194
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Tiexin Guo <guotiexin@gmail.com>
- Loading branch information
1 parent
8ab86a8
commit 266fbef
Showing
2 changed files
with
136 additions
and
133 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,197 +1,200 @@ | ||
# Quick Start | ||
|
||
If you haven't watch the demo yet, see it on the [main page](./index.md). | ||
[Watch the demo](./index.md) first if you prefer to see DevStream in action. | ||
|
||
## 1 Download DevStream (`dtm`) | ||
> Note: currently, we only have Linux and macOS versions of DevStream. Windows support will come later. | ||
Please visit GitHub [Releases](https://github.com/devstream-io/devstream/releases) page and download the appropriate binary according to your operating system and architecture. | ||
In this quickstart, we will do the following automatically with DevStream: | ||
|
||
Note : `dtm` currently doesn't support Windows yet. | ||
- create a GitHub repository with Golang web app scaffolding; | ||
- set up GitHub Actions workflow for the Golang app we created, which contains test and build stages for our Go web app. | ||
|
||
For Linux/Macos users: | ||
## 1 Download | ||
|
||
- rename the downloaded binary to `dtm` and move it to your PATH (e.g.: `mv dtm /usr/local/bin/`) | ||
- grant `dtm` executable permission (e.g.: `chmod a+x dtm`) | ||
|
||
## 2 Prepare a Config File | ||
|
||
Before you start: for an example of DevStream config, see [examples/quickstart.yaml](https://github.com/devstream-io/devstream/blob/main/examples/quickstart.yaml). | ||
Remember to open this configuration file, modify all FULL_UPPER_CASE_STRINGS (like YOUR_GITHUB_USERNAME, for example) in it to your own. Pay attention to the meaning of each item to ensure that it is what you want. For other plugins, checkout the "Plugins" section in our [doc](https://docs.devstream.io) for detailed usage. | ||
|
||
Download the [examples/quickstart.yaml](https://raw.githubusercontent.com/devstream-io/devstream/main/examples/quickstart.yaml) to your working directory: | ||
In your working directory, run: | ||
|
||
```shell | ||
curl -o quickstart.yaml https://raw.githubusercontent.com/devstream-io/devstream/main/examples/quickstart.yaml | ||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/devstream-io/devstream/main/hack/quick-start/quickstart.sh)" | ||
``` | ||
|
||
Then modify the file accordingly. | ||
This will download the `dtm` binary and a `quickstart.yaml` config file to your working directory, and grant the binary execution permission. | ||
|
||
For example, my GitHub username is "IronCore864", and my Dockerhub username is "ironcore864", then I can run: | ||
> Optional: you can then move `dtm` to a place which is in your PATH. For example: `mv dtm /usr/local/bin/`. | ||
```shell | ||
sed -i.bak "s/YOUR_GITHUB_USERNAME_CASE_SENSITIVE/IronCore864/g" quickstart.yaml | ||
## 2 Configuration | ||
|
||
sed -i.bak "s/YOUR_DOCKER_USERNAME/ironcore864/g" quickstart.yaml | ||
``` | ||
As aforementioned, we will handle GitHub repo scaffolding and CI workflows in GitHub Actions, so, we will need the following environment variables (env vars) to be set: | ||
|
||
> This config file uses two plugins, one will create a GitHub repository and bootstrap it into a Golang web app, and the other will create GitHub Actions workflow for it. | ||
- GITHUB_USER | ||
- GITHUB_TOKEN | ||
- DOCKERHUB_USERNAME | ||
|
||
The two plugins, [githubactions-golang](./plugins/githubactions-golang.md) & | ||
[github-repo-scaffolding-golang](./plugins/github-repo-scaffolding-golang.md), require an environment variable to work, so let's set it: | ||
Run the following commands to set values for these env vars (replace values within the double quotes): | ||
|
||
```shell | ||
export GITHUB_TOKEN="YOUR_GITHUB_TOKEN_HERE" | ||
export GITHUB_USER="<YOUR_GITHUB_USER_NAME_HERE>" | ||
export GITHUB_TOKEN="<YOUR_GITHUB_PERSONAL_ACCESS_TOKEN_HERE>" | ||
export DOCKERHUB_USERNAME="<YOUR_DOCKER_HUB_USER_NAME_HERE>" | ||
``` | ||
|
||
If you don't know how to create a GitHub token, check out [the official document here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). | ||
> Note: if you don't know how to get your GITHUB_TOKEN, see this official document "[Creating a personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)." | ||
## 3 Initialize | ||
Then we run the following commands to update our config file with those env vars: | ||
|
||
Run: | ||
For **macOS** or **FreeBSD** based systems: | ||
|
||
```shell | ||
dtm init -f quickstart.yaml | ||
``` | ||
|
||
and you should see similar output to: | ||
|
||
``` | ||
2022-03-04 12:08:06 ℹ [INFO] Initialize started. | ||
2022-03-04 12:08:06 ℹ [INFO] Using dir <.devstream> to store plugins. | ||
2022-03-04 12:08:11 ℹ [INFO] Downloading: [github-repo-scaffolding-golang-darwin-arm64_0.2.0.so] ... | ||
13.52 MiB / 13.52 MiB [=================================] 100.00% 3.14 MiB/s 4s | ||
2022-03-04 12:08:15 ✔ [SUCCESS] [github-repo-scaffolding-golang-darwin-arm64_0.2.0.so] download succeeded. | ||
2022-03-04 12:08:17 ℹ [INFO] Downloading: [githubactions-golang-darwin-arm64_0.2.0.so] ... | ||
16.05 MiB / 16.05 MiB [=================================] 100.00% 5.41 MiB/s 2s | ||
2022-03-04 12:08:20 ✔ [SUCCESS] [githubactions-golang-darwin-arm64_0.2.0.so] download succeeded. | ||
2022-03-04 12:08:20 ✔ [SUCCESS] Initialize finished. | ||
sed -i.bak "s@YOUR_GITHUB_USERNAME_CASE_SENSITIVE@${GITHUB_USER}@g" quickstart.yaml | ||
sed -i.bak "s@YOUR_DOCKER_USERNAME@${DOCKERHUB_USERNAME}@g" quickstart.yaml | ||
``` | ||
|
||
This step verifies the MD5 sum of your dtm binary, downloads the required plugins according to the config file, and verifies the plugins' MD5 sums as well. | ||
|
||
Note: if your dtm binary's MD5 sum doesn't match the MD5 sum from our release page, dtm init will stop. If your local dtm MD5 differs, it indicates that you built the binary yourself (for developing purposes, for example). Due to the nature of the Go plugin, dtm must be built together with the corresponding plugins. So, if you are building dtm, you should also build the plugins as well, in which case, you do not need to run dtm init to download the plugins. | ||
|
||
## 4 Usage Overview | ||
|
||
To apply the config, run: | ||
For **GNU** Linux users: | ||
|
||
```shell | ||
./dtm apply -f YOUR_CONFIG_FILE.yaml | ||
sed -i "s@YOUR_GITHUB_USERNAME_CASE_SENSITIVE@${GITHUB_USER}@g" quickstart.yaml | ||
sed -i "s@YOUR_DOCKER_USERNAME@${DOCKERHUB_USERNAME}@g" quickstart.yaml | ||
``` | ||
|
||
If you don't specify the config file with the "-f" parameter, it will try to use the default value which is "config.yaml" from the current directory. | ||
## 3 Init | ||
|
||
_`dtm` will compare the config, the state, and the resources to decide whether a "create", "update", or "delete" is needed. For more information, read our [Core Concepts documentation here](./core-concepts/core-concepts.md)._ | ||
|
||
The command above will ask you for confirmation before actually executing the changes. To apply without confirmation (like `apt-get -y update`), run: | ||
Run: | ||
|
||
```shell | ||
./dtm -y apply -f YOUR_CONFIG_FILE.yaml | ||
``` | ||
./dtm init -f quickstart.yaml | ||
``` | ||
|
||
and you should see similar output to the following: | ||
|
||
``` | ||
2022-06-30 11:21:48 ℹ [INFO] Got Backend from config: local | ||
2022-06-30 11:21:48 ℹ [INFO] Using dir <.devstream> to store plugins. | ||
2022-06-30 11:21:48 ℹ [INFO] Downloading: [github-repo-scaffolding-golang-darwin-arm64_0.7.0.so] ... | ||
15.05 MiB / 15.05 MiB [================================] 100.00% 21.17 MiB/s 0s | ||
2022-06-30 11:21:49 ✔ [SUCCESS] [github-repo-scaffolding-golang-darwin-arm64_0.7.0.so] download succeeded. | ||
2022-06-30 11:21:49 ℹ [INFO] Downloading: [github-repo-scaffolding-golang-darwin-arm64_0.7.0.md5] ... | ||
33 B / 33 B [==========================================] 100.00% 35.29 KiB/s 0s | ||
2022-06-30 11:21:49 ✔ [SUCCESS] [github-repo-scaffolding-golang-darwin-arm64_0.7.0.md5] download succeeded. | ||
2022-06-30 11:21:49 ℹ [INFO] Plugin: github-repo-scaffolding-golang-darwin-arm64_0.7.0.so doesn't match with .md5 and will be downloaded. | ||
2022-06-30 11:21:49 ℹ [INFO] Downloading: [github-repo-scaffolding-golang-darwin-arm64_0.7.0.so] ... | ||
15.05 MiB / 15.05 MiB [================================] 100.00% 31.25 MiB/s 0s | ||
2022-06-30 11:21:50 ✔ [SUCCESS] [github-repo-scaffolding-golang-darwin-arm64_0.7.0.so] download succeeded. | ||
2022-06-30 11:21:50 ℹ [INFO] Downloading: [github-repo-scaffolding-golang-darwin-arm64_0.7.0.md5] ... | ||
33 B / 33 B [==========================================] 100.00% 43.43 KiB/s 0s | ||
2022-06-30 11:21:50 ✔ [SUCCESS] [github-repo-scaffolding-golang-darwin-arm64_0.7.0.md5] download succeeded. | ||
2022-06-30 11:21:50 ℹ [INFO] Downloading: [githubactions-golang-darwin-arm64_0.7.0.so] ... | ||
17.49 MiB / 17.49 MiB [================================] 100.00% 31.18 MiB/s 0s | ||
2022-06-30 11:21:51 ✔ [SUCCESS] [githubactions-golang-darwin-arm64_0.7.0.so] download succeeded. | ||
2022-06-30 11:21:51 ℹ [INFO] Downloading: [githubactions-golang-darwin-arm64_0.7.0.md5] ... | ||
33 B / 33 B [=========================================] 100.00% 160.70 KiB/s 0s | ||
2022-06-30 11:21:51 ✔ [SUCCESS] [githubactions-golang-darwin-arm64_0.7.0.md5] download succeeded. | ||
2022-06-30 11:21:51 ℹ [INFO] Plugin: githubactions-golang-darwin-arm64_0.7.0.so doesn't match with .md5 and will be downloaded. | ||
2022-06-30 11:21:51 ℹ [INFO] Downloading: [githubactions-golang-darwin-arm64_0.7.0.so] ... | ||
17.49 MiB / 17.49 MiB [================================] 100.00% 31.78 MiB/s 0s | ||
2022-06-30 11:21:52 ✔ [SUCCESS] [githubactions-golang-darwin-arm64_0.7.0.so] download succeeded. | ||
2022-06-30 11:21:52 ℹ [INFO] Downloading: [githubactions-golang-darwin-arm64_0.7.0.md5] ... | ||
33 B / 33 B [==========================================] 100.00% 87.12 KiB/s 0s | ||
2022-06-30 11:21:52 ✔ [SUCCESS] [githubactions-golang-darwin-arm64_0.7.0.md5] download succeeded. | ||
2022-06-30 11:21:52 ✔ [SUCCESS] Initialize finished. | ||
``` | ||
|
||
## 4 Apply | ||
|
||
To delete everything defined in the config, run: | ||
Run: | ||
|
||
```shell | ||
./dtm delete -f YOUR_CONFIG_FILE.yaml | ||
./dtm apply -f quickstart.yaml | ||
``` | ||
|
||
_Note that this deletes everything defined in the config. If some config is deleted after apply (state has it but config not), `dtm delete` won't delete it. It differs from `dtm destroy`._ | ||
|
||
Similarly, to delete without confirmation: | ||
When it prompts: | ||
|
||
```shell | ||
./dtm -y delete -f YOUR_CONFIG_FILE.yaml | ||
...(omitted) | ||
Continue? [y/n] | ||
Enter a value (Default is n): | ||
``` | ||
To delete everything defined in the config, regardless of the state: | ||
|
||
```shell | ||
./dtm delete --force -f YOUR_CONFIG_FILE.yaml | ||
``` | ||
input `y` and hit the enter key. | ||
|
||
To verify, run: | ||
You should see similar output to the following | ||
|
||
```shell | ||
./dtm verify -f YOUR_CONFIG_FILE.yaml | ||
``` | ||
|
||
To destroy everything, run: | ||
2022-06-30 11:25:47 ℹ [INFO] Apply started. | ||
2022-06-30 11:25:47 ℹ [INFO] Got Backend from config: local | ||
2022-06-30 11:25:47 ℹ [INFO] Using dir <.devstream> to store plugins. | ||
2022-06-30 11:25:47 ℹ [INFO] Using local backend. State file: devstream.state. | ||
2022-06-30 11:25:47 ℹ [INFO] Tool (github-repo-scaffolding-golang/default) found in config but doesn't exist in the state, will be created. | ||
2022-06-30 11:25:47 ℹ [INFO] Tool (githubactions-golang/default) found in config but doesn't exist in the state, will be created. | ||
Continue? [y/n] | ||
Enter a value (Default is n): y | ||
|
||
```shell | ||
./dtm destroy -f YOUR_CONFIG_FILE.yaml | ||
2022-06-30 11:26:20 ℹ [INFO] Start executing the plan. | ||
2022-06-30 11:26:20 ℹ [INFO] Changes count: 2. | ||
2022-06-30 11:26:20 ℹ [INFO] -------------------- [ Processing progress: 1/2. ] -------------------- | ||
2022-06-30 11:26:20 ℹ [INFO] Processing: (github-repo-scaffolding-golang/default) -> Create ... | ||
2022-06-30 11:26:24 ℹ [INFO] The repo go-webapp-devstream-demo has been created. | ||
2022-06-30 11:26:37 ✔ [SUCCESS] Tool (github-repo-scaffolding-golang/default) Create done. | ||
2022-06-30 11:26:37 ℹ [INFO] -------------------- [ Processing progress: 2/2. ] -------------------- | ||
2022-06-30 11:26:37 ℹ [INFO] Processing: (githubactions-golang/default) -> Create ... | ||
2022-06-30 11:26:38 ℹ [INFO] Creating GitHub Actions workflow pr-builder.yml ... | ||
2022-06-30 11:26:38 ✔ [SUCCESS] Github Actions workflow pr-builder.yml created. | ||
2022-06-30 11:26:38 ℹ [INFO] Creating GitHub Actions workflow main-builder.yml ... | ||
2022-06-30 11:26:39 ✔ [SUCCESS] Github Actions workflow main-builder.yml created. | ||
2022-06-30 11:26:39 ✔ [SUCCESS] Tool (githubactions-golang/default) Create done. | ||
2022-06-30 11:26:39 ℹ [INFO] -------------------- [ Processing done. ] -------------------- | ||
2022-06-30 11:26:39 ✔ [SUCCESS] All plugins applied successfully. | ||
2022-06-30 11:26:39 ✔ [SUCCESS] Apply finished. | ||
``` | ||
|
||
_`dtm` will read the state, then determine which tools are installed, and then remove those tools. It's same as `dtm apply -f empty.yaml` (empty.yaml is an empty config file)._ | ||
|
||
## 5 Apply | ||
|
||
Run: | ||
## 5 Check the Results | ||
|
||
```shell | ||
dtm apply -f quickstart.yaml | ||
``` | ||
Go to your GitHub repositories list and you can see the new repo `go-webapp-devstream-demo` has been created. | ||
|
||
and confirm to continue, then you should see similar output to: | ||
There is scaffolding code for a Golang web app in it, with GitHub Actions CI workflow set up properly. | ||
|
||
``` | ||
2022-03-04 12:08:54 ℹ [INFO] Apply started. | ||
2022-03-04 12:08:54 ℹ [INFO] Using dir <.devstream> to store plugins. | ||
2022-03-04 12:08:54 ℹ [INFO] Tool < go-webapp-repo > found in config but doesn't exist in the state, will be created. | ||
2022-03-04 12:08:54 ℹ [INFO] Tool < golang-demo-actions > found in config but doesn't exist in the state, will be created. | ||
Continue? [y/n] | ||
Enter a value (Default is n): y | ||
2022-03-04 12:08:57 ℹ [INFO] Start executing the plan. | ||
2022-03-04 12:08:57 ℹ [INFO] Changes count: 2. | ||
2022-03-04 12:08:57 ℹ [INFO] -------------------- [ Processing progress: 1/2. ] -------------------- | ||
2022-03-04 12:08:57 ℹ [INFO] Processing: go-webapp-repo -> Create ... | ||
2022-03-04 12:09:04 ℹ [INFO] Repo created. | ||
2022-03-04 12:09:22 ✔ [SUCCESS] Plugin go-webapp-repo Create done. | ||
2022-03-04 12:09:22 ℹ [INFO] -------------------- [ Processing progress: 2/2. ] -------------------- | ||
2022-03-04 12:09:22 ℹ [INFO] Processing: golang-demo-actions -> Create ... | ||
2022-03-04 12:09:23 ℹ [INFO] Language is: go-1.18. | ||
2022-03-04 12:09:23 ℹ [INFO] Creating GitHub Actions workflow pr-builder.yml ... | ||
2022-03-04 12:09:24 ✔ [SUCCESS] Github Actions workflow pr-builder.yml created. | ||
2022-03-04 12:09:25 ℹ [INFO] Creating GitHub Actions workflow main-builder.yml ... | ||
2022-03-04 12:09:26 ✔ [SUCCESS] Github Actions workflow main-builder.yml created. | ||
2022-03-04 12:09:26 ✔ [SUCCESS] Plugin golang-demo-actions Create done. | ||
2022-03-04 12:09:26 ✔ [SUCCESS] All plugins applied successfully. | ||
2022-03-04 12:09:26 ✔ [SUCCESS] Apply finished. | ||
``` | ||
## 6 Check the Results | ||
The commits (made by DevStream when scaffolding the repo and creating workflows) have triggered the CI, and the workflow has finished successfully, as shown in the screenshot below: | ||
|
||
Go to your GitHub account, and we can see a new repo named "go-webapp-devstream-demo" has been created; there are some Golang web app scaffolding lying around already, and the GitHub Actions for building the app is also ready. Hooray! | ||
![](./images/repo-scaffolding.png) | ||
|
||
## 7 Clean Up | ||
## 6 Clean Up | ||
|
||
Run: | ||
|
||
```shell | ||
dtm destroy -f quickstart.yaml | ||
./dtm delete -f quickstart.yaml | ||
``` | ||
|
||
and you should see similar output: | ||
input `y` the same just like you did in the previous steps, and you should see similar output: | ||
|
||
``` | ||
2022-03-04 12:10:36 ℹ [INFO] Destroy started. | ||
2022-03-04 12:10:36 ℹ [INFO] Change added: go-webapp-repo_github-repo-scaffolding-golang -> Delete | ||
2022-03-04 12:10:36 ℹ [INFO] Change added: golang-demo-actions_githubactions-golang -> Delete | ||
2022-06-30 11:31:01 ℹ [INFO] Delete started. | ||
2022-06-30 11:31:01 ℹ [INFO] Got Backend from config: local | ||
2022-06-30 11:31:01 ℹ [INFO] Using dir <.devstream> to store plugins. | ||
2022-06-30 11:31:01 ℹ [INFO] Using local backend. State file: devstream.state. | ||
2022-06-30 11:31:01 ℹ [INFO] Tool (githubactions-golang/default) will be deleted. | ||
2022-06-30 11:31:01 ℹ [INFO] Tool (github-repo-scaffolding-golang/default) will be deleted. | ||
Continue? [y/n] | ||
Enter a value (Default is n): y | ||
2022-03-04 12:10:38 ℹ [INFO] Start executing the plan. | ||
2022-03-04 12:10:38 ℹ [INFO] Changes count: 2. | ||
2022-03-04 12:10:38 ℹ [INFO] -------------------- [ Processing progress: 1/2. ] -------------------- | ||
2022-03-04 12:10:38 ℹ [INFO] Processing: go-webapp-repo -> Delete ... | ||
2022-03-04 12:10:40 ✔ [SUCCESS] GitHub repo go-webapp-devstream-demo removed. | ||
2022-03-04 12:10:40 ℹ [INFO] Prepare to delete 'go-webapp-repo_github-repo-scaffolding-golang' from States. | ||
2022-03-04 12:10:40 ✔ [SUCCESS] Plugin go-webapp-repo delete done. | ||
2022-03-04 12:10:40 ℹ [INFO] -------------------- [ Processing progress: 2/2. ] -------------------- | ||
2022-03-04 12:10:40 ℹ [INFO] Processing: golang-demo-actions -> Delete ... | ||
2022-03-04 12:10:40 ℹ [INFO] language is go-1.18. | ||
2022-03-04 12:10:41 ✔ [SUCCESS] Github Actions workflow pr-builder.yml already removed. | ||
2022-03-04 12:10:42 ✔ [SUCCESS] Github Actions workflow main-builder.yml already removed. | ||
2022-03-04 12:10:42 ℹ [INFO] Prepare to delete 'golang-demo-actions_githubactions-golang' from States. | ||
2022-03-04 12:10:42 ✔ [SUCCESS] Plugin golang-demo-actions delete done. | ||
2022-03-04 12:10:42 ✔ [SUCCESS] All plugins destroyed successfully. | ||
2022-03-04 12:10:42 ✔ [SUCCESS] Destroy finished. | ||
``` | ||
2022-06-30 11:31:03 ℹ [INFO] Start executing the plan. | ||
2022-06-30 11:31:03 ℹ [INFO] Changes count: 2. | ||
2022-06-30 11:31:03 ℹ [INFO] -------------------- [ Processing progress: 1/2. ] -------------------- | ||
2022-06-30 11:31:03 ℹ [INFO] Processing: (githubactions-golang/default) -> Delete ... | ||
2022-06-30 11:31:04 ℹ [INFO] Deleting GitHub Actions workflow pr-builder.yml ... | ||
2022-06-30 11:31:05 ✔ [SUCCESS] GitHub Actions workflow pr-builder.yml removed. | ||
2022-06-30 11:31:05 ℹ [INFO] Deleting GitHub Actions workflow main-builder.yml ... | ||
2022-06-30 11:31:06 ✔ [SUCCESS] GitHub Actions workflow main-builder.yml removed. | ||
2022-06-30 11:31:06 ℹ [INFO] Prepare to delete 'githubactions-golang_default' from States. | ||
2022-06-30 11:31:06 ✔ [SUCCESS] Tool (githubactions-golang/default) delete done. | ||
2022-06-30 11:31:06 ℹ [INFO] -------------------- [ Processing progress: 2/2. ] -------------------- | ||
2022-06-30 11:31:06 ℹ [INFO] Processing: (github-repo-scaffolding-golang/default) -> Delete ... | ||
2022-06-30 11:31:06 ✔ [SUCCESS] GitHub repo go-webapp-devstream-demo removed. | ||
2022-06-30 11:31:06 ℹ [INFO] Prepare to delete 'github-repo-scaffolding-golang_default' from States. | ||
2022-06-30 11:31:06 ✔ [SUCCESS] Tool (github-repo-scaffolding-golang/default) delete done. | ||
2022-06-30 11:31:06 ℹ [INFO] -------------------- [ Processing done. ] -------------------- | ||
2022-06-30 11:31:06 ✔ [SUCCESS] All plugins deleted successfully. | ||
2022-06-30 11:31:06 ✔ [SUCCESS] Delete finished. | ||
``` | ||
|
||
Now if you check your GitHub repo list again, everything has been nuked by DevStream. Hooray! | ||
|
||
> Optional: you can also remove the DevStream state file (which should be empty now) by running: `rm devstream.state`. |