{"id":"fxllencode/devops-rblx-tutorial","name":"devops-rblx-tutorial","scope":"fxllencode","platform":"roblox","description":"Mirrored from the Wally registry.","version":"1.0.1","latest":"1.0.1","versions":["0.1.0","1.0.0","1.0.1"],"license":"MIT","licenseRating":"safe","licenseCaveats":["License identified from the packaged LICENSE file; the manifest declared none."],"licenseVerified":true,"dependencies":{},"integrity":"97d9354373deee3154f91abdb4bed82ba3f29a367a9d57870b756786e01da520","likes":0,"downloads":0,"install":"forest install fxllencode/devops-rblx-tutorial","url":"https://forest.dev/p/roblox/fxllencode/devops-rblx-tutorial","files":"https://api.forest.dev/ai/package/roblox/fxllencode/devops-rblx-tutorial/files","readme":"<div align=center>\n\n# Creating a proper Open-Source Project with DevOps!\n\n\nTutorial on how to create a proper open-source project to support many platforms, powered by Rojo, GitHub actions, Wally, and more!\n\n\n\n</div>\n\n## Table of Contents\n\n- [Creating a proper Open-Source Project with DevOps!](#creating-a-proper-open-source-project-with-devops)\n  - [Table of Contents](#table-of-contents)\n  - [Introduction](#introduction)\n  - [Step 1: Setting up and installing Foreman](#step-1-setting-up-and-installing-foreman)\n    - [Adding PATH - `*nix` systems.](#adding-path---nix-systems)\n    - [Add PATH - Windows](#add-path---windows)\n  - [Step 2 - Project Structure and Foreman Setup](#step-2---project-structure-and-foreman-setup)\n  - [Step 3 - Setting up our Rojo project](#step-3---setting-up-our-rojo-project)\n  - [Step 4 - Developing with Rojo](#step-4---developing-with-rojo)\n  - [Step 5 - Setting up Wally (Optional)](#step-5---setting-up-wally-optional)\n  - [Step 6 - Setting up StyLua and Selene](#step-6---setting-up-stylua-and-selene)\n  - [Step 7 - Creating our DevOps workflow!](#step-7---creating-our-devops-workflow)\n  - [Conclusion](#conclusion)\n\n\n## Introduction \n\nI've created this tutorial because of how useful I found it in creating an open-source package that supports nearly every platform! \n\nAs someone who loves to use 3rd party tools such as Rojo, one of the problems I've had is with people who want to use my package, but do not use Rojo or do not understand how to compile the code for themselves, so I strived to add support for adding an `.rbxm` file, so users can drag and drop. However, this complicated things. As someone who is passionate about DevOps, I like to automate my entire developmnt process.\n\nAnd so, this tutorial exists!\n\n## Step 1: Setting up and installing Foreman\n\n**If you already have foreman installed, you can skip this step!**\n\n\n\n\nForeman is a toolchain manager for Roblox, similar to `rustup`. Because of the amount of tools that we may use, it is a good idea to install `Foreman` to make it easier to manage! \n\nFirst, make sure you have [Rust](https://www.rust-lang.org/) 1.53.0 or greater installed, as we will be installing Foreman from `cargo`. \n\nTo install, simply run:\n\n```\ncargo install foreman\n```\n\nAfter this completes, you will need to add the `.bin` to your `PATH` variable.\n\n### Adding PATH - `*nix` systems.\n\nOn `*nix` systems, you will need to open your enviromental variable file. On bash, run the following commands:\n\n```\nsudo nano ~/.bashrc\n```\n\nOnce `nano` is opened, you will see a lot of items in `nano`.\n\nScroll all the way to the bottom, and add the following line:\n\n```\nexport PATH=\"$HOME/.foreman/bin/wally/:$PATH\"\n```\n\nThen, close and safe the file by using <kbd> CTRL </kbd> + <kbd> X </kbd>, then ensure you hit <kbd> Y </kbd> and then <kbd> ENTER </kbd>\n\nFinally, restart your terminal or set it's source with:\n\n```\nsource ~/.bashrc\n```\n\n### Add PATH - Windows\n\nTo add Foreman to your `PATH` variable on Windows, first open your search, and search for `Enviormental Variables`\n\nAfter you do this, a panel will open. At the bottom, you will see `Enviormental Variables`\n\nWhen the next UI opens, scroll down to `System Variables`\n\nIf you see a Variable called `PATH`, hit `Edit`. Otherwise, hit `New`\n\nA new UI will open if you are editing, with a lot of other file paths. To the right, hit `New`, and you will have the option to add a variable to your `PATH`\n\nFinally, hit `Browse Directory`, and look for where `cargo` installed foreman. Once found, browse to `.foreman/bin`, and select that. Hit `OK`, and you are done!\n\nMake sure you restart all terminal instances that are open. \n\nTo test, run `foreman --help`. A menu should come up! If one did not, repeat the steps above.\n\n## Step 2 - Project Structure and Foreman Setup\n\nNow that we have Foreman installed, it is time to setup our project. \n\nFor our project structure, we will follow something similar to this:\n\n![image](https://lh3.googleusercontent.com/KLZ8xgBuGMVSq5xon_dGMAaRVBa1pgm8pzwFfJsLwz_332qz75394TLrkSODniKr2l-fkeWJBKBoKIr4GiQyuckzP3i_KWb0xYhMSlTzuX5pOZdBhV-uEvEOeuYE-z0y67vSs7JzrqOE_9KpXULQrQRQa_XNVEw-lwfd8EIpNNHduK2M0ZRkPbIV8CzC8wkCO6QC9o0Cqa3FtQXHE9SqbQr6BweqG1Cj7n60_opiUN07S7VHlqbAtM6I1-JvgckYYvWc3B60rAx4kN8RXRjQ7MXmwlQC55OMsnlBOsNKGT7QA0i2pbpCsN28FEQV5OuglYiIJ0EVVud-h7xZx68jMne65DKYdywQOfGpmgOuFuP1pILbdQTmK_31Mf3nZQPLsPc2D3BXRBOoOe2ZTbDk79Cr-btSExWSOS2RSNwXRVbmX7NXtCZi9olrsipQbeXKtBzuKeYlDAtvjhvsJYOOG40bLm1QB8vQm14pngH2A2rZrcwqIvS20EjyckQI6dh0-94NsJeaawP2o2naEAMwZEoAQL6fNSVqDiw86_3Y8I480THrUeFjMmNKxzEiSyRbz2dLfVpV_vVq19wtYKd-rkAn_IKktu62Q2-CNrmX57nb5rwX83EIBrpNA-5jhXKBNA8vbmOwZWuBfc-MbNI5VTYqoLfgbMT2uCabymWrQgp0n5TnFFfXJVQ7eZS5rLkbTLuDfcOxacb5VTbl3Q6G_DZTAL0y-trgpYebGj6CaYCqbqmy3xn4fiwXeSE-=w890-h551-no?authuser=0)\n\n\nWe need to create our repository! \n\nFirst, create a new GitHub project, and make sure it's public. Add your preferred license. \n\nNext, clone your `git` repository and open it with your preferred text editor. I'll be use VSCode, but you can use whatever you want!\n\nWe are going to create a few folders in our directory:\n\n* `.github/workflows`\n* `Include`\n* `lib`\n* `testing`\n* `Packages`\n\nYou'll also want a `README.md` file, and a `.gitignore` file. Make sure to add `Packages` to your `.gitignore` file!\n\nFinally, we need to setup our tools, which will be installed via `Foreman`\n\nCreate a new file called `foreman.toml`.\n\nFor this tutorial, will we be using `Rojo`, `Wally`, `Stylua`, and `Selene`. There are many other tools available, but for the scope of this tutorial, this is it! Inside the file, write:\n\n```toml\n[tools]\nrojo = { github = \"rojo-rbx/rojo\", version = \"7.0.0\" }\nwally = { source = \"UpliftGames/wally\", version = \"0.3.1\" }\nstylua = { source = \"JohnnyMorganz/stylua\", version = \"0.13.1\" }\nselene = { source = \"Kampfkarren/selene\", version = \"=0.9.2\" }\n```\n\nAfter you've saved the file, you need to install the tools. Run:\n\n```\nforeman install\n```\n\nand wait for the tools to install. You can confirm they installed by running `foreman list`. Make sure all the tools listed above work by testing `Rojo`:\n\n```\nrojo --version\n```\n\nJust as listed above, you should see the following output:\n\n```\nRojo 7.0.0\n```\n\nCongrats! You've now installed the tools we will use for this tutorial!\n\n## Step 3 - Setting up our Rojo project\n\nTo being setting up our `rojo` project, run `rojo init`. \n\nThis will add a `src` directory, a `default.project.json` file, and update your `.gitignore` file with some more information.\n\nBegin by deleting the `src` directory, as we will be using the `lib` directory instead.\n\nNext, we will update our `default.project.json` file, but before, I urge you to read and understand how `rojo` project's work. They have great documentation, I suggest reading this before continuing: \n\nhttps://rojo.space/docs/v7/project-format/\n\nOur `default.project.json` is rarely going to be used, so replace the contents with the following:\n\n```json\n{\n  \"name\": \"[PROJECT_NAME_HERE]\",\n  \"tree\": {\n    \"$path\": \"lib\"\n  }\n}\n```\n\nHowever, we need to add multiple other files here, as well. \n\nCreate a `testing.project.json` and `pack.project.json`.\n\nThe `testing` file structure is how you can test your code in studio. I've found one issue I used to have with creating packages is the ability to test the code, so by doing this, we can easily test our own code.\n\nThe `pack` file will be used later on to pack our source code into a `.rbxm` file, so it can be dragged and dropped by a non-rojo/wally user. \n\n`testing.project.json`\n```json\n{\n    \"name\": \"[PROJECT_NAME] testing\",\n    \"tree\": {\n      \"$className\": \"DataModel\",\n      \"ReplicatedStorage\": {\n        \"$className\": \"ReplicatedStorage\",\n        \"[PROJECT_NAME]\": {\n            \"$path\": \"Include/Linking.lua\",\n            \"Packages\": {\n                \"$path\": \"Packages\",\n                \"[PROJECT_NAME]\": {\n                    \"$path\": \"lib\"\n                }        \n              }\n        \n      }\n       \n      },\n      \"ServerScriptService\": {\n          \"$className\": \"ServerScriptService\",\n          \"Server\": {\n            \"$path\": \"testing\"\n          }\n      }\n    }\n    \n  }\n  ```\n\n  `pack.project.json`\n  ```json\n  {\n    \"name\": \"[PROJECT_NAME]\",\n    \"tree\": {\n      \"$path\": \"Include/Linking.lua\",\n      \"Packages\": {\n        \"$path\": \"Packages\",\n        \"[PROJECT_NAME]\": {\n            \"$path\": \"lib\"\n        }        \n      }\n    }\n  }\n  ```\n\nGreat! That's all done! :D\n\nFinally, let's set up the rest of our files. For my example, we are making a very simple module that prints out a name when given.\n\nTo begin, let's create our linking script. This is really important to ensure our project is packed correctly, especially if you add a dependency from `Wally`, as we need this dependency to get packed in our `.rbxm` file.\n\nThe structure looks like this:\n\n`Include/Linking.lua`\n```lua\nreturn require(script.Packages[\"[PACKAGE_NAME]\"])\n```\n\nIn my example, I have the following:\n\n```lua\nreturn require(script.Packages[\"hello_world\"])\n```\n\nNext, let's create our basic module! If you have your own module, this is the place to put it. Please ensure the main entry point into your module is named `init.lua`! This is extremely important! \n\n`init.lua`\n```lua\nlocal module = {}\n\nfunction module.welcome(string) \n\nreturn (\"Hello, \" .. string .. \"!\") \n\nend\n\nreturn module\n```\n\nGreat! We now have a module setup, but we have no way of ensuring it works. Let's create a test script under the `testing` folder. In my case, I named it `script.server.lua`. \n\n`script.server.lua`\n```lua\nlocal hello_world = require(game.ReplicatedStorage.hello_world)\n\nprint(hello_world.welcome(\"world\"))\n```\nBy doing this, we will test to make sure our module works as intended! \n\nCongratulations, you've set up your `Rojo` project! In the next section, I'll explain how to work with Rojo in the development process.\n\n## Step 4 - Developing with Rojo\n\nFor most people, developing without actively testing is not going to work well. To combat this, we will use Rojo's syncing feature, so you can develop in your text editor, while still seeing the update in your studio instance.\n\nIf you are on Windows, you can install the `Rojo 7` plugin via:\n```\nrojo plugin install\n```\n\nOtherwise, install the plugin via the Roblox marketplace. Please ensure you are using `Rojo 7`! Otherwise, it will not work.\n\nOnce installed into your studio, find it in your plugins bar and click on it.\n\nTo begin a live syncing session (in which your changes you make in your editor go right to studio) run the following command:\n\n```\nrojo serve testing.project.json\n```\n\nThis will then start up a server on the `Rojo` designated port! By running this, you can easily test your changes in real-time in studio! Once you hit `Connect` in the plugin inside of studio, you can then run the game, and if your code works, everything is all good now! \n\nIf you prefer to pack your code and dependencies into a `.rbxm` file, you can do this using the `rojo build` command.\n\nFirst, add the following entry into your `.gitignore` file:\n\n```\npack.rbxm\n```\n\nThis will ensure you do not commit your built `.rbxm` direcly to your project! (We will handle this in the CI/CD pipeline.)\n\nTo build the file, run:\n\n```\nrojo build -o pack.rbxm pack.project.json\n```\n\nYou can then drop that `.rbxm` into studio! Please note that does not add testing files, but the module and it's dependencies. The **only** way to test is by serving to studio!\n\n\n## Step 5 - Setting up Wally (Optional)\n\nIf we want to publish our package to `Wally` (which you should do!), we need to initalize `Wally` in our project. Run:\n\n```\nwally init\n``` \n\nin your terminal to create a `wally.toml` file.\n\nNext, open the newly created file. The basic structure of `Wally` is as follows:\n\n```toml\n[package]\nname = \"fxllencode/devops-rblx-tutorial\"\nversion = \"0.1.0\"\nregistry = \"https://github.com/UpliftGames/wally-index\"\nrealm = \"shared\"\n\n[dependencies]\n```\n\nFor more information and keys, check out the Wally documentation:\n\nhttps://github.com/UpliftGames/wally#manifest-format\n\nFor this tutorial, set the `name` key to your GitHub name + your package name. This is how people will install your package. Then, edit the `SemVer` code to whatever version your package is on. Package format uses the `SemVer` standard, so numbers are `Major.Minor.Patch`. \n\nDo not edit the registry or realm as that is out of the scope of this tutorial. \n\nOnce we have set this up, we need to setup our auth tokens for deployment to the registry. Begin with:\n\n```\nwally login\n``` \n\nand follow the propmts given. Once this is complete, we need to get the token from the internal file. \n\nNavigate to your `Wally` installation (usually  `%userprofile%\\.wally\\auth.toml` on Windows or `~/.wally/auth.toml` on Linux) and open it using a text editor.\n\nYou should see the following:\n```toml\n# This is where Wally stores details for authenticating with registries.\n# It can be updated using `wally login` and `wally logout`.\n\n[tokens]\n\"https://api.wally.run/\" = \"[REDACTED]\"\n```\n\nIf you properly logged in, you should see a token inside the quotes. Copy that token, and open your GitHub repository on the website. \n\nGo to your repository settings -> secrets -> actions -> new repository secret.\n\n\nCreate a new secret with the name `WALLY_AUTH_TOKEN` and a value of what you copied, and hit \"Add secret\". That's it! Do not login or logout of Wally after you have done that. We will handle publishing in our CI/CD workflow. \n\n## Step 6 - Setting up StyLua and Selene\n\nWhen creating a codebase, code styling is very important. We want to ensure that your code is readable and does not contain flaws regardless of who contributes to the code or not. This is where `Selene` and `StyLua` come into play! `Selene` is a rust-based linter for Luau, that can help detect codebase issues. `StyLua` will format your Lua code to ensure the style is the same around the board. \n\nFirst, let's setup `StyLua`. To ensure it was installed via `Foreman`, run:\n\n```\nstylua --version\n```\n\nin the terminal.\n\nYou should see:\n\n```\nstylua 0.13.1\n```\n\nNext, let's format our module! Keep in mind that we will not be formatting our `testing` foldler as it is meant for testing, and people will not be downloading it, so it's style does not matter.\n\nTo style your module, run:\n\n```\nstylua lib\n```\n\nYour code is now formatted according to the `StyLua` standards! Great! Next, let's lint our code and check it for errors. To start, we need to ensure we have `selene` installed. Run the following commmand:\n\n```\nselene --version\n```\n\nYour output should be:\n\n```\nselene 0.9.2\n```\n\nNext, we need to generate the Roblox-std library.\n\n```\nselene generate-roblox-std\n```\n\nThis should create a new file, `roblox.toml`. Finally, create a new file called `selene.toml`, and add the following contents:\n\n```toml\nstd = \"roblox\"\n```\n\nFinally, let's lint our library:\n\n```\nselene lib\n```\n\nIf there is no output, we are good! However, if you see an output, you should follow it's suggestion to improve your code.\n\nWe now have fully setup linting and style guides!\n\n## Step 7 - Creating our DevOps workflow!\n\nNow that we have the basis for our module, we should start automating things! \n\nWe will have one workflow, our CI workflow. This workflow has 2 parts, one runs on commit to main branch, and one runs on the dev branch. (You should never commit to main until the code is production ready as this will deploy it to Wally and create a release!)\n\nTo start, enter your `.github/workflows` folder and create a new file called `CI.yaml`. This workflow will be the heart of our DevOps workflow! \n\nAn example workflow is below:\n`CI.yaml`\n```yaml\nname: Releases\n\non: push\n\njobs: \n\n  deploy:\n    if: ${{ github.ref == 'refs/heads/main' }}\n    runs-on: ubuntu-latest\n\n\n    steps:\n      - name: Checkout Main\n        uses: actions/checkout@v3\n\n      - name: Setup Foreman\n        uses: Roblox/setup-foreman@v1\n        with: \n          token: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Install Foreman Toolch","readmeTruncated":true,"readmeFull":"https://api.forest.dev/v1/package/fxllencode/roblox/devops-rblx-tutorial/1.0.1/readme"}