Github actions to deploy static site to AWS S3 - amazon-s3

I am trying to deploy static content to AWS S3 from Github actions. I created AWS id and secret environment variables
and have this as main.yml
name: S3CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v1
- 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: us-west-2
- name: Build static site
- run: yarn install && npm run-script build
- name: Deploy static site to S3 bucket
run: aws s3 sync ./dist/ s3://awss3-blog --delete
But Github actions failed with error
Invalid Workflow File
DETAILS
every step must define a uses or run key

Usually, always actually from my own experience, GitHub is showing clearly the invalid part of the YAML. In my cases, it is almost always complain about the tabs instead of spaces, and yes, I'm very mad about it!!!
In your case, as #smac89 already mentioned, it is the line starting - run, which is wrongly NOT associated with the previous - name because of that dash, so the - name became orphan as well.
To the point of deploying to S3: I warmly suggest (as I already did somewhere else) to do it just with the CLI and without any additional action/plugin.
It is as simple as:
- name: Deploy static site to S3 bucket
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: aws s3 sync ./dist/ s3://awss3-blog --delete
As you can see, it is exactly the same effort from the secrets perspective, but simpler, independent, cleaner etc. BTW, region is not required and may safely be omitted.

It has to do with this line:
- run: yarn install && npm run-script build
But it is specifically complaining about this step:
- name: Build static site
Remove the - infront of the run if you want the above step to use that run command

This is a full example. Just pay attentions to the variables that you have to set and remove the Cloudfront invalidation if you don't need it. This repo: https://github.com/caiocsgomes/caiogomes.me has it implemented, building a static website with Hugo and deploying to s3.
# Workflow name
name: S3 Deploy
on:
workflow_dispatch:
push:
paths:
- 'app/**'
- '.github/workflows/deploy.yml'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: sa-east-1
BUCKET_NAME: caiogomes.me
steps:
- name: Install hugo
run: sudo apt install hugo
- name: Install aws cli
id: install-aws-cli
uses: unfor19/install-aws-cli-action#v1
with:
version: 2
verbose: false
arch: amd64
rootdir: ""
workdir: ""
- name: Set AWS credentials
run: export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} && export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Checkout repository
uses: actions/checkout#v3
with:
submodules: 'true'
- name: Build
run: cd app/ && hugo
- name: Upload files to S3
run: aws s3 sync app/public/ s3://${{ env.BUCKET_NAME }}/ --exact-timestamps --delete
create-cloudfront-invalidation:
needs: build-and-deploy
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: sa-east-1
CLOUDFRONT_DISTRIBUTION_ID: ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }}
steps:
- name: Install aws cli
id: install-aws-cli
uses: unfor19/install-aws-cli-action#v1
with:
version: 2
verbose: false
arch: amd64
rootdir: ""
workdir: ""
- name: Set AWS credentials
run: export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} && export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Invalidate clodufront distribution
run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"

Related

How to fix Github Actions dotnet publish workflow error: The "--output" option isn't supported when building a solution

