Go Release Binaries failed - go

I'm trying to build my go project with github action and releasing it on my own repository. As mentioned Go Release Binaries, I wrote my own .yml file but I got error on building flow.
name: Release API binary
on:
push:
tags:
- "*"
jobs:
build:
name: GO API build
runs-on: ubuntu-latest
strategy:
matrix:
goos: [linux]
goarch: [amd64, arm64]
steps:
- name: Check out code into the Go module directory
uses: actions/checkout#v3
- name: Setup go and release
uses: wangyoucao577/go-release-action#v1.34
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
project_path: "./api"
binary_name: "flying-server"
The project directory is like this:
-> Project root
--> api
---> main.go
---> go.mod
---> go.sum
My error on github action is just like this
Additional Note:
I tried to create a tag version with
git tag v0.0.13
then pushed it
git push origin v0.0.13
Based on the procedure above, I want to build a Go project and release it on the repository. I searched for this error, but I could not understand where the problem was.

Related

How to set up a monorepo in SonarCloud with a Java + Angular application

I have developed an application where the backend is developed using Java language (with maven) and the frontend is using Angular language. I host both parts in one project in github.
Now I am interested on the use of SonarQube on SonarCloud. For this purpose, I am following the information gathered from the community sonarsource and the standard documentation from sonarcloud. The idea is to use GiHub Actions for analyzing the projects.
What I have created is a .github/workflows/build.yml on the root folder with the content:
name: Build
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened]
jobs:
sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 11
uses: actions/setup-java#v1
with:
java-version: 11
- name: Cache SonarCloud packages
uses: actions/cache#v1
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache#v1
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=kendo-tournament-backend
with:
projectBaseDir: ./backend/
- name: SonarCloud Frontend Scan
uses: SonarSource/sonarcloud-github-action#master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
projectBaseDir: ./frontend/
Where basically, I create some steps for executing the maven project, and another extra step to execute the frontend. On both of them, I included the projectBaseDir with the path to both projects' folders as specified here.
Also, as suggested on the documentation, I have included a sonar-project.properties on the root folder of the frontend folder with:
sonar.projectKey=kendo-tournament-frontend
sonar.organization=softwaremagico
# This is the name and version displayed in the SonarCloud UI.
#sonar.projectName=Kendo Tournament Manager Frontend
#sonar.projectVersion=1.0
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
#sonar.sources=.
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
And for the backend, I have updated the root pom.xml with the:
<properties>
<sonar.organization>softwaremagico</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
</properties>
As required.
But, no analyses scan is launch for any of both projects. And SonarCloud looks like is ignoring the configuration.
Probably, something is missing but I cannot imagine what. What steps are needed to set up a monorepository correctly using Java and Angular in Github?
Ok, after the example obtained from here. The changes I have made are:
Two different workflows on github, one for backend and one for frontend. Not one workflow with all steps together.
Include two different sonar-project.properties. One inside the backend folder, and one inside the frontend folder. Now I have added the sonar.sources line as follows:
sonar.projectKey=kendo-tournament-backend
sonar.organization=softwaremagico
sonar.sources=.
That ensures that is only for this folder.
For launching CircleCi with Sonar (for backend) edit file .circleci/config.yml:
version: 2.1
jobs:
build:
docker:
- image: 'circleci/openjdk:11-jdk'
working_directory: ~/KendoTournamentManager/backend
steps:
- checkout:
path: ~/KendoTournamentManager
- run:
name: Analyze on SonarCloud
command: mvn verify sonar:sonar -Dsonar.projectKey=kendo-tournament-backend
workflows:
main:
jobs:
- build:
context: SonarCloud
And now seems working fine:

Issues creating a CD based release on Github (WPF .NET 5.0)

I'm trying to put together a CI / CD pipeline for GitHub and strugglign with attaching my build artifact to the release. Here's my ci.yml
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
Build:
runs-on: windows-latest
env:
BuildPath: ${{ github.workspace }}\BuildTesting\bin\Release\net5.0-windows
steps:
- uses: actions/checkout#v2
- name: Setup .NET SDK
uses: actions/setup-dotnet#v1.8.1
with:
dotnet-version: 5.0.x
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Upload a Build Artifact
uses: actions/upload-artifact#v2.2.4
with:
name: thingy
path: ${{ github.workspace }}\BuildTesting\bin\Release\net5.0-windows
retention-days: 1
That runs well and I get a release artifact:
I was under the impression I'd be able to download that existing artifact but I couldn't get my head around why actions/download-artifact isn't downloading anything. So I found another article and in their cd step they were re-building, so I figured that in doing that at least I'd have a fresh build in the cd workflow to pull from. So I create a release triggered on tag push events. I can't use most zip utilities becuase they don't run on windows. I have to user windows-latest as the target framework for WPF desktop applications has to be net5.0-windows and using ubuntu-latest it fails. I tried papeloto/action-zip#v1 and in one case I managed to get a zip file which then attached to the release successfully but was only 22 bytes, so empty once I downloaded it. Here's my cd.yml:
name: CD
on:
push:
tags:
- '*'
jobs:
Release:
runs-on: windows-latest
env:
BuildPath: ${{ github.workspace }}\BuildTesting\bin\Release\net5.0-windows
ZipName: TheThing.zip
steps:
# Build the solution
- uses: actions/checkout#v2
- name: Setup .NET SDK
uses: actions/setup-dotnet#v1.8.1
with:
dotnet-version: 5.0.x
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Zip the release
uses: << What should I use to zip ${{ env.BuildPath }} ? >>
# Create a Release on the GitHub project
- name: Create release
id: create_release
uses: actions/create-release#v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: false
prerelease: false
# Upload the Build Artifact to the Release
- name: Update release asset
id: upload-release-asset
uses: actions/upload-release-asset#v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: .\${{ env.ZipName }}
asset_name: ${{ env.ZipName }}
asset_content_type: application/zip
Can anyone please recommend a GitHub action for zipping a folder that will work for windows-latest ... or another approach?
Long term I want to go with semantic versioning but GitVersion overwhelmed me last time I tried, granted I'd never working with yml builds before. I'd like to keep this as simple as possible as I'm starting to grok the basics of what's going on and once I get past this I'll start looking into GitVersion.
I'm using a test repository located here so you can see the whole thing.
You may use PowerShell to zip your artifacts using 7Zip. Please check my repository in GitHub. That compile a WPF app, compress the artifacts, create a prerelease and upload files under that release.

How to goreleaser to build sub-folder in github

I use goreleaser to build in github action.
Because my main.go in ./cmd/tes_cli, it always show error in github action.
repo does not contain a main function.
I check the original document, it seems "builds" could works. my configuration could not add builds
name: Release Go project
on:
push:
tags:
- "*" # triggers only if push new tag version, like `0.8.4` or else
jobs:
build:
name: GoReleaser build
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout#v2
with:
fetch-depth: 0 # See: https://goreleaser.com/ci/actions/
- name: Set up Go 1.14
uses: actions/setup-go#v2
with:
go-version: 1.14
id: go
- name: Run GoReleaser
uses: goreleaser/goreleaser-action#master
with:
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Add an extra configuration file to resolve it.
Refer https://github.com/kkdai/disqus-importor-go/pull/4/files
args: release -f .goreleaser.yml --rm-dist
link to another config file.
# .goreleaser.yml
project_name: import_disqus_cli
builds:
- env: [CGO_ENABLED=0]
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
id: "import_disqus_cli"
dir: .
main: ./cmd/test_cli

Go GitHub Actions clone private repository to be used from main code

I am trying to automatically build and test my go code on pushes to the master branch of my GitHub repository using GitHub actions.
The basic configuration to do so works perfectly fine:
name: Build & Test
on:
push:
branches:
- master
jobs:
test:
## We want to define a strategy for our job
strategy:
## this will contain a matrix of all of the combinations
## we wish to test again:
matrix:
go-version: [1.14.x] #[1.12.x, 1.13.x, 1.14.x]
platform: [ubuntu-latest] #[ubuntu-latest, macos-latest, windows-latest]
## Defines the platform for each test run
runs-on: ${{ matrix.platform }}
## the steps that will be run through for each version and platform
## combination
steps:
## sets up go based on the version
- name: Install Go
uses: actions/setup-go#v2
with:
go-version: ${{ matrix.go-version }}
env:
GOPATH: /home/runner/work/project
GO111MODULE: "on"
## runs a build
- name: Build
run: go build src/
env:
GOPATH: /home/runner/work/project
GO111MODULE: "on"
## runs go test ./...
- name: Test
run: go test ./...
env:
GOPATH: /home/runner/work/project
GO111MODULE: "on"
However, the repository has another (private) repository as direct dependency, so I need to clone this as well after checking out the main repository.
- name: Check out dependency
uses: actions/checkout#v2
with:
repository: mydependency
token: ${{ secrets.GIT_ACCESS_TOKEN }}
path: src/dependency
Then it will not find the dependency as it is not accessible from GOROOT.
src/main.go:20:2: package dependency is not in GOROOT (/opt/hostedtoolcache/go/1.14.15/x64/src/dependency)
The issue here is that the path is not accessible within the GitHub action, so I cannot clone the repository to this specific path.
I of course can specify the GOROOT as env variable for setup-go, build and test in such a way that the dependency is found, but then it will not find native go packages anymore.
env:
GOPATH: /home/runner/work/project/go
GOROOT: /home/runner/work/project
GO111MODULE: "on"
package bufio is not in GOROOT (/home/runner/work/project/src/bufio)
So, I managed to solve the issue myself. The checkout#v2 action does only allow relative paths, however, we can just clone the dependency manually.
- name: Checkout dependencies
run: |
git clone https://${{ secrets.GIT_ACCESS_TOKEN }}#github.com/myorg/dependency.git ${GOROOT}/src/dependency
In this way, it will also work with different Go versions yielding in a different GOROOT.
The full pipeline steps:
steps:
## sets up go based on the version
- name: Install Go
uses: actions/setup-go#v2
with:
go-version: ${{ matrix.go-version }}
env:
GO111MODULE: "on"
- name: Checkout dependencies
run: |
git clone https://${{ secrets.GIT_ACCESS_TOKEN }}#github.com/myorg/dependency.git
## checks out our code locally so we can work with the files
- name: Checkout code
uses: actions/checkout#v2
## runs a build
- name: Build
run: go build src
## runs go test ./...
- name: Test
run: go test ./...

How to push nuget package in GitHub actions

