1. Project Overview & Quickstart (microsoft/azurelinux)
Azure Linux 4
An open-source Linux distribution built and optimized for Azure, with sources derived from Fedora Linux. Azure Linux provides a secured, reliable operating system for virtual machines, containers, and bare-metal platforms.
Azure Linux is built on a robust open-source foundation from the Fedora ecosystem and enhanced with Azure-specific innovations. This provides the familiarity of the RPM package ecosystem, while adding Azure-native security, compliance, and operational capabilities.
Key features of Azure Linux include: hardened security posture, an Azure-optimized kernel, supply chain security, native Azure integration, and a predictable lifecycle.
This branch holds the in-development sources for Azure Linux 4. For Azure Linux 3, see the
3.0branch.
Getting started
The links below will help you get started with Azure Linux:
| Product documentation | https://aka.ms/azurelinux |
| Release information | GitHub Releases |
| File a bug / feedback | GitHub Issues |
| Ask a question / get help | SUPPORT.md |
| Get started as a distro developer | DEVELOPING.md |
| Contribution guidelines | CONTRIBUTING.md |
| Report a security issue | SECURITY.md |
Using Azure Linux
Note: Azure Linux 4 is still in development
๐ฅ๏ธ Azure VM
To try Azure Linux in an Azure VM, please visit our Azure Linux 4.0 page on the Microsoft Marketplace.
๐ฆ Container
To try Azure Linux base container, please use the following image reference: mcr.microsoft.com/azurelinux-beta/base/core:4.0
๐ฟ ISO Installer
To try Azure Linux in a local VM, please download the ISO Installer: x86_64 / ARM64
Before using a downloaded ISO, verify the checksum and signature of the ISO.
After downloading and verifying the ISO, follow the ISO installer instructions to install and use Azure Linux in a local VM (Hyper-V on Windows or QEMU/KVM on Linux). The ISO runs the Anaconda installer.
Note: Support for the ISO is community based. Before filing a new bug or feature request, please search the list of Github Issues. If you are unable to find a matching issue, please report new bugs by clicking here. For additional information, refer to the SUPPORT.md file.
๐ง Windows Subsystem for Linux (WSL)
To try Azure Linux on the Windows Subsystem for Linux, please download the .wsl distribution package for your architecture:
Before installing a downloaded package, verify the checksum and signature of the .wsl package.
Install the distribution using wsl:
wsl --install --from-file "C:\Path\To\AzureLinux-4.0-ARCH.wsl"To list all the installed distributions:
wsl --listTo use the distro:
wsl -d AzureLinux-4What's in this branch?
Azure Linux 4 is an RPM-based distribution optimized for Azure and modern cloud workloads. It is defined by a set of TOML configuration files and targeted overlays applied to Fedora Linux, its upstream base.
Deviations from upstream are declaratively defined and scoped to avoid unnecessary divergence or forking. This repository contains a mechanically rendered set of RPM package spec files derived from applying this layer to Fedora's upstream packaging sources.
How Azure Linux is defined
The distro is described almost entirely in TOML-based configuration files. Our open-source development tool, azldev, is used to apply this configuration to upstream Fedora spec files and packaging sources.
azldev.toml # Top-level entry point
โโโ distro/ # Distro-wide configs (e.g., sources, mock configs)
โโโ base/ # The "base" project: components, images, tests
โโโ comps/ # Component definitions (one per source package)
โโโ images/ # Base image definitionsConcepts/terms
- Components (also known as source packages) are the unit of packaging.
Most are imported in source form from Fedora's upstream dist-git repositories; each component produces one or more RPMs. Azure Linux builds all components from sources to produce a full set of installable RPM packages. - Overlays are declarative modifications to upstream specs and sources
(e.g., patches, additions/removals, build parameters). They live alongside the component definition and always carry adescriptionexplaining why the change is needed. Overlays let us avoid forking upstream specs and are more flexible than plain textual patches. - Rendered specs are the final
.specfiles produced by applying overlays to upstream sources. They are mechanically generated byazldev, checked in for visibility and auditability, and live underspecs/. Treat them as derived output and not sources for editing. We use them as the input to standard RPM building services/tools (mock+rpmbuild,koji).
For a deeper tour of the tooling, the overlay system, and how to get started developing within this distro, please see
DEVELOPING.md.
Repository layout
| Path | What's there |
|---|---|
azldev.toml |
Top-level config โ includes distro/ and base/. |
distro/ |
Distro definitions (Azure Linux + upstream Fedora), shared mock configs. |
base/ |
The base project: components, images, tests. |
base/comps/ |
Component definitions โ the heart of the distro. |
base/images/ |
Image definitions (VM, container, etc.) built from the component set using KIWI NG. |
specs/ |
Rendered specs โ generated .spec files after overlays are applied. Checked in for visibility; do not hand-edit. |
locks/ |
Per-component lock files pinning upstream commits + input fingerprints; do not hand-edit. |
external/schemas/ |
Cached copy of the JSON Schema for TOML config files; mirrored from azldev. |
.github/ |
CI workflows, plus Copilot prompts, skills, and agent instructions used by AI-assisted development. |
Getting started as a distro developer
If you want to build or develop within the distro, start with DEVELOPING.md. Don't worry about this if you're primarily looking to use the distro.
Engagement & support
- Bugs and feature requests: file a
GitHub issue. Please search existing issues first to avoid duplicates. Share as much as you can with us regarding what you tried and what you're seeing. - Support: see SUPPORT.md for the full set of channels.
- Security vulnerabilities: do not open a public issue. Follow the process in SECURITY.md to report privately to the Microsoft Security Response Center.
- Pull requests: see CONTRIBUTING.md for the patch-series workflow, commit-message conventions, and review expectations.
- Community calls: Azure Linux hosts community calls where users can connect with our product and support teams, discuss new features, share feedback, and learn how others are using Azure Linux.
Each session also includes a featured demo. Upcoming community calls (08:00โ09:00 PT):- 2026-07-23 โ Click to join
- 2026-09-24 โ Click to join
- 2026-11-19 โ Click to join
- 2027-01-28 โ Click to join
- 2027-03-25 โ Click to join
- 2027-05-27 โ Click to join
This project has adopted the Microsoft Open Source Code of Conduct. For more information, see the Code of Conduct FAQ or contact [email protected] with any additional questions
or comments.
Trademarks
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos is subject to those third parties' policies.
Acknowledgments
Any Linux distribution, including Azure Linux, benefits from contributions by the open-source software community. We gratefully acknowledge all contributions made from the broader community.
We specifically want to thank the Fedora Project for providing us with a strong foundation across components, spec files, tools, services, and community. We are proud to participate and contribute to this community.
The Azure Linux penguin icon is inspired by the Linux mascot ("Tux"), created by Larry Ewing.
License
Unless otherwise specified, the content of the Azure Linux distribution and this repository are distributed under an MIT license.
Individual packages within the distribution are distributed under licenses specified in their package spec files and sources.
This repository contains files derived from Fedora Linux. For details on the licensing terms for the Fedora Project, please consult fedoraproject.org.
2. Official Technical Reference & Guides (microsoft/azure-linux-dev-tools)
File: README.md
Azure Linux Dev Tools
Azure Linux Dev Tools is a collection of utilities useful for development
of the Azure Linux distro.
`azldev`
azldev is a developer tool for working on the
Azure Linux distro.
It supports:
- Parsing, resolving, and querying TOML-based metadata defining the Azure Linux distro.
- Preparing the sources for a source component for building with
mock,koji, or similar standard build tool/service. - Fetching source archives from lookaside caches.
- Developer convenience utilities for locally building individual packages and images.
Quick start
Install
golangand other prerequisites via your system's package manager, e.g.:consolednf install -y golang mock dnf-utils mock-rpmautospec kiwiNote:
mock-rpmautospecplugin hooksrpmautospecinto mock's build lifecycle. It pullsrpmautospecas a dependency which processes%autoreleaseand%autochangelogmacros in spec files.Install
azldev:consolego install github.com/microsoft/azure-linux-dev-tools/cmd/azldev@latestTo pin a specific release instead of tracking the latest, replace
@latest
with a version tag, e.g.@v0.1.0.To ensure you can build using
mockyou must be a member of themockgroup, e.g.:consoleusermod -aG mock $USERNote that this may require re-login or
newgrpto ensure your environment registers
the group update.
Completion
You can install completion extensions for azldev with your shell by running:
eval "$(azldev completion bash)"Similar support exists for fish and zsh.
User documentation
To learn more about the TOML-based metadata that azldev supports, azldev's
command-line usage, or other usage information, please consult
this repo's User Guide.
Developing and contributing
Please see our Contribution Guidelines for our project.
For development setup and workflow, please consult our Developer Guide.
Changelog
Notable changes for each release are recorded in the changelog.
When preparing a release:
- Match the wording and formatting of existing entries, including inline code
for commands and identifiers. - End each new entry with links to its pull requests, such as
#123. - Leave entries for earlier releases unchanged.
Getting Help
Have questions, found a bug, or need a new feature? Open an issue in our GitHub repository. For guidance on how to file an issue, see how to report issues.
For security issues, please see the security policy.
License
This project is licensed under the MIT License. See the LICENSE
file for details.
Trademarks
This project may contain trademarks or logos for projects, products, or
services. Authorized use of Microsoft trademarks or logos is subject to and must
follow Microsoft's Trademark & Brand
Guidelines.
Use of Microsoft trademarks or logos in modified versions of this project must
not cause confusion or imply Microsoft sponsorship. Any use of third-party
trademarks or logos are subject to those third-party's policies.
File: docs/developer/ideas/future-ideas.md
Ideas for future consideration
Package building
Parameterized components
A single component can be defined to be built with a matrix of parameters, where each set of parameters results in a different "flavour" of the component being built.
Sample use cases:
- Building different configurations of the kernel.
- Building a bootstrap and full version of a component to resolve circular dependencies.
One project can define and build different versions of the kernel
OOT module components can build with all or selected versions of the kernels
Components providing OOT kernel modules must have a way to build against all supported kernel versions or a specific subset of them.
IMPORTANT: it must be possible to define OOT components in such way, that packages built for a newer kernel version are NOT considered as updates of the ones built for the older kernel versions. This is required, so that updating the OOT components does not inadvertently update the kernel as well due to the package's dependency on a specific kernel version.
Example:
- Project defines
kernel-olderversion 1.0.0 andkernel-newerversion 1.1.0. - Project builds
OOT-compfor both kernels. - Having the package manager update
OOT-componkernel-olderdoes not automatically update tokernel-newer.
Effectively this means that the OOT-comp packages defined for both kernels are not considered the same package by the package manager/RPM.
Supported origins for component sources
Fedora SRPM repos
Blob stores with anonymous access
Azure blob stores requiring authentication
For such blob stores, the tool should at minimum be able to use the credentials set by logging into Azure with az login.
File: docs/developer/how-to/add-go-tool.md
How to: add a go tool to this project
Please consult the documentation for our build tool go modules.
File: docs/developer/how-to/dev-workflow.md
Ideal Development Workflow
Before Making Changes
- Understand the codebase: Review existing code patterns and architecture
- Run the full test suite: Execute
mage allto ensure clean state - Create an issue: For non-trivial changes, discuss the approach first
Making Changes
- Create a feature branch: Use descriptive names (e.g.,
user/feature/add-config-validation) - Write tests first: Consider adding tests for new functionality before implementing
- Follow coding standards: See standards section below
- Make incremental commits: Use clear, descriptive commit messages following conventional commit format. Conventional commit naming will be enforced by the CI pipeline for the final PR title.
Validating Changes
Before submitting, ensure your changes pass all checks:
mage all # Default Go validation (also invokes slow scenario tests)For faster iteration during development:
mage build # Rebuild the tool
mage unit # Fast unit tests
mage check all # All quality checks, including optional Python checks
mage fix all # Auto-fix issuesTo audit how thoroughly your tests actually catch bugs (beyond line coverage) โ for example after
adding a new package or non-trivial logic โ run mutation testing; see
Mutation Testing. mage mutationDiff main audits just your
branch's changes.
For scenario tests, use:
mage scenario # Run all scenario tests (may take time)To see all available Mage targets, run:
mage -lFile: docs/developer/how-to/get-started.md
Getting Started
Prerequisites
go 1.25+ - Required for building and running the application
git - For version control and submitting changes
mage - Our build automation tool
bash# Mage is not technically required, the build tools may also be invoked # directly via `go run magefile.go` or `./magefile.go` go install github.com/magefile/mage@latestPython and pip (only if you touch Python code) - The repository pins
therufflinter/formatter andpyrighttype checker in
requirements-lint.txt. They are used bymage check python
andmage fix python. Create and activate a virtual environment before installing the tools:bash# On Azure Linux tdnf install -y python3-pip python3 -m venv .venv source .venv/bin/activate pip install -r requirements-lint.txtActivate
.venvin each shell before runningmage check python,mage fix python,
ormage check all. The dev container installs the pinned tools for you.
Initial Setup
Fork the repository (strongly recommended for all contributors)
Clone your fork locally
Install dependencies, e.g.:
bashdnf install -y golangVerify the build works:
bashmage buildInstall the built tools to your
$GOPATH/bindirectory:bashmage installAfter running
mage install, the tools will be available in your$GOPATH/bindirectory.
Not all systems will have this directory in their$PATHby default, so you may need to add it.
Azure Linux 3.0 as a development host
# These instructions work for Azure Linux (https://github.com/microsoft/azurelinux)
# While the tools should build and run on any system with golang installed, some of the runtime dependencies
# may not be available on all systems (e.g., `mock`).
tdnf install -y golang ca-certificates glibc-devel
# Install runtime requirements for the azldev tool
tdnf install -y mock dnf-utils mock-rpmautospec
git clone
cd <REPO>
# You may want to permanently add $GOPATH/bin to your $PATH via
# echo 'export GOPATH=$(go env GOPATH)' >> $HOME/.bashrc
# echo 'export PATH=$PATH:${GOPATH}/bin' >> $HOME/.bashrc
export GOPATH=$(go env GOPATH)
export PATH=$PATH:${GOPATH}/bin
go install github.com/magefile/mage@latest
mage build
mage installDevelopment
Please review these follow-up documents:
Testing
Testing can be run with mage, or directly using go test. The mage build system is preferred as it can also automatically run the scenario tests and update the test expectations.
# Run the unit tests
mage unit
# Run the coverage tests, producing an .html report
mage coverage
# Run scenario tests
mage scenarioSee the testing documentation for detailed guidelines on writing and running tests.
Troubleshooting
Common Issues
- Build failures: Ensure Go version is 1.25+ and all dependencies are installed. Try running
mage build -v. EnsureGOPATHis configured. - Test failures: Run
mage generateto ensure generated code is up to date - Lint errors: Address specific linting issues or discuss exceptions with maintainers
- Command not found: Run
mage install, ensureGOPATHis in your$PATH.
Questions and Support
If you have any questions about contributing, please open an issue in the repository.
Thank you for contributing!
File: docs/developer/how-to/testing.md
Testing guidelines
This document provides guidelines for writing and maintaining tests within the AZL Dev Preview project, with a special focus on using interface mocks via GoMock.
Table of Contents
Unit Tests
- CRITICAL: Unit tests must NOT write to the real filesystem or spawn real external processes
- Use the test context facilities (
internal/global/testctx) for in-memory filesystem access - Tests should not assume any files in the real host filesystem are present
- Use table-driven tests where appropriate
- Test both success and failure cases
- Use meaningful test names that describe the scenario
- Leverage
testifyfor assertions
Scenario Tests
- Use the scenario testing framework in
scenario/ - Test realistic user workflows
- Include both positive and negative test cases
- Use
mage scenarioUpdatewhen test expectations change and snapshots need updating - Use existing test helpers in
scenario/internal/cmdtest
Mutation Testing
Mutation testing measures how good the tests actually are (as opposed to mere line coverage) by
introducing small changes ("mutants") into the source and checking whether the test suite catches
them. A mutant that tests fail on is killed; one that passes is a lived mutant and points to a
real gap in test assertions. The project uses gremlins,
pinned in tools/gremlins.
Mutation testing recompiles and reruns the tests for every mutant, so it's slower than unit tests;
running the whole repo (./) takes a few minutes. Scope it for quicker feedback:
# Scope to a single package.
mage mutation ./internal/rpm
# Scope to only the lines changed relative to a git ref (fastest; ideal on a branch).
mage mutationDiff mainInterpreting the output:
- Test efficacy is the percentage of
KILLEDmutants overKILLED + LIVED. Higher is better. - LIVED mutants are the actionable signal: a change the tests did not detect.
- NOT COVERED mutants are in code with no test coverage at all.
- Some
LIVEDmutants are equivalent (e.g.len(x) > 0vs>= 0when the loop body no-ops on an
empty slice) and cannot be killed. Inspect before "fixing".
The console output is filtered to just the actionable mutants (LIVED and NOT COVERED) plus the
summary totals; a full JSON report covering every mutant (including KILLED) is written toout/mutation-report.json for tooling or detailed review.
Mutation testing only exercises unit tests. Scenario tests are gated behind the scenario build
tag and are not run by gremlins, so they never slow down a mutation run. The targets also exclude thescenario/ and magefiles/ trees and generated mocks from the mutant set to avoid NOT COVERED
noise.
Note: Timeout tuning is configured in
.gremlins.yaml(unleash.timeout-coefficient, currently 100).
On this repo's fast suites, gremlins' default is often too tight once recompilation is included, so mutants can be
mis-reported asTIMED OUT(which gremlins counts as killed, inflating efficacy).
If you rungremlinswithout the repo config, pass a higher--timeout-coefficient(e.g. 100) for accurate results.
Test Utilities
- Create reusable test fixtures when appropriate
- Mock external dependencies appropriately. See Mocking dependencies for details
- The in-memory filesystem is available via
internal/global/testctxfor testing purposes
Mocking dependencies
The AZL Dev Preview project uses GoMock to generate mock implementations of interfaces for testing purposes. These mocks allow for controlled testing of components that depend on interfaces without relying on concrete implementations.
Mock generation is handled through Go's built-in go:generate functionality. The project uses a pinned version of mockgen stored in the tools/mockgen directory to ensure consistent behavior across all environments.
Generating Mocks
To generate new mocks for an interface, add a go:generate directive at the top of the file containing the interface. Example from internal/global/opctx/interfaces.go:
//go:generate go tool -modfile=../../../tools/mockgen/go.mod mockgen -source=interfaces.go -destination=opctx_test/opctx_mocks.go -package=opctx_test --copyright_file=../../../LICENSEThe directive should:
- Reference the mockgen tool using the relative path to the tool's go.mod file
- Specify the source file containing the interfaces
- Define the destination path for the generated mocks. Place the file inside a folder with the
_testsuffix to ensure it is ignored during test coverage reports - Set the package name for the generated mocks
- Include a copyright file reference
Mocks are automatically generated as part of the build process when running any of the below commands:
mage generate
mage build
mage unit
go generate ./...NOTE: go test will NOT run the go:generate directives.
Using Mocks in Tests
Best Practices
- Don't overuse mocks: Only mock interfaces that are external to the component under test
- Keep tests focused: Test one unit of functionality at a time
- Use helper functions: Create helper functions to set up common mock configurations
- Use table-driven tests: When testing similar functionality with different inputs
- Follow existing patterns: See examples in the codebase such as
internal/utils/externalcmd/externalcmd_test.go
Basic Usage
Full documentation and examples for using GoMock can be found in the GoMock documentation. Below is a short set of usage examples from this project.
To use the generated mocks in your tests:
Import the mock package:
goimport ( "go.uber.org/mock/gomock" "github.com/microsoft/azure-linux-dev-tools/internal/global/opctx/opctx_test" )Create a controller and mock instances:
gofunc TestMyFunction(t *testing.T) { // Create a new controller ctrl := gomock.NewController(t) // Create mock instances using the controller mockFileSystem := opctx_test.NewMockFileSystemFactory(ctrl) mockOSEnv := opctx_test.NewMockOSEnvFactory(ctrl) // Use the mocks in your test app := azldev.NewApp(mockFileSystem, mockOSEnv) // Set expectations, run test code, verify }
Setting Expectations
GoMock allows you to define expectations for method calls on your mock objects:
// Expect DryRun() to be called any number of times and return false
mockDryRunnable.EXPECT().DryRun().AnyTimes().Return(false)
// Expect GetEventListener() to be called exactly once with any arguments
// and return a specific mock object
mockContext.EXPECT().GetEventListener().Times(1).Return(mockEventListener)These expectations are automatically verified at the end of the test. If the expectations are not met, the test will fail. Similarly, if an unexpected method call is made on the mock, the test will also fail.
Setting up mock return values
You can configure a mock to return a specific value. This includes returning another pre-configured mock:
// Must always create a controller for the mocks.
ctrl := gomock.NewController(t)
// Create a mock of the command factory interface.
mockCmdFactory := opctx_test.NewMockCommandFactory(ctrl)
// Create a mock of the command returned by the command factory.
mockCmd := opctx_test.NewMockCommand(ctrl)
// Set up the mock command's behaviour for its Run() method. Here it returns a nil error.
// The 'gomock.Any()' is an argument matcher making sure we won't fail the test regardless of the input.
mockCmd.EXPECT().Run(gomock.Any()).Return(nil)
// Set up the command factory to return the mock command when Command() is called.
mockCmdFactory.EXPECT().Command(gomock.Any()).Return(mockCmd, nil)
(...)
// Some test code using the mock command factory:
cmd, err := mockCmdFactory.Command("arbitrary input")
require.NoError(t, err)
require.Equal(t, mockCmd, cmd)
err = cmd.Run(ctx.Background())
require.NoError(t, err)
// GoMock will automatically verify that the expected calls were made on the mock.Testing Error Conditions
Use mocks to simulate error conditions:
mockCmd.EXPECT().Run(gomock.Any()).Return(errors.New("command error"))Mocks side effects
You can define a function to be executed when a mock method is called, allowing you to simulate side effects:
const testDir = "/test/dir"
// Must always create a controller for the mocks.
ctrl := gomock.NewController(t)
// Create a mock of a command we expect to run.
// The 'gomock.Any()' is an argument matcher making sure we won't fail the test regardless of the input.
testFS := afero.NewMemMapFs()
mockCmd := opctx_test.NewMockCommand(ctrl)
mockCmd.EXPECT().Run(gomock.Any()).DoAndReturn(func(_ context.Context) error {
// Simulate some side effect. Creating a directory in this case.
err := fileutils.MkdirAll(testFS, testDir)
require.NoError(t, err)
return nil
})
...File: docs/developer/reference/build.md
Build Reference
All code in this repo is written in golang. The golang package is required to build and run the tools.
The build system uses mage, which can be installed with go install github.com/magefile/mage@latest. Alternatively, a zero-install approach is available through go run magefile.go or ./magefile.go, which automatically downloads the required dependencies without manual installation. Go build tools are managed automatically by go.
All core tooling dependencies are handled by go tool, which will automatically get the required tools when using mage. See the tools section for more information.
Optional Python lint tools are pinned in requirements-lint.txt. Before using a Mage target that runs Python checks, follow the virtual environment setup in Getting Started so that ruff and pyright are on your PATH.
This repo contains configs for the golangci-lint linter. It is installed as part of the VSCode go extension. It's also optionally available as a binary release.
Mage Commands
| Command | Description | When to Use |
|---|---|---|
mage -l |
List all available targets | To see all options |
mage all |
Build, test, default checks, and scenario pipeline | Before submitting PR |
mage build |
Build Go binaries | After code changes |
mage install |
Build Go binaries and install | Outer-loop testing |
mage unit |
Run unit tests | After writing tests |
mage scenario |
Run scenario tests (SLOW) | For major changes |
mage scenarioUpdate |
Update test snapshots | When test expectations change |
mage mutation |
Run mutation testing on a package; writes out/mutation-report.json |
To assess test quality of a package |
mage mutationDiff <ref> |
Run mutation testing on lines changed vs a git ref | To check test quality of a branch's changes |
mage check default |
Run default Go checks (lint, static analysis, license) | Before committing |
mage check all |
Run all quality checks, including Python | Before committing or after Python changes |
mage fix all |
Auto-fix code issues | When linting fails |
mage generate |
Run go generate ./... (mockgen, stringer, etc.) |
Seldom needed directly; runs automatically with build/test |
mage docs |
Build binary + regenerate CLI docs and JSON schema | After changing config structs or CLI commands |
Note: Dependencies run automatically in correct order
(i.e. mage build and mage unit automatically run code generation as needed).
Code Generation
The project uses automatic code generation including:
go:generatedirectives- Stringer for enums
- Schema generation
- Mocks generated by
mockgen
There are two generation stages:
mage generateโ runsgo generate ./...for all packages (mockgen, stringer, etc.). This is a prerequisite for building and runs automatically withmage buildandmage unit.mage docsโ builds the binary, then regenerates CLI docs (docs/user/reference/cli/) and JSON schema (schemas/azldev.schema.json). Run this after changing config structs (schema) or Cobra command descriptions (CLI docs).
You typically don't need to run mage generate manually; mage build runs it automatically. Run mage docs explicitly when you want to update the schema or CLI docs without running the full scenario test suite.
See tools documentation for more details on how to use tools with go tool in go:generate directives.
File: docs/developer/reference/coding-standards.md
Coding Standards
Go Code Style
Follow Go conventions: Use
mage fix lintfor formatting (fallback:gofmt), and standard Go idiomsNaming: Use clear, descriptive names for variables, functions, and types
Error handling: Always handle errors appropriately with context. Use the following pattern:
go// ErrOperationFailed is a global error for operation failures var ErrOperationFailed = errors.New("operation failed") // someOperation returns an error func someOperation() error { return fmt.Errorf("failed to connect to service: %w", ErrOperationFailed) } // Example usage in a function func performOperation() error { err := someOperation() // Wrap the error with context if err != nil { return fmt.Errorf("performing operation: %w", err) } return nil }Comments: Document exported functions, types, and complex logic
Package organization: Follow the existing package structure
String formatting: Prefer
%#qformat specifier for strings
Code Quality Requirements
- Linting: All code must pass
golangci-lintchecks (usemage check lintandmage fix lintto fix some issues automatically)- Avoid using
//nolintcomments unless absolutely necessary. If you must use it, specify the linter (e.g.,//nolint:golint).
- Avoid using
- Testing: New functionality requires unit tests
- Coverage: Maintain reasonable test coverage for critical paths
- Documentation: Update relevant documentation for user-facing changes
File Organization
- Business logic: Place in
internal/packages - Command handlers: Keep minimal logic in
cmd/packages - Unit Tests: Co-locate with source files using
_test.gosuffix - Scenario Tests: Use
scenario/for scenario tests - Configuration: Use TOML format, provide defaults in
defaultconfigs/
Command Structure
- See azldev command guidelines for details on command structure and naming conventions.
Python Code Style
Some functionality is implemented in Python scripts (e.g. scripts embedded in the
Go binary).
- Linting & formatting: All Python must pass
ruff(config:ruff.toml).
Runmage check pythonto lint andmage fix pythonto auto-format and apply fixes. - Type checking: All Python must pass
pyright(config:pyrightconfig.json).
This is also run bymage check python. - Tool installation: Install the pinned versions from
requirements-lint.txt
in the virtual environment described in Getting Started. - Both checks are part of
mage check all.
Logging Guidelines
- Use structured logging with the
slogpackage - Include relevant context in log messages
- Use appropriate log levels (Debug, Info, Warn, Error)