Something changed in the way the dotnet publish workflow task works. We've been using this pretty straightforward yaml script for some time now.
name: Publish to staging server
env:
AZURE_WEBAPP_NAME: 'my-dotnet-webapp'
AZURE_SLOT_NAME: 'staging'
GITHUB_PUBLISH_SECRET: ${{ secrets.AZURE_DEPLOYMENTSLOT_STAGING }}
AZURE_WEBAPP_PACKAGE_PATH: '.'
DOTNET_VERSION: '7.0.0'
on:
push:
branches:
- staging
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v3
- name: Set up .NET Core
uses: actions/setup-dotnet#v3
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Set up dependency caching for faster builds
uses: actions/cache#v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Build with dotnet
run: dotnet build --configuration Release
- name: dotnet publish
run: dotnet publish -c Release -o ${{env.DOTNET_ROOT}}/myapp
- name: Upload artifact for deployment job
uses: actions/upload-artifact#v3
with:
name: .net-app
path: ${{env.DOTNET_ROOT}}/myapp
retention-days: 1
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'Production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
steps:
- name: Download artifact from build job
uses: actions/download-artifact#v3
with:
name: .net-app
- name: Deploy to Azure Web App
id: deploy-to-webapp
uses: azure/webapps-deploy#v2
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
slot-name: ${{ env.AZURE_SLOT_NAME }}
publish-profile: ${{ env.GITHUB_PUBLISH_SECRET }}
package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
Today, I tried to run with workflow and received the following error during the dotnet publish step:
Error: /usr/share/dotnet/sdk/7.0.200/Current/SolutionFile/ImportAfter/Microsoft.NET.Sdk.Solution.targets(36,5): error NETSDK1194: The "--output" option isn't supported when building a solution.
I expected the workflow to run without error as it has done dozens of times previously.
What's really going on here?
After a considerable amount of research and a little trial and error, I realized that I had to explicitly specify the webapp project file as an argument of the command. This is because I do still need to use the output option, so Github knows where to find the files in the subsequent deploy workflow.
Then there was the matter of figuring out the file path for the project file. This may vary for others based on their specific Visual Studio solution file structure.
Here is the fix that worked to resolve this issue (assume that when I created my project in VS, I named it MyWebApp:
- name: dotnet publish
run: dotnet publish ~/work/MyWebApp/MyWebApp/MyWebApp/MyWebApp.csproj -c Release -o ${{env.DOTNET_ROOT}}/myapp
Yes, that's 3 directories deep. The project file in my Windows file explorer is only 2 directories deep.
Hope this helps someone.
The reason for this is a update by .NET according to This guy, what worked for me was changing
--output .
To
--property:PackageOutputPath=.

How to pass a github secret to asp.net core app deployed using github action?

I want to use GitHub secrets inside the repository code.
The repository is an asp.net core web app. I am deploying the app to the Azure app service using Github actions.
I have tried declaring env variable in the workflow like this
# Docs for the Azure Web Apps Deploy action: https://go.microsoft.com/fwlink/?linkid=2134798
# More GitHub Actions for Azure: https://go.microsoft.com/fwlink/?linkid=2135048
name: Azure App Service - TestJuzer(Production), Build and deploy DotnetCore app
on:
push:
branches:
- master
env:
TEST_STRING: ${{ secrets.TEST_STRING }}
jobs:
build-and-deploy:
runs-on: windows-latest
steps:
# checkout the repo
- name: 'Checkout Github Action'
uses: actions/checkout#master
- name: Set up Node.js '12.x'
uses: actions/setup-node#v1
with:
node-version: '12.x'
- name: Set up .NET Core
uses: actions/setup-dotnet#v1
with:
dotnet-version: '5.0.x'
- name: Build with dotnet
run: dotnet build --configuration Release
env:
TEST_STRING: ${{ secrets.TEST_STRING }}
- name: dotnet publish
run: dotnet publish -c Release -o ${{env.DOTNET_ROOT}}/myapp
- name: Run Azure webapp deploy action using publish profile credentials
uses: azure/webapps-deploy#v2
with:
app-name: TestJuzer
slot-name: Production
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_461CFB6B8D42419FA7F58944D621BA78 }}
package: ${{env.DOTNET_ROOT}}/myapp
env:
TEST_STRING: ${{ secrets.TEST_STRING }}
and accessing the env variable in .net like this
Environment.GetEnvironmentVariable("TEST_STRING")
"TEST_STRING" is the name of the secret. But I am getting null.
I want to pass secret as an environment variable in the workflow and use it in the deployed app.
Any help appreciated Thanks
You set env variable on agent machine. And here you should rather set it on App Service. You could use Azure App Service Settings:
Here is sample workflow:
# .github/workflows/configureAppSettings.yml
on: [push]
jobs:
build:
runs-on: windows-latest
steps:
- uses: azure/login#v1
with:
creds: '${{ secrets.AZURE_CREDENTIALS }}'
- uses: azure/appservice-settings#v1
with:
app-name: 'my-app'
slot-name: 'staging' # Optional and needed only if the settings have to be configured on the specific deployment slot
app-settings-json: '${{ secrets.APP_SETTINGS }}'
connection-strings-json: '${{ secrets.CONNECTION_STRINGS }}'
general-settings-json: '{"alwaysOn": "false", "webSocketsEnabled": "true"}' #'General configuration settings as Key Value pairs'
id: settings
- run: echo "The webapp-url is ${{ steps.settings.outputs.webapp-url }}"
- run: |
az logout
In you case it could be like:
- name: Set Web App settings
uses: Azure/appservice-settings#v1
with:
app-name: 'node-rnc'
app-settings-json: |
[
{
"name": "TEST_STRING",
"value": "${{ secrets.TEST_STRING }}",
"slotSetting": false
}
]

GitHub CI: Push React build to another repo

I've set a GitHub action that make a build of my React application.
I need that build to be pushed to another repo that I'm using to keep track of the builds.
This is the action that is actually running:
on:
push:
branches: [master]
jobs:
build:
name: create-package
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14]
steps:
- uses: actions/checkout#v2
- uses: actions/setup-node#v2
name: Use Node.js 14
with:
node-version: ${{ matrix.node-version }}
#- name: Install dependencies
- run: npm ci
- run: npm run build --if-present
env:
CI: false
copy:
runs-on: ubuntu-latest
needs: build
steps:
- name: Copy to another repo
uses: andstor/copycat-action#v3
with:
personal_token: ${{ secrets.API_TOKEN_GITHUB }}
src_path: build
dst_path: /.
dst_owner: federico-arona
dst_repo_name: test-build
dst_branch: main
By the way when the action run the copy job it fails with the following message:
cp: can't stat 'origin-repo/build': No such file or directory
What am I doing wrong?
For anyone that needs an answer on this.
The problem was related to the fact that I was using two different jobs, one to run the build and one to copy that build to another repo.
This won't work because each job has its own runner and its own file system, meaning that the data aren't shared between jobs.
To avoid this problem I made all on in one job. Another solution is to pass the build between jobs as artifact:
https://docs.github.com/en/actions/guides/storing-workflow-data-as-artifacts#passing-data-between-jobs-in-a-workflow
Another problem was related to the copy action I was using. For some reason that action didn't find the build directory, probably because its assuming a different working directory. I switched to another action.
Here's the final result:
on:
push:
branches: [master]
jobs:
build:
name: create-package
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14]
steps:
- uses: actions/checkout#v2
- uses: actions/setup-node#v2
name: Use Node.js 14
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
env:
CI: false
- run: ls
- name: Copy to another repo
uses: andstor/copycat-action#v3
with:
personal_token: ${{ secrets.API_TOKEN_GITHUB }}
src_path: build
dst_path: /.
dst_owner: federico-arona
dst_repo_name: test-build
dst_branch: main

How to set and access an environment variable in GitHub Actions?

I am in the process of automating my react-native Expo release-cycle. I am using release channels in Expo to build staging and production builds. For example, on every push to staging-v1 GitHub branch, the action below is triggered.
//staging.yaml
name: Release to staging
on:
push:
branches:
- staging*
jobs:
publish:
name: Install and publish on staging channel
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v1
- uses: actions/setup-node#v1
with:
node-version: 12.x
- uses: expo/expo-github-action#v5
with:
expo-version: 3.x
expo-username: ${{ secrets.EXPO_CLI_USERNAME }}
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
expo-packager: npm
- run: npm install
- run: expo publish --release-channel ${{ GITHUB_REF }}
{{ GITHUB_REF }} holds the current branch name. So when I push my changes to staging-v1 this action runs. However, I am getting this error.
I've tried setting env variables, it did not work also. I just want to append my branch_name to the expo publish command. Ultimately, when building, the run command should look like this.
- run: npm install
- run: expo publish --release-channel staging-v1
Any insight into this problem will be greatly appreciated. Thanks :)
I built a GitHub Action for this: FranzDiebold/github-env-vars-action
The usage is as follows:
steps:
- uses: FranzDiebold/github-env-vars-action#v1.2.0
- name: Print environment variables
run: |
echo "GITHUB_REPOSITORY_SLUG=$GITHUB_REPOSITORY_SLUG"
echo "GITHUB_REPOSITORY_OWNER=$GITHUB_REPOSITORY_OWNER"
echo "GITHUB_REPOSITORY_OWNER_SLUG=$GITHUB_REPOSITORY_OWNER_SLUG"
echo "GITHUB_REPOSITORY_NAME=$GITHUB_REPOSITORY_NAME"
echo "GITHUB_REPOSITORY_NAME_SLUG=$GITHUB_REPOSITORY_NAME_SLUG"
echo "GITHUB_REF_SLUG=$GITHUB_REF_SLUG"
echo "GITHUB_REF_NAME=$GITHUB_REF_NAME"
echo "GITHUB_REF_NAME_SLUG=$GITHUB_REF_NAME_SLUG"
echo "GITHUB_SHA_SHORT=$GITHUB_SHA_SHORT"
An example output is:
GITHUB_REPOSITORY_SLUG=ajinkabeer-test-repo
GITHUB_REPOSITORY_OWNER=ajinkabeer
GITHUB_REPOSITORY_OWNER_SLUG=ajinkabeer
GITHUB_REPOSITORY_NAME=test-repo
GITHUB_REPOSITORY_NAME_SLUG=test-repo
GITHUB_REF_SLUG=refs-heads-staging-v1
GITHUB_REF_NAME=staging-v1
GITHUB_REF_NAME_SLUG=staging-v1
GITHUB_SHA_SHORT=e2e4f0ab
A demo for all Operating systems (Linux, macOS and Windows) is also available in the demo workflows file of the repository!
After a lot of trial and error, I've found the solution. I used the github-slug-action workflow to access my branch_name.
name: Release to staging
on:
push:
branches:
- staging*
jobs:
publish:
name: Install and publish on staging channel
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v1
- uses: actions/setup-node#v1
with:
node-version: 12.x
- uses: expo/expo-github-action#v5
with:
expo-version: 3.x
expo-username: ${{ secrets.EXPO_CLI_USERNAME }}
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
expo-packager: npm
- run: npm install
- name: Run tests
run: |
npm test
- uses: rlespinasse/github-slug-action#v2.x
- run: expo publish --release-channel=${{ env.GITHUB_REF_SLUG }}
Here is the log.

How to set cache-control to max-age=0 with github s3 sync action

I am uploading a vue app to my s3 bucket on every merge to master. My problem is that the invalidation of the cache does not fully work. My next step is adding a metadata to the object index.html on every push. For that I wanted to ask how to add it in the github action jakejarvis/s3-sync-action (https://github.com/marketplace/actions/s3-sync)?
Or do I have to use another github action to accomplish that?
My workflow looks like that at the moment:
name: Build
on:
push:
branches: [master]
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: Use Node.js 12.x
uses: actions/setup-node#v1
with:
node-version: '12.x'
- name: npm install
run: |
npm ci
- name: build
run: |
npm run build
- name: Deploy to S3
uses: jakejarvis/s3-sync-action#master
with:
args: --acl public-read --delete
env:
AWS_S3_BUCKET: ${{ secrets.AWS_STAGING_BUCKET_NAME }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
SOURCE_DIR: 'dist'
- name: Invalidate cloudfront
uses: muratiger/invalidate-cloudfront-and-wait-for-completion-action#master
env:
DISTRIBUTION_ID: ${{ secrets.AWS_STAGING_DISTRIBUTION_ID }}
PATHS: '/*'
AWS_REGION: ${{ secrets.AWS_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
The result I am looking for is that the index.html has another metadata Cache-Control: max-age=0 after every deployment. At the moment I am adding it by hand in the s3 management console which is not a good solution for me. Because the metadata is gone after every deployment.
I found answers on how to do it with the aws-cli but I don't know it it is possible to add that in my action.
aws s3 cp s3://[mybucket]/index.html s3://[mybucket]/index.html --metadata-directive REPLACE \
--expires 2034-01-01T00:00:00Z --acl public-read --cache-control max-age=0,public
PS: I know I need to write tests 🙈
In your example:
with:
args: --acl public-read --delete
args takes effect because it's passed through as-is to the aws s3 invocation, which has $* at the end:
sh -c "aws s3 sync ${SOURCE_DIR:-.} s3://${AWS_S3_BUCKET}/${DEST_DIR} \
--profile s3-sync-action \
--no-progress \
${ENDPOINT_APPEND} $*"
If you'd also like to set --cache-control max-age=0,public then add it to the args:
with:
args: --acl public-read --delete --cache-control max-age=0,public