GitHub
Repo Creation
We will walk through the development cycle by first creating our first GitHub repository. We will call it clock, make it private, and give it a .gitignore of Node since we will be coding typescript.
Slack Subsciption
Open slack and add a channel called clock Run the command:
/github subscribe gitusername/clock
By doing this you will get notifications on slack when git changes are made.
Cloning Repo Locally
You can use your own Git UI by I'm very used to using GitKraken. It's my favorite way to work with Git without doing everything in cli. So I open GitKraken and clone my repo. If you need instructions on how to link GitHub, see this YouTube video.
Create Branches
By default, the only branch you have is your 'Main' branch. This is ok but if you want to work as a larger company would, you would have a 'develop' branch. All features will be branched from develop into feature branches.
So we will click Branch from main and create a develop branch.
This develop branch only exists locally so we have to push develop so it gets on GitHub.
One done, we will create a feature branch from develop called feature/typescript and push it.
Back on GitHub, we can see our branch creations.
Initializing Typescript
So back in terminal on our folder, we have nothing but a .gitignore file.
We will initialize typescript by running:
npm init --template typescript
You can answer the questions or just click enter until you type yes.
Now in general, I like to have a few different packages installed when I code in Typescript so I'll add a few:
npm install -D ts-node nodemon
These help when running the application, ts-node runs the typescript where nodemon is nice because if you use it, it will automatically reload changes and you code. Now to use them, open the package.json file and modify them:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "ts-node ./src/index.ts",
"dev": "nodemon ./src/index.ts",
"build": "tsc",
"lint": "tslint -c tslint.json src/**/*.ts",
"prepublish": "npm run build"
},
This is good but I also like to change a few things. For testing I like to use Jest and for Linting, I like using ESLint. So let's install and configure them. Run the following:
npm install -D jest
Now modify the package.json file. You won't have any tests so far but it's good to have it preconfigured. Also, while you're at it, remove the "prepublish" script. It causes more problems than it solves for me.
"scripts": {
"test": "jest",
"start": "ts-node ./src/index.ts",
"dev": "nodemon ./src/index.ts",
"build": "tsc",
"lint": "tslint -c tslint.json src/**/*.ts"
},
Typescript has a few configurations that I like so go into tsconfig.json and add the following:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"lib": [
"es2015",
"DOM"
],
"esModuleInterop": true,
...
}
}
These modules will help us console out information as use interop.
Logging
Of course, we do want to make sure we log issues to axiom when we encounter issues. To do this, we want to configure it but we will need a few things first. Start by installing the following modules:
npm install dotenv winston @axiomhq/winston
These two packages will allow for environment variable consumption as well as logging. In ./src/index.ts, initialize environment variables by the following code:
require('dotenv').config();
You can have environment variables via a .env file in the root directory, we will create one as an example
MESSAGE=Hello World
Next we will console out the message in code:
const {
MESSAGE
} = process.env;
console.log(MESSAGE)
We can then run out code via:
npm run dev
That's nice but we want to be able to log it to axiom. Let's create a logger folder in src and create a file called index.ts and input the following:
// eslint-disable-next-line @typescript-eslint/no-var-requires
import { createLogger, format, transports } from 'winston';
const { combine, timestamp, printf } = format;
import { WinstonTransport } from '@axiomhq/winston';
const {
AXIOM_DATASET,
AXIOM_TOKEN,
AXIOM_ORG_ID
} = process.env;
// tslint:disable-next-line:no-shadowed-variable
const myFormat = printf(({ level, message, timestamp }: any) => {
return `${timestamp} ${level}: ${message}`;
});
const configuredTransports: any = [
new transports.Console({
level: 'debug'
}),
];
if (AXIOM_TOKEN !== undefined) {
configuredTransports.push(new WinstonTransport({
token: AXIOM_TOKEN ? AXIOM_TOKEN.trim() : '',
dataset: AXIOM_DATASET ? AXIOM_DATASET.trim() : '',
orgId: AXIOM_ORG_ID ? AXIOM_ORG_ID.trim() : ''
}));
}
const logger = createLogger({
format: combine(
timestamp(),
myFormat
),
defaultMeta: {
service: `clock`
},
transports: configuredTransports
});
export default logger;
We will have to update our .env file to include:
- AXIOM_DATASET
- AXIOM_TOKEN
- AXIOM_ORG_ID
Axiom's organization id can be obtained in Axiom's site under account settings.
Now let's change our index.ts code to:
require('dotenv').config();
import logger from './logger'
const {
MESSAGE
} = process.env;
logger.info(MESSAGE);
You can see that the message gets logged to the console.
If you open Axiom and under streaming for staging, the same error is pushed. This is how we aggregate logs to a single source.
For testing, let's make a loop so we know it's working by adjusting the code. This will spit out a new message every second.
require('dotenv').config();
import logger from './logger'
const {
MESSAGE
} = process.env;
setInterval(() => {
logger.info(`${MESSAGE}: ${new Date()}`)
}, 1000)
For now, we have our little application, let's commit the feature. In GitKraken, we can see that there are changes so click 'View Changes'
Since we want all out change, we will click 'Stage All Change'
We will use a commit message of 'Configured typescript'. In 'Commit options' I will check 'Push after committing' so it pushes the feature to GitHub.
Notice a GitHub Icon on our commit now.
Now in a typical development company this is where we start to have people who check your code. You have pushed your changes for the feature to GitHub. Now someone has to check it. If you go to "Pull Request" on your repo, you will notice that changes have been pushed. Select 'Compare & pull request'.
On the Pull Request, change the branch to 'develop'. In a typical environment, you would then assign someone to review your code. Since we don't have anyone, you can select 'assign yourself'. You should get an email notifying you that a pull request has been made and you should check it.
Once you are happy with the code, if you were the checker, you would then select 'Merge pull request' and 'Confirm Merge'.
On GitKraken, after a few seconds, you will now notice that a merge has been done into develop.
Now if you were someone even higher up, you may elect to repeat the same steps but this time merge it into your main branch. In general, main branches are protected branches. You only want to push to your main branch once all checks have been done and you know for sure the code will work. Once complete, your GitKraken tree will look like this: