Version: 1.0.0
Last Updated: December 2025
- Philosophy & Principles
- Project Structure
- Naming Conventions
- Code Style Guide
- Type System & Multiple Dispatch
- Module Organization
- Documentation Standards
- Testing Requirements
- Error Handling
- Performance Guidelines
- Dependencies & Compatibility
- CI/CD Configuration
- Version Control Practices
- Licensing & Legal
- Release Process
- Community Standards
Julia software developed under this constitution adheres to:
- Composability: Design for interoperability with the broader Julia ecosystem
- Type Stability: Prioritize predictable, inferrable return types
- Zero-Cost Abstractions: High-level code should compile to efficient machine code
- Reproducibility: All results must be reproducible given the same inputs and environment
- Transparency: Code should be readable and self-documenting
Functions and types should behave as users expect. When in doubt, follow conventions established by Base Julia and major ecosystem packages.
Write correct, clear code first. Optimize only after profiling identifies actual bottlenecks.
MyPackage/
├── .github/
│ ├── workflows/
│ │ ├── CI.yml
│ │ ├── Documentation.yml
│ │ └── CompatHelper.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── dependabot.yml
├── docs/
│ ├── src/
│ │ ├── index.md
│ │ ├── getting_started.md
│ │ ├── api.md
│ │ └── examples.md
│ ├── make.jl
│ └── Project.toml
├── src/
│ ├── MyPackage.jl # Main module file
│ ├── types.jl # Type definitions
│ ├── core.jl # Core functionality
│ ├── utils.jl # Utility functions
│ └── deprecated.jl # Deprecated functionality
├── test/
│ ├── runtests.jl # Test entry point
│ ├── test_types.jl
│ ├── test_core.jl
│ └── Project.toml # Test-specific dependencies
├── benchmark/
│ ├── benchmarks.jl
│ └── Project.toml
├── examples/
│ └── basic_usage.jl
├── .gitignore
├── .JuliaFormatter.toml
├── CHANGELOG.md
├── CITATION.cff
├── CONTRIBUTING.md
├── LICENSE
├── Project.toml
└── README.md
Every package MUST include:
Project.toml- Package metadata and dependenciessrc/PackageName.jl- Main module filetest/runtests.jl- Test suite entry pointREADME.md- Package overview and quick startLICENSE- Open source license.gitignore- Git ignore patterns
name = "MyPackage"
uuid = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
authors = ["Author Name <author@example.com>"]
version = "0.1.0"
[deps]
# Direct dependencies only
[weakdeps]
# Optional dependencies for extensions
[extensions]
# Package extensions
[compat]
julia = "1.10"
# Explicit compat bounds for all dependencies
[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[targets]
test = ["Test"]- Use
PascalCasefor package names - Names should be descriptive but concise
- Avoid prefixes like
Jlor suffixes like.jlin the package name - Check JuliaHub/General registry for name conflicts
# Good
DataFrames, Plots, HTTP, JSON3
# Avoid
JuliaDataFrames, PlotPackage, my_package- Match the package name exactly
- Submodules use
PascalCase
module MyPackage
module SubModule
end
end- Use
PascalCasefor all types - Abstract types should describe a category:
AbstractContainer,AbstractSolver - Concrete types should be specific:
LinearSolver,HashContainer
# Abstract types
abstract type AbstractModel end
abstract type AbstractOptimizer <: AbstractModel end
# Concrete types
struct GradientDescent <: AbstractOptimizer
learning_rate::Float64
momentum::Float64
end
# Parametric types
struct Container{T} <: AbstractContainer
data::Vector{T}
end- Use
snake_casefor functions - Predicates (returning Bool) end with
?(notis_) - Mutating functions end with
! - Use verbs for actions, nouns for accessors
# Good
calculate_distance(a, b)
isvalid(x) # Predicate - returns Bool
normalize!(vector) # Mutates argument
# Avoid
calculateDistance(a, b) # camelCase
is_valid(x) # Use isvalid
Normalize(vector) # PascalCase for functions- Use
snake_casefor variables - Single-letter variables only for mathematical conventions or very short scope
- Constants use
SCREAMING_SNAKE_CASE
# Good
user_count = 10
matrix_size = (m, n)
const DEFAULT_TOLERANCE = 1e-8
const MAX_ITERATIONS = 1000
# Mathematical conventions (acceptable in limited scope)
for i in 1:n
x = A[i, :]
end- Use
snake_case.jlfor source files - File names should reflect content
- Main module file matches package name exactly
# Good
src/MyPackage.jl # Main module
src/linear_algebra.jl
src/io_utils.jl
test/test_core.jl
# Avoid
src/LinearAlgebra.jl # Conflicts with stdlib
src/utils.JL # Wrong extension caseUse JuliaFormatter.jl with this configuration:
# .JuliaFormatter.toml
style = "sciml"
indent = 4
margin = 92
always_for_in = true
whitespace_typedefs = true
whitespace_ops_in_indices = true
remove_extra_newlines = true
short_function_def = true
always_use_return = false
whitespace_in_kwargs = true
annotate_untyped_fields_with_any = false
format_docstrings = true
align_struct_field = false
align_assignment = false
align_pair_arrow = false
normalize_line_endings = "unix"
trailing_comma = true
join_lines_based_on_source = true
indent_submodule = true
separate_kwargs_with_semicolon = true
surround_wherecolon = false# 4 spaces for indentation (no tabs)
function calculate_result(x, y)
if x > 0
return x + y
else
return x - y
end
end
# Space after commas, around operators
result = func(a, b, c)
x = a + b * c
# No space inside brackets
array = [1, 2, 3]
dict = Dict("a" => 1, "b" => 2)
# Space around = in keyword arguments
func(x; keyword=value) # SciML style- Maximum 92 characters per line
- Break long lines at logical points
# Good - break at operators or after opening parenthesis
result = very_long_function_name(
argument_one,
argument_two,
keyword_argument=value,
)
# Good - break method chains
result = data |>
transform_step_one |>
transform_step_two |>
final_aggregation# Short functions - single line acceptable
square(x) = x^2
add(a, b) = a + b
# Multi-line functions
function complex_calculation(
input_data::AbstractVector{T},
parameters::Dict{Symbol,Any};
tolerance::Float64=1e-8,
max_iterations::Int=100,
) where {T<:Number}
# Implementation
result = zero(T)
for i in 1:max_iterations
# ...
end
return result
end
# Multiple dispatch - explicit return type when non-obvious
function Base.convert(::Type{MyType}, x::Int)::MyType
return MyType(x)
end# Prefer ternary for simple conditionals
status = isvalid(x) ? :valid : :invalid
# Use if-else for complex logic
if condition_one
action_one()
elseif condition_two
action_two()
else
default_action()
end
# Guard clauses for early returns
function process(x)
isnothing(x) && return nothing
!isvalid(x) && throw(ArgumentError("Invalid input"))
# Main logic
return transform(x)
endmodule MyPackage
# Standard library imports first
using LinearAlgebra: norm, dot, ×
using Statistics: mean, std
# External packages second
using DataStructures: OrderedDict
using StaticArrays: SVector, SMatrix
# Explicit imports for extension
import Base: show, convert, iterate
# Export public API
export MyType, calculate, transform!
end# Define clear abstract type hierarchies
abstract type AbstractSolver end
abstract type AbstractIterativeSolver <: AbstractSolver end
abstract type AbstractDirectSolver <: AbstractSolver end
# Concrete implementations
struct ConjugateGradient <: AbstractIterativeSolver
tolerance::Float64
max_iterations::Int
end
struct LUFactorization <: AbstractDirectSolver
pivot::Bool
end# Prefer immutable structs by default
struct Point{T<:Real}
x::T
y::T
end
# Use mutable only when necessary
mutable struct Counter
value::Int
end
# Use inner constructors for validation
struct PositiveReal
value::Float64
function PositiveReal(x::Real)
x > 0 || throw(DomainError(x, "Value must be positive"))
return new(Float64(x))
end
end
# Outer constructors for convenience
Point(x::Real, y::Real) = Point(promote(x, y)...)# Annotate struct fields
struct Config
name::String
value::Float64
options::Dict{Symbol,Any}
end
# Annotate function arguments for dispatch
function process(data::AbstractVector{<:Number})
# ...
end
# Avoid over-constraining - use abstract types
# Good
function compute(x::AbstractArray)
# Works with Array, SubArray, etc.
end
# Avoid
function compute(x::Array{Float64,1})
# Only works with Vector{Float64}
end# Type-stable function
function add_one(x::T) where {T<:Number}
return x + one(T)
end
# Avoid type instability
# Bad - return type depends on runtime value
function unstable(x)
if x > 0
return 1 # Int
else
return 1.0 # Float64
end
end
# Good - consistent return type
function stable(x)
if x > 0
return 1.0
else
return 1.0
end
end
# Use @code_warntype to check
@code_warntype stable(1.0)# Define generic fallback
function process(x)
throw(MethodError(process, (x,)))
end
# Specialize for specific types
function process(x::Number)
return x^2
end
function process(x::AbstractString)
return uppercase(x)
end
function process(x::AbstractVector)
return map(process, x)
end
# Use traits for behavior dispatch
abstract type SizeCategory end
struct SmallSize <: SizeCategory end
struct LargeSize <: SizeCategory end
size_category(x) = length(x) < 100 ? SmallSize() : LargeSize()
function optimize(x)
return _optimize(size_category(x), x)
end
_optimize(::SmallSize, x) = direct_method(x)
_optimize(::LargeSize, x) = iterative_method(x)# src/MyPackage.jl
module MyPackage
# Version
const VERSION = v"0.1.0"
# Dependencies
using LinearAlgebra
using Statistics
# Internal imports
import Base: show, convert
# Include source files in dependency order
include("types.jl")
include("core.jl")
include("utils.jl")
include("io.jl")
# Public API exports
export AbstractModel, ConcreteModel
export fit!, predict, evaluate
export load_model, save_model
# Precompilation (Julia 1.9+)
using PrecompileTools
@setup_workload begin
@compile_workload begin
model = ConcreteModel()
fit!(model, rand(100, 10), rand(100))
end
end
end # module# For large packages, use submodules
module MyPackage
# Core submodule
module Core
export AbstractType, CoreFunction
include("core/types.jl")
include("core/functions.jl")
end
# IO submodule
module IO
using ..Core: AbstractType
export read_data, write_data
include("io/readers.jl")
include("io/writers.jl")
end
# Re-export commonly used items
using .Core
using .IO
export AbstractType, CoreFunction
export read_data, write_data
end# Project.toml
[weakdeps]
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
[extensions]
MyPackagePlotsExt = "Plots"
MyPackageMakieExt = "Makie"
# ext/MyPackagePlotsExt.jl
module MyPackagePlotsExt
using MyPackage
using Plots
function MyPackage.plot_result(result::MyPackage.Result)
# Plots-specific implementation
end
end"""
function_name(arg1, arg2; keyword=default) -> ReturnType
Brief one-line description of the function.
Extended description providing more context, explaining the algorithm,
or describing edge cases. This can span multiple paragraphs.
# Arguments
- `arg1::Type`: Description of first argument.
- `arg2::Type`: Description of second argument.
# Keywords
- `keyword::Type=default`: Description of keyword argument.
# Returns
- `ReturnType`: Description of return value.
# Throws
- `ArgumentError`: When inputs are invalid.
- `DomainError`: When values are out of bounds.
# Examples
```julia
julia> result = function_name(1, 2)
3
julia> function_name(1, 2; keyword=true)
4Additional details for ??function_name:
- Implementation notes
- Performance characteristics
- Related functions
See also: related_function, another_function
"""
function function_name(arg1::Type1, arg2::Type2; keyword::Bool=false)
# Implementation
end
### 7.2 Type Documentation
```julia
"""
MyType{T} <: AbstractType
Short description of the type.
Extended description explaining the purpose, use cases,
and design decisions for this type.
# Fields
- `field1::T`: Description of field.
- `field2::Int`: Description of field.
# Constructors
MyType(field1, field2)
MyType(field1) # Uses default field2
# Examples
```julia
julia> obj = MyType(1.0, 2)
MyType{Float64}(1.0, 2)
julia> obj.field1
1.0
See also: RelatedType
"""
struct MyType{T} <: AbstractType
field1::T
field2::Int
end
### 7.3 Documentation Website
Use Documenter.jl with this structure:
```julia
# docs/make.jl
using Documenter
using MyPackage
DocMeta.setdocmeta!(
MyPackage,
:DocTestSetup,
:(using MyPackage);
recursive=true,
)
makedocs(
sitename="MyPackage.jl",
modules=[MyPackage],
authors="Author Name",
format=Documenter.HTML(
prettyurls=get(ENV, "CI", nothing) == "true",
canonical="https://username.github.io/MyPackage.jl",
assets=["assets/favicon.ico"],
sidebar_sitename=true,
),
pages=[
"Home" => "index.md",
"Getting Started" => "getting_started.md",
"Tutorials" => [
"Basic Usage" => "tutorials/basic.md",
"Advanced Topics" => "tutorials/advanced.md",
],
"API Reference" => "api.md",
"Contributing" => "contributing.md",
"Changelog" => "changelog.md",
],
checkdocs=:exports,
linkcheck=true,
warnonly=[:missing_docs],
)
deploydocs(
repo="github.com/username/MyPackage.jl.git",
devbranch="main",
push_preview=true,
)
# MyPackage.jl
[](https://username.github.io/MyPackage.jl/stable/)
[](https://username.github.io/MyPackage.jl/dev/)
[](https://github.com/username/MyPackage.jl/actions/workflows/CI.yml?query=branch%3Amain)
[](https://codecov.io/gh/username/MyPackage.jl)
[](https://github.com/invenia/BlueStyle)
Brief description of what the package does.
## Installation
```julia
using Pkg
Pkg.add("MyPackage")using MyPackage
# Basic example
result = my_function(data)- Feature 1
- Feature 2
- Feature 3
For detailed documentation, see the stable docs.
Contributions are welcome! Please read our Contributing Guide.
This project is licensed under the MIT License - see the LICENSE file.
If you use this package in your research, please cite:
@software{mypackage,
author = {Author Name},
title = {MyPackage.jl},
year = {2025},
url = {https://github.com/username/MyPackage.jl}
}
---
## 8. Testing Requirements
### 8.1 Test Structure
```julia
# test/runtests.jl
using MyPackage
using Test
using Aqua
using JET
@testset "MyPackage.jl" begin
# Code quality tests
@testset "Code Quality (Aqua.jl)" begin
Aqua.test_all(
MyPackage;
ambiguities=false, # Customize as needed
)
end
# Static analysis (optional but recommended)
@testset "Static Analysis (JET.jl)" begin
JET.test_package(MyPackage; target_defined_modules=true)
end
# Unit tests
include("test_types.jl")
include("test_core.jl")
include("test_utils.jl")
# Integration tests
include("test_integration.jl")
# Doctests
@testset "Doctests" begin
DocMeta.setdocmeta!(
MyPackage,
:DocTestSetup,
:(using MyPackage);
recursive=true,
)
doctest(MyPackage)
end
end
# test/test_core.jl
@testset "Core Functions" begin
@testset "function_name" begin
# Test basic functionality
@test function_name(1, 2) == 3
# Test edge cases
@test function_name(0, 0) == 0
@test function_name(-1, 1) == 0
# Test type stability
@test @inferred function_name(1.0, 2.0) == 3.0
# Test errors
@test_throws ArgumentError function_name(nothing, 1)
@test_throws DomainError function_name(-1, -1)
# Test with different types
@testset "Type: $T" for T in [Int32, Int64, Float32, Float64]
x, y = T(1), T(2)
result = function_name(x, y)
@test result isa T
@test result == T(3)
end
end
@testset "mutating_function!" begin
# Test mutation
data = [1, 2, 3]
result = mutating_function!(data)
@test result === data # Same object
@test data == [2, 4, 6] # Modified
end
end- Minimum 80% code coverage required
- 90%+ coverage recommended
- All public API functions must have tests
- Edge cases and error conditions must be tested
# test/Project.toml
[deps]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"# Define custom exceptions when appropriate
struct MyPackageError <: Exception
msg::String
end
Base.showerror(io::IO, e::MyPackageError) = print(io, "MyPackageError: ", e.msg)
# Use specific exception types
struct ValidationError <: Exception
field::Symbol
value::Any
reason::String
end
function Base.showerror(io::IO, e::ValidationError)
print(io, "ValidationError: field '", e.field, "' ")
print(io, "with value '", e.value, "' - ", e.reason)
end# Use built-in exceptions appropriately
function process(x::Number)
x >= 0 || throw(DomainError(x, "Input must be non-negative"))
return sqrt(x)
end
# Argument validation
function configure(; tolerance::Real=1e-8, max_iter::Integer=100)
tolerance > 0 || throw(ArgumentError("tolerance must be positive, got $tolerance"))
max_iter > 0 || throw(ArgumentError("max_iter must be positive, got $max_iter"))
# ...
end
# Use @assert only for internal invariants, not user input
function internal_function(x)
@assert x !== nothing "Internal error: x should never be nothing here"
# ...
end# For recoverable errors, consider Result types
struct Result{T,E}
value::Union{T,Nothing}
error::Union{E,Nothing}
end
success(value::T) where {T} = Result{T,Nothing}(value, nothing)
failure(error::E) where {E} = Result{Nothing,E}(nothing, error)
issuccess(r::Result) = r.value !== nothing
isfailure(r::Result) = r.error !== nothing
function safe_parse(str::AbstractString)::Result{Int,String}
try
return success(parse(Int, str))
catch
return failure("Failed to parse '$str' as Int")
end
endusing Logging
function complex_operation(data)
@debug "Starting operation" data_size=length(data)
@info "Processing data"
result = process(data)
if isempty(result)
@warn "Operation produced empty result"
end
@debug "Operation complete" result_size=length(result)
return result
end# Avoid allocations in hot loops
# Bad
function sum_squares_bad(x)
return sum([xi^2 for xi in x]) # Allocates array
end
# Good
function sum_squares_good(x)
return sum(xi^2 for xi in x) # Generator, no allocation
end
# Pre-allocate outputs
function transform!(output, input)
@assert length(output) == length(input)
for i in eachindex(input)
output[i] = process(input[i])
end
return output
end
# Use views instead of copies
function process_slice(A, i)
row = @view A[i, :] # No copy
return sum(row)
end# Check type stability
using Test
@inferred function_name(args...)
# Avoid containers with abstract element types
# Bad
data = Any[1, 2.0, "three"]
# Good
data = Union{Int,Float64,String}[1, 2.0, "three"]
# Better - use homogeneous types when possible
data = Float64[1.0, 2.0, 3.0]
# Annotate struct fields
struct Container
data::Vector{Float64} # Not Vector or Vector{Any}
endusing LoopVectorization
# Enable SIMD with @turbo (LoopVectorization.jl)
function dot_product(x, y)
s = zero(eltype(x))
@turbo for i in eachindex(x, y)
s += x[i] * y[i]
end
return s
end
# Use @simd for simple cases
function simple_sum(x)
s = zero(eltype(x))
@simd for i in eachindex(x)
@inbounds s += x[i]
end
return s
end# benchmark/benchmarks.jl
using BenchmarkTools
using MyPackage
const SUITE = BenchmarkGroup()
SUITE["core"] = BenchmarkGroup()
SUITE["core"]["function_name"] = @benchmarkable function_name($data) setup=(data=rand(1000))
# Run benchmarks
# julia --project=benchmark benchmark/run_benchmarks.jl# Profile before optimizing
using Profile
function target_function(n)
# ... implementation
end
# Profile
@profile target_function(10000)
Profile.print()
# For detailed analysis
using ProfileView # or PProf
@profview target_function(10000)- Minimize direct dependencies
- Prefer packages from the General registry
- Use package extensions for optional features
- Pin compat bounds for all dependencies
# Project.toml
[compat]
julia = "1.10"
DataStructures = "0.18"
JSON3 = "1.13"
StaticArrays = "1.5"Rules for compat bounds:
- Always specify Julia version
- Use semver:
"1.2"means>= 1.2.0, < 2.0.0 - Be as permissive as possible while maintaining compatibility
- Test against minimum supported versions in CI
# Use package extensions (Julia 1.9+)
# Project.toml
[weakdeps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
[extensions]
MyPackageCUDAExt = "CUDA"
# ext/MyPackageCUDAExt.jl
module MyPackageCUDAExt
using MyPackage
using CUDA
# GPU-specific implementations
function MyPackage.process(x::CuArray)
# CUDA implementation
end
end# .github/workflows/CI.yml
name: CI
on:
push:
branches:
- main
tags: ['*']
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
permissions:
actions: write
contents: read
strategy:
fail-fast: false
matrix:
version:
- '1.10' # Minimum supported
- '1' # Latest stable
- 'nightly' # Development
os:
- ubuntu-latest
- macos-latest
- windows-latest
arch:
- x64
exclude:
- os: macos-latest
version: 'nightly'
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
if: matrix.version == '1' && matrix.os == 'ubuntu-latest'
- uses: codecov/codecov-action@v4
if: matrix.version == '1' && matrix.os == 'ubuntu-latest'
with:
files: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
docs:
name: Documentation
runs-on: ubuntu-latest
permissions:
actions: write
contents: write
statuses: write
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: '1'
- uses: julia-actions/cache@v2
- name: Install dependencies
run: julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Build and deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
run: julia --project=docs docs/make.jl# .github/workflows/CompatHelper.yml
name: CompatHelper
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
CompatHelper:
runs-on: ubuntu-latest
steps:
- uses: julia-actions/setup-julia@v2
with:
version: '1'
- name: Run CompatHelper
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }}
run: |
julia -e '
using Pkg
Pkg.add("CompatHelper")
using CompatHelper
CompatHelper.main()
'# .github/workflows/TagBot.yml
name: TagBot
on:
issue_comment:
types: [created]
workflow_dispatch:
inputs:
lookback:
default: 3
permissions:
actions: read
checks: read
contents: write
deployments: read
issues: read
discussions: read
packages: read
pages: read
pull-requests: read
repository-projects: read
security-events: read
statuses: read
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}# .gitignore
# Julia
*.jl.cov
*.jl.*.cov
*.jl.mem
Manifest.toml
docs/Manifest.toml
docs/build/
test/Manifest.toml
# Build artifacts
deps/deps.jl
deps/build.log
deps/usr/
# IDE
.idea/
*.swp
*.swo
.vscode/
*.sublime-*
# OS
.DS_Store
Thumbs.db
# Local development
LocalPreferences.toml
.env
*.local.jlmain- Stable, release-ready codedevelop- Integration branch (optional)feature/*- New featuresfix/*- Bug fixesdocs/*- Documentation updates
Follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Formatting, no code changerefactor: Code change, no feature/fixperf: Performance improvementtest: Adding/updating testschore: Maintenance tasksci: CI configuration changes
Examples:
feat(solver): add conjugate gradient method
fix(io): handle empty file input correctly
docs: update installation instructions
refactor!: rename process to transform
BREAKING CHANGE: The process function has been renamed to transform.
All existing code using process() must be updated.
<!-- .github/PULL_REQUEST_TEMPLATE.md -->
## Description
Brief description of changes.
## Type of Change
- [ ] Bug fix (non-breaking change fixing an issue)
- [ ] New feature (non-breaking change adding functionality)
- [ ] Breaking change (fix or feature causing existing functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring
## Checklist
- [ ] My code follows the project style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have commented hard-to-understand areas
- [ ] I have updated the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests proving my fix/feature works
- [ ] New and existing tests pass locally
- [ ] I have updated CHANGELOG.md
## Related Issues
Closes #
## Additional Notes
Any additional information or context.For open source Julia packages:
- MIT License - Permissive, widely used in Julia ecosystem
- BSD 3-Clause - Similar to MIT with attribution clause
- Apache 2.0 - Includes patent grant
- GPL v3 - Copyleft, requires derivative works to be open source
MIT License
Copyright (c) 2025 Author Name
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# CITATION.cff
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
type: software
title: "MyPackage.jl"
version: 0.1.0
date-released: 2025-01-01
url: "https://github.com/username/MyPackage.jl"
repository-code: "https://github.com/username/MyPackage.jl"
license: MIT
authors:
- family-names: "Lastname"
given-names: "Firstname"
email: "email@example.com"
orcid: "https://orcid.org/0000-0000-0000-0000"
keywords:
- julia
- scientific-computing
abstract: "Brief description of the package."Follow Semantic Versioning (SemVer):
- MAJOR.MINOR.PATCH (e.g., 1.2.3)
- MAJOR: Breaking changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatible
Pre-release versions:
0.x.y: Initial development, API may change1.0.0-alpha.1: Alpha release1.0.0-beta.1: Beta release1.0.0-rc.1: Release candidate
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- New feature X
### Changed
- Modified behavior Y
### Deprecated
- Function Z is deprecated, use W instead
### Removed
- Removed obsolete function
### Fixed
- Bug fix description
### Security
- Security fix description
## [0.2.0] - 2025-06-15
### Added
- Feature A (#123)
- Feature B (#124)
### Fixed
- Critical bug in function C (#125)
## [0.1.0] - 2025-01-01
### Added
- Initial release
- Core functionality
- Basic documentation
[Unreleased]: https://github.com/username/MyPackage.jl/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/username/MyPackage.jl/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/username/MyPackage.jl/releases/tag/v0.1.0-
Pre-release
- All tests pass on CI
- Documentation is up to date
- CHANGELOG.md updated
- Version bumped in Project.toml
- Breaking changes documented
-
Release
- Create release commit
- Register with General registry via JuliaRegistrator
- Wait for registry PR to merge
- TagBot creates GitHub release
-
Post-release
- Verify package installs correctly
- Announce release (Discourse, social media)
- Update any dependent packages
# In GitHub PR or Issue comment:
@JuliaRegistrator register
# For a specific branch:
@JuliaRegistrator register branch=release-1.0
# For a subdirectory package:
@JuliaRegistrator register subdir=packages/MyPackageAdopt the Julia Community Standards or Contributor Covenant:
<!-- CODE_OF_CONDUCT.md -->
# Code of Conduct
## Our Pledge
We pledge to make participation in our project a harassment-free experience
for everyone, regardless of age, body size, disability, ethnicity, gender
identity, level of experience, nationality, personal appearance, race,
religion, or sexual orientation.
## Our Standards
Examples of behavior that contributes to a positive environment:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior:
* Trolling, insulting/derogatory comments, and personal attacks
* Public or private harassment
* Publishing others' private information without permission
* Other conduct which could reasonably be considered inappropriate
## Enforcement
Project maintainers are responsible for clarifying standards of acceptable
behavior and will take appropriate action in response to unacceptable behavior.
## Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 2.0.<!-- CONTRIBUTING.md -->
# Contributing to MyPackage.jl
Thank you for your interest in contributing!
## Getting Started
1. Fork the repository
2. Clone your fork: `git clone https://github.com/your-username/MyPackage.jl`
3. Create a branch: `git checkout -b feature/your-feature`
4. Install development dependencies:
```julia
using Pkg
Pkg.develop(path=".")
Pkg.instantiate()using Pkg
Pkg.test("MyPackage")using JuliaFormatter
format(".")julia --project=docs docs/make.jl- Update documentation for any changed functionality
- Add tests for new features
- Update CHANGELOG.md
- Ensure all CI checks pass
- Request review from maintainers
This project follows the conventions outlined in our Julia Constitution. Please ensure your code:
- Uses JuliaFormatter with our configuration
- Has complete docstrings for public functions
- Includes appropriate tests
- Is type-stable where performance matters
Open an issue or reach out on the Julia Discourse/Slack/Zulip.
### 16.3 Issue Templates
```markdown
<!-- .github/ISSUE_TEMPLATE/bug_report.md -->
---
name: Bug Report
about: Report a bug to help us improve
title: '[BUG] '
labels: 'bug'
---
## Bug Description
A clear description of the bug.
## To Reproduce
```julia
using MyPackage
# Code that reproduces the bug
What you expected to happen.
- Julia version:
- MyPackage version:
- OS:
Any other relevant information.
```markdown
<!-- .github/ISSUE_TEMPLATE/feature_request.md -->
---
name: Feature Request
about: Suggest a new feature
title: '[FEATURE] '
labels: 'enhancement'
---
## Problem Statement
What problem does this feature solve?
## Proposed Solution
Your idea for the feature.
## Alternatives Considered
Other approaches you've thought about.
## Additional Context
Any other relevant information.
# Create new package
using PkgTemplates
t = Template(;
user="username",
dir="~/code",
plugins=[
Git(; manifest=true, ssh=true),
GitHubActions(),
Codecov(),
Documenter{GitHubActions}(),
Formatter(; style="sciml"),
],
)
t("MyPackage")
# Develop package locally
using Pkg
Pkg.develop(path="path/to/MyPackage")
# Run tests
Pkg.test("MyPackage")
# Build docs locally
julia --project=docs -e 'using Pkg; Pkg.instantiate()'
julia --project=docs docs/make.jl
# Format code
using JuliaFormatter
format("src")
# Check type stability
@code_warntype function_name(args...)
# Profile performance
using Profile
@profile function_name(args...)
Profile.print()| Package | Purpose |
|---|---|
| PkgTemplates.jl | Package scaffolding |
| JuliaFormatter.jl | Code formatting |
| Documenter.jl | Documentation generation |
| Aqua.jl | Code quality checks |
| JET.jl | Static analysis |
| BenchmarkTools.jl | Performance benchmarking |
| ProfileView.jl | Profiling visualization |
| Revise.jl | Live code reloading |
| TestItemRunner.jl | VS Code test integration |
- Generate package with PkgTemplates
- Configure .JuliaFormatter.toml
- Set up GitHub repository
- Configure branch protection rules
- Add CODEOWNERS file
- Aqua.jl tests pass
- JuliaFormatter applied
- Docstrings for all exports
- Type annotations on struct fields
- Type-stable critical paths
- 80%+ code coverage
- Tests for all public API
- Edge cases covered
- Doctests included
- README with badges
- Getting started guide
- API reference
- Examples/tutorials
- CHANGELOG.md
- GitHub Actions CI
- Multi-version testing
- Documentation deployment
- CompatHelper
- TagBot
- LICENSE file
- CONTRIBUTING.md
- CODE_OF_CONDUCT.md
- Issue templates
- PR template
This constitution is a living document. Contributions and suggestions for improvement are welcome.