-
Notifications
You must be signed in to change notification settings - Fork 21
Internal development documentation
There are several points to this documentation, navigate to the relevant section below.
- Glossary
- SQL naming conventions
- Go naming conventions
- Testing
All guides use the RFC 2119 keywords to indicate requirements.
At the time of writing, the product is split into three micro services:
-
system- common system parts like users, authentication, organisations and teams, -
messaging- the Messaging service (channels, messages), -
crm- the CRM service (modules, records)
REQUIRED: Please consider all of these service names to be reserved. Don't use the names themselves as structures or fields, as to avoid confusion in possible discussions.
These keywords refer to specific parts shared by implementations:
-
Organisation(top level entity), -
Role(synonyms: Team, or User Group), -
Resource(refers to an object that has a Permission set), -
Access, access value for a Permission (Values:Allow,DenyorInherit), -
Permission, a combination of [Resource, Role and Access]
Messaging specific keywords:
-
Channel- a conversation channel, -
Direct messages- a message group between two people, -
Private channel- a message group between three or more people, -
Message- a single message entry, -
Reply- a reply to a specific message (1 level of replies only), -
Thread- all replies to a specific message (1 level of replies only),
CRM specific keywords:
-
Module- the top entity for holding the CRM structure, -
Field- a single CRM entry column (may be a complex field with multiple columns), -
Record- a single entry row for a given module -
Trigger- code snippet that is executed on certain trigger action -
Trigger action- actions are manual and before/after create, update and delete -
Automation- Trigger functionality -
Chart- Rules for data filtering and aggregation with chart rendering/output configuration
The keywords just define the glossary to use.
- all tables SHOULD be prefixed with the microservice name or abbreviation (sys_, messaging_),
- tables SHOULD be named in singular form if the entity is the source (user, message),
- tables SHOULD be named in plural if they hold multiple related records (user - user_settings with 1:N)
- columns SHOULD have the COMMENT attribute field out with their description,
- external relationship columns MUST be prefixed with
rel_, - recursive relationships MUST be named
self_id
TODO: be more strict about rel_ (can we use: rel_(table)_(column_name)?)
As a starting point, you should make yourself familiar with ["What's in a name? by Andrew Gerrand"].
Here are some of the namings which you SHOULD follow:
- use upper case ID for field names or partials (ChannelID, UserID,...),
- use singular form for structs (Role{} instead of Roles{})
- use the "Set" suffix for plurality (RoleSet{} intead of Roles{} (use codegen/v2/type-set.go)
- structure API call function names to be a single word (list, update, delete - verb)
- prefix API calls with entity name to group them together (boomarkCreate, bookmarkRemove - noun + verb)
- preferred words to use (CRUD):
- 'create' instead of add/new/publish,
- 'update' instead of set/edit,
- 'delete' instead of remove,
- 'read' instead of 'get'
- 'list' for returning multiple records,
- 'kind' for meta types instead of
*Type
The project is reasonably well tested. We have unit tests, integration tests, mocks, and in some cases even e2e tests. While the coverage will tend to increase over time, there are a few rules to follow. The primary way of testing is using the provided .drone.yml and Drone CI. You can install drone locally and run the tests with drone exec. Integration tests are run with make integration.
Each branch, pull request and tag are built. The pull request build must pass to be merged into master.
Build dependencies are managed in Dockerfile.builder. It should include everything we need to build the project and run relevant tests. This includes code generation tools and static analysis tools.
We have two types of integration tests - ones that rely on external services (HTTP client for example), and one that relies on our internal services (Database,...). The tests can be a mixture of both.
As such, we enforce build tags on integration tests. Here are a few examples:
-
// +build unit- a test that doesn't require any service, -
// +build integration- a mandatory tag to test against our services, -
// +build external- testing against third party and public services -
// +build integration,external- testing against our and public services -
// +build !integration,external- testing exclusively against the public services -
// +build unit integration- no service required, provides functions for integrations
Generated mocks currently don't have build tags. If your test is an unit test, the build tag is not required, however for integrations and external services tests, the build tags are mandatory.
Currently everything is evaluated in the CI, but we plan to drop external from the CI; a failure there is expected and doesn't mean that the build is broken if they should fail due to external reasons.
We generate various parts of the codebase:
- various StructSet helpers,
- most of the
reststructures and handlers, - testing mocks,
- static assets like db migration files
If any generated assets are out of date, the CI build will fail. If the source code isn't formatted correctly (go fmt), the CI build will fail. Make sure you're up to date and run make mocks && make codegen.