I am trying to use GitHub actions to generate a NuGet package from my project and push it to the (private) GitHub registry.
My script ([NAME] fields redacted):
name: Update NuGet
on: [push]
jobs:
build:
runs-on: ubuntu-latest
name: Update NuGet
steps:
- uses: actions/checkout#master
- uses: actions/setup-dotnet#v1
with:
dotnet-version: '2.2.105'
- name: Package Release
run: |
cd [SOLUTION_FOLDER]
dotnet pack -c Release -o out
- name: Publish Nuget to GitHub registry
run: dotnet nuget push ./[SOLUTION_FOLDER]/[PROJECT_FOLDER]/out/$(ls ./[SOLUTION_FOLDER]/[PROJECT_FOLDER]/out) -s https://nuget.pkg.github.com/[USERNAME]/index.json -k ${GITHUB_TOKEN}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Log output:
info : Pushing [PROJECT_FOLDER].3.4.23.nupkg to 'https://nuget.pkg.github.com/[USERNAME]'...
info : PUT https://nuget.pkg.github.com/[USERNAME]/
info : An error was encountered when fetching 'PUT https://nuget.pkg.github.com/[USERNAME]/'. The request will now be retried.
info : An error occurred while sending the request.
info : The server returned an invalid or unrecognized response.
info : PUT https://nuget.pkg.github.com/[USERNAME]/
info : An error was encountered when fetching 'PUT https://nuget.pkg.github.com/[USERNAME]/'. The request will now be retried.
info : An error occurred while sending the request.
info : The server returned an invalid or unrecognized response.
info : PUT https://nuget.pkg.github.com/[USERNAME]/
error: An error occurred while sending the request.
error: The server returned an invalid or unrecognized response.
##[error]Process completed with exit code 1.
This is the coresponding GitHub issue (with a workaround option): https://github.com/NuGet/Home/issues/8580
Second Update:
I got an answer in the GitHub issue from jcansdale that says (haven't tested this):
Support for the dotnet nuget push --api-key option has now been added to GitHub Packages. For some reason this works consistently, but using basic auth (password in nuget.config file) fails randomly!
Example:
- name: Publish Nuget to GitHub registry
run: dotnet nuget push ./<project>/out/*.nupkg -k ${GITHUB_TOKEN} -s https://nuget.pkg.github.com/<organization>/index.json --skip-duplicate --no-symbols
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Update:
Based on Dids answer on GitHub my configuration works now like this:
name: NuGet Generation
on:
push:
branches:
- master
pull_request:
types: [closed]
branches:
- master
jobs:
build:
runs-on: ubuntu-18.04
name: Update NuGet package
steps:
- name: Checkout repository
uses: actions/checkout#v1
- name: Setup .NET Core # Latest
uses: actions/setup-dotnet#v1
with:
source-url: https://nuget.pkg.github.com/<organization>/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Build solution and generate NuGet package
run: |
cd <project>
dotnet pack -c Release -o out
- name: Push generated package to GitHub registry
run: dotnet nuget push ./<project>/out/*.nupkg --skip-duplicate --no-symbols true
Note: At the time of writing I needed to use --no-symbols true instead of --no-symbols to prevent exceptions in the dotnet NuGet client.
Old answer:
I switched to the Windows image and got it to work based on the example of #anangaur. This is my final code:
name: NuGet Generation
on:
push:
branches:
- master
jobs:
build:
runs-on: windows-latest
name: Update NuGet
steps:
- name: Checkout repository
uses: actions/checkout#master
# latest image has .NET already installed!
# - name: Setup .NET environment
# uses: actions/setup-dotnet#v1
# with:
# dotnet-version: '2.2.105'
- name: Build solution and generate NuGet package
run: |
cd SOLUTION_FOLDER
dotnet pack -c Release -o out
- name: Install NuGet client
uses: warrenbuckley/Setup-Nuget#v1
- name: Add private GitHub registry to NuGet
run: nuget sources add -name "GPR" -Source https://nuget.pkg.github.com/ORGANIZATION_NAME/index.json -Username ORGANIZATION_NAME -Password ${{ secrets.GITHUB_TOKEN }}
- name: Push generated package to GitHub registry
run: nuget push .\SOLUTION_FOLDER\PROJECT_FOLDER\out\*.nupkg -Source "GPR" -SkipDuplicate
Here is a workaround that works on all platforms:
name: prerelease NuGet
on: [push]
jobs:
build:
runs-on: ubuntu-latest
# also works with windows-latest and macos-latest
steps:
- name: Checkout repository
uses: actions/checkout#v1
- name: Build with dotnet
run: dotnet build --configuration Release --version-suffix prerelease-$(date +%Y%m%d%H%M%S)
shell: bash
- name: Publish nuget
run: |
for f in ./[repository]/bin/Release/*.nupkg
do
curl -vX PUT -u "[user]:${{ secrets.GHPackagesToken }}" -F package=#$f https://nuget.pkg.github.com/[user]/
done
shell: bash
Notes:
this creates a datestamped prerelease build for every git push and uploads it to nuget
for the suffix to work, you need to set <VersionPrefix> instead of <Version> in your .csproj
if you don't want the prerelease suffix, remove the --version-suffix parameter
the shell is explicitly set as bash in order to allow compatibility with building on windows
you will need to replace [user] and [repository] above with your own specific values
you will need to create a personal access token with the permissions of write:packages
then create a GitHub Secret named GHPackagesToken and put the token created above in there
using GitHub Secrets eliminates the need for a separate file containing your token
this assumes you're have <GeneratePackageOnBuild>true</GeneratePackageOnBuild> in your .csproj
if you don't, then you will need an additional step running dotnet pack
make sure to specify <RepositoryUrl>...</RepositoryUrl> in your .csproj
for a working example if you can't get the above code working, see https://github.com/vslee/IEXSharp/blob/master/.github/workflows/dotnetcore.yml, which pushes to https://github.com/vslee/IEXSharp/packages (ignore all of my extraneous comments there)
I posted this bc I tried both the examples from jwillmer above, as well as #anangaur and #marza91 on the GH issue thread but neither worked for me (on any platform)
once GitHub fixes the issue of not being able to use the API key directly in the dotnet nuget push command (see initial post of GH issue), then we won't need this workaround anymore
You can use the dotnet nuget add source command:
- name: NuGet push
run: |
dotnet nuget add source https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json --name github --username ${{ github.repository_owner }} --password ${{ github.token }} --store-password-in-clear-text
dotnet nuget push **/*.nupkg --source github
The --store-password-in-clear-text option was required for me when running in a linux environment.
With this method, there's no need to modify the actions/setup-dotnet task.
Also, this method would allow you to push to multiple NuGet streams if needed.
Make sure you project file has the following
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Library</OutputType>
<PackageId>Example.PackageName</PackageId>
<Version>1.0.0</Version>
<Authors>Author Engineering</Authors>
<Company>Company Inc</Company>
<PackageDescription>This package for ...!</PackageDescription>
<RepositoryUrl>
https://github.com/YOUR_ACCOUNT/Example.PackageName</RepositoryUrl>
</PropertyGroup>
This should be your main.yaml for building, packaging, publishing, and versioning:
name: Continuous Integration
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v1
- name: Setup Dotnet Core
uses: actions/setup-dotnet#v1
with:
dotnet-version: 3.1.100
source-url: https://nuget.pkg.github.com/YOUR_ACCOUNT/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Setup Nuget Config
run: sed 's/GITHUB_TOKEN/${{ secrets.GITHUB_TOKEN }}/g' .nuget.config > nuget.config
- name: Build
run: dotnet build --configuration Release
- name: Version and Tag
id: bump_version
uses: mathieudutour/github-tag-action#v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Prep Version String
run: echo ::set-env name=VERSION_NUMBER::$(echo ${{ steps.bump_version.outputs.new_tag }} | sed 's/[v]//g')
- name: Define Package Name
run: echo ::set-env name=PACKAGE_NAME::$"Example.PackageName/bin/Release/Example.PackageName.${{ env.VERSION_NUMBER }}.nupkg"
- name: Set Nuget Package Version
uses: roryprimrose/set-vs-sdk-project-version#v1
with:
version: ${{ env.VERSION_NUMBER }}
- name: Pack
run: dotnet pack --configuration Release Example.PackageName
- name: Publish Package
run: dotnet nuget push Example.PackageName/bin/Release/*.nupkg --source https://nuget.pkg.github.com/YOUR_ACCOUNT/index.json
- name: Create Release
uses: actions/create-release#v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.bump_version.outputs.new_tag }}
release_name: Release ${{ github.ref }}
The other answers were so long, I don't know why. This is what I do:
For NuGet.org:
- name: Push Package to NuGet.org
run: dotnet nuget push *.nupkg -k ${{ secrets.NUGET_ORG_API_KEY }} -s https://api.nuget.org/v3/index.json
For GitHub.com:
- name: Push Package to GitHub.com
run: dotnet nuget push *.nupkg -k ${{ secrets.GITHUB_TOKEN }} -s https://nuget.pkg.github.com/USERNAME/index.json
My working solution:
replace 'usernamecompanyname' with a valid value for your repo
I kept the build and pack separated to allow for easier debugging if something goes wrong
you can set ACTIONS_RUNNER_DEBUG variable in your github secrets to true to allow for more detailed debuging
Change dotnet-version to your desired dotnet-sdk version
No need to specify GITHUB_TOKEN in your github repo secrests, this token is present by default
build_and_publish_nuget.yml:
name: Build and publish package
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout#master
- name: Setup .NET environment
uses: actions/setup-dotnet#v1
with:
dotnet-version: '3.1.102'
source-url: https://nuget.pkg.github.com/usernamecompanyname/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Build project
run: dotnet build -c Release
- name: Generate a NuGet package
run: dotnet pack --no-build -c Release -o .
- name: Push to GitHub package registry
run: dotnet nuget push *.nupkg
GitHub has been having intermittent issues with publish NuGet Packages to GitHub Packages. I reached out to support and they gave me two options.
Option 1: CURL
curl -vX PUT -u "<username>:<TOKEN>" -F package=#PATH-TO-PKG-FILE.nupkg https://nuget.pkg.github.com/<OWNER>/
Option 2: DOTNET GPR TOOL
https://github.com/jcansdale/gpr
dotnet tool install gpr -g
gpr push PATH-TO-PKG-FILE.nupkg -k <TOKEN>
I went with Option 2 in my GitHub Action Workflow:
$file = Get-ChildItem -Path <where I output my nupkg file to> -Recurse -Filter *.nupkg | Select -First 1
gpr push $file.FullName -k ${{secrets.GITHUB_TOKEN}}

Resources