Central repository for Attini distributions¶
Description¶
You often want to have a central repository for your build artifacts. This example shows how to configure an S3 bucket to act as a central repository for Attini distributions.
Prerequisites¶
AWS account that is a member of an AWS organization
Install the AWS CLI and Configure CLI credentials
Install the Attini CLI
A GitHub repository
We will go through:
How to configure the S3 bucket
How to configure Github actions to build the Attini distribution using the Attini CLI
How to push the Attini distributions to S3 using the AWS CLI
How to fetch the Attini distribution from the S3 bucket and deploy it to a different AWS Account using the Attini CLI
Note
This example is for Github actions, but the general architecture will work with any build server that integrates with git and AWS. You will just have to reconfigure a few things.
Create the S3 Bucket¶
First, we need an S3 bucket with the following configuration.
Note
Ensure you have AWS CloudTrail data events enabled for this bucket if you plan to use it in Production. If the distributions are tampered with, you want to know who did it.
We need a life cycle policy for the objects. There will always be a copy of the distributions inside every individual environment using it, so you don’t need to worry about removing distributions that might be needed for a rollback.
In the example below, we will delete the distributions after 365 days.
We need a bucket policy allowing application accounts to get the distributions.
The example below opens the bucket for the entire AWS Organization.
We need to give GitHub actions the permission to upload an object to the bucket.
In the example below, I create a Managed Policy that I will use for an IAM User.
Example bucket CloudFormation template:
AWSTemplateFormatVersion: 2010-09-09
Description: Example of and S3 bucket that can act as a central repository for attini distributions.
Parameters:
BucketName:
Type: String
Description: The repository (s3 bucket) name.
OrganizationId:
Type: String
Description: The id of your AWS Organization (o-xxxxxxxxxx). This will allow all AWS Accounts in your AWS Organization to get objects from the bucket.
Resources:
AttiniRepository:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
BucketEncryption:
ServerSideEncryptionConfiguration:
-
ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
VersioningConfiguration:
Status: Enabled
LifecycleConfiguration:
Rules:
-
Id: ExpirationInDays
Status: Enabled
ExpirationInDays: 356
-
Id: MultipartUploadLifecycleRule
Status: Enabled
AbortIncompleteMultipartUpload:
DaysAfterInitiation: 7
-
Id: NoncurrentVersionExpirationInDays
Status: Enabled
NoncurrentVersionExpirationInDays: 30
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref AttiniRepository
PolicyDocument:
Statement:
-
Action:
- s3:GetObject
- s3:ListBucket
Effect: Allow
Resource:
- !GetAtt AttiniRepository.Arn
- !Sub ${AttiniRepository.Arn}/*
Principal: "*"
Condition:
StringEquals:
aws:PrincipalOrgID: !Ref OrganizationId
PushAttiniDistribution:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: push-attini-distribution
Description: This policy allows an IAM User or IAM Role to push distribution to the repository bucket
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- s3:PutObject
Effect: Allow
Resource: !Sub ${AttiniRepository.Arn}/*
Outputs:
AttiniRepository:
Description: The name of the S3 bucket
Value: !Ref AttiniRepository
Configure your Git Repository¶
Configure access to the S3 bucket¶
If your build server already has access to S3, you can skip this step.
Create an AWS IAM User that has “s3:PutObject” access to the bucket we just created. You can use the
push-attini-distribution
Managed Policy in the template if you want to. Temporarily save the “Access key ID” and “Secret access key” somewhere safe.Go to your Gihub repository > Settings > Secrets > Actions secrets.
Add 2 new secrets, one called
AWS_ACCESS_KEY_ID
and the otherAWS_SECRET_ACCESS_KEY
and populate the values that you saved from step 1.
Configure the Attini distribution¶
Create a file called attini-config.yaml
in the root of the repository.
It should look something like this:
distributionName: hello-world
package:
prePackage:
commands:
- attini configure set-dist-id --id ${GITHUB_SHA} # this command will set the Attini distribution to the git commit id
Note
If you ever need to package (attini distribution package
) the distribution on your local computer when doing development,
you can mock the GITHUB_SHA
environment variable using the flag --environment-config-script
.
In this script, you can add the shell command export GITHUB_SHA=test-commit-id
.
Configure the Github action¶
In the root of your repository, create a file called .github/workflows/build.yml
Now add the following code to the file:
on:
push:
branches:
- main
name: Build and push Attini distribution
jobs:
deploy:
name: Build and push
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
- name: Install Attini CLI # Better to do this in the container image if it's possible
shell: bash
run: |
curl -fsSO https://docs.attini.io/blob/attini-cli/install-cli.sh
chmod +x install-cli.sh
./install-cli.sh -s
- name: Check out repository code
uses: actions/checkout@v2
- name: Package and upload the Attini distribution
shell: bash
run: |
# GITHUB_SHA is an environment variable which is our git commit id, which is a good value to use for the distribution id.
DISTRIBUTION_ID="${GITHUB_SHA}"
DISTRIBUTION_NAME="hello-world"
REPOSITORY_BUCKET_NAME="attini-repository-bucket"
attini distribution package . --name ${DISTRIBUTION_NAME}.zip
# If you upload the distribution to the path "/latest/" it easy to find the latest version.
aws s3 cp ${DISTRIBUTION_NAME}.zip s3://${REPOSITORY_BUCKET_NAME}/${DISTRIBUTION_NAME}/latest/${DISTRIBUTION_NAME}.zip
# You also want to save a copy with the DISTRIBUTION_ID in path so that you can easily get old versions.
aws s3 cp ${DISTRIBUTION_NAME}.zip s3://${REPOSITORY_BUCKET_NAME}/${DISTRIBUTION_NAME}/${DISTRIBUTION_ID}/${DISTRIBUTION_NAME}.zip
At the very least you want to change the values for aws-region
and REPOSITORY_BUCKET_NAME
in the file.
Next time you push a change to the “main” branch, your distribution will be packaged and uploaded to the s3 bucket to the location /hello-world/${DISTRIBUTION_ID}/hello-world.zip
and /hello-world/latest/hello-world.zip
.
You can, of course name your distributions whatever you want and use any prefix or path in S3 that makes sense for your way of working, but having the distribution name and id in the S3 key is a good place to start.
You can also add additional steps that automatically log in to your Development AWS account and deploys the distribution there.
Deploy the Attini distribution from the repository¶
Now log in to your application account (ex, Development or Production) from your terminal (or using the AWS CloudShell) and run the following command:
attini deploy run s3://${REPOSITORY_BUCKET_NAME}/hello-world/${DISTRIBUTION_ID}/hello-world.zip
This will pull the distribution from the repository and deploy it to your current environment.