(on spotty Internet, from anywhere, collaboratively, rapidly)
- Use a DevOps methodology
- Use a Development Platform
- Use Infrastructure as Code (IaC)
- Use the prevailing Community Standards for each language
- Use a Process Proportional to the Project
- Use Continuous Process Improvement
Combine Software Development and IT Operations (SysAdmin). Shorten the software lifecycle and iterate quickly with continuous automation. Improves speed and reliability.
Figure 1: Lifecycle (Image Credit)
Steps:
- Plan: Stakeholder asks for a change
- Create: Write code (or config)
- Verify: Testing (automated unit and integration testing)
- Package: Tag code, Create distributable artifact
- Release: Publish libs, Deploy apps
- Configure: Environment specific configuration
- Monitor: Metrics and Health logging and alerting
Example: jmyapi
- Plan - Get an email from ops (or OPS-PR, or stopped in the hall)
- Create an issue ticket (possible stakeholder does this for you, but almost never happens)
- Create - Code up the change.
- Possibly on a branch
- Run tests on local workstation via build tool
- Commit and push.
- Verify - Automated CI tests run on push; optionally integration tests may be automated or may require manual testing.
- Package - Bump semver version in file named VERSION. Commit and push. This triggers the next automated actions:
- Release - Action triggered on version push (configurable) and runs workflows:
- Create a Release entry with release notes
- Publish the lib artifact to Maven Central
- Publish API docs to web
- Configure - Environment variables and bash scripts used extensively; not always necesary to re-configure on each release
- Monitor - Nagios always watching
Reusable GitHub Action workflow libs:
All in one system for code versioning, issue tracking, documentation, software artifacts, collaboration, and automation. The leading platform is GitHub, but GitLab is another top contender.
- Collaboration and open source
- Public vs private switch to optionally allow access to repos via web by those external to the org
- Pull Requests
- Codespaces
- Discussions
- Docs
- README: My template
- Wiki (Markdown much nicer than MediaWiki)
- Pages (HTML hosting, good for API docs)
- IDE
- Editor with code highlighting and completion
- Button click to launch tasks
- Search and navigation
- VSCode is integrated into GitHub
- We have JetBrains IntelliJ licenses at JLab
- Git
- Distributed, doesn't require constant server connection like CVS
- Versioning, Semver recommended
- Automation
- Flexible automation framework that runs custom workflows in containers
- Marketplace of pre-made workflows
- Built-in workflows such as security code scanning
- GitHub depdabot will auto create PR for you
- GitHub will email you if it finds passwords, secrets, keys
- Commit tags
- Auto-close issue when associated PR merged
- Auto link commits to issues
- Generic hook for Workflow/Pipeline
- Misc
- Rules (only allow merge if automated tests pass)
- Bookmarkable code (hyperlinking)
- Gists: versioned notes, public or private
- Project templates: create a new project from a template
- Users can subscribe to email notification of events
Caveats
- JLab's GitHub license is full for private repos
- JLab CST division pays for and manages our GitHub and wants to switch to GitLab
- We probably don't want both (5 total given we will likely keep all the other accelerator repos indefinately)
- They're different enough to cause overhead/cost (PR vs MR, Pipeline vs Workflow)
Everything is automated and scripted instead of interactive. Phoenix mentality where apps can be destroyed and re-created easily.
- Continuous Integration (CI): automated build and test
- Continuous Deployment (CD): automated release, deploy, publish
- Libs are easier, push to artifact repo such as DockerHub, Maven Central, PyPi
- Apps require push to onsite server. I have an app deployment manager app for this. Used to automate deployment to test environments. For production, I manually ssh to a production server and invoke a "deploy" bash script that uses curl/wget to grab artifact and deploy it. This gives me an opportunity to manually test out the changes on the test environment before promoting code to production.
- devcontainers: setting up a dev environment is often time consuming. Easier to push "go" and have one built for you in a container. This is emerging tech, but I have an example here: java-devcontainer.
- Scripting: WSL on Windows makes Bash the lowest common denoninator and thus a reasonable cross-platform option that runs everywhere
Extensive use of Containers means development can occur anywhere (Windows, Mac, Linux). Work from home on spotty Internet. Makes it much easier to on-board and collaborate. Steps to setup an environment/infrastructure:
- Checkout code
- Run scripted dev environment setup (bash)
- Store test configuration in version control, but for production it's currently at secure location:
opsfs:/ace/app-conf
- Store scripts for setting up environment in version control
- Run service dependencies in containers via Compose; Compose Notes
- Launch app from an IDE
- Quick iteration cycle to make changes and test results
Each language has a unique suite of tools, coding conventions, and culture.
Java | Python | C++ | |
---|---|---|---|
Build | Gradle/Maven | Setuptools | Make |
Artifacts | Maven Central | PyPi | vcpkg |
API Docs | javadocs | Sphinx | doxygen |
Testing | junit | pytest | ctest |
Naming | CamelCase | snake_case | ? |
For simple single person projects it may be reasonable to:
- commit to main branch directly
- skimp on automated tests
- No need for another dev to review code
For multi-developer or high criticality
- use branching with merge
- extensive automated test coverage
- code reviews
- Constantly learning and trying new technology
- Containers in particular are quickly evolving
- The future for us may include heavier use of devcontainers and production containers (Kubernetes)
- We may want a more formal automation system, such as Red Hat Ansible Tower