mirror of
https://github.com/dagger/dagger-for-github.git
synced 2025-12-31 04:30:01 +11:00
chore: Set aside old content
Signed-off-by: Jeremy Adams <jeremy@dagger.io>
This commit is contained in:
parent
97a086c722
commit
7815dae500
123 changed files with 0 additions and 19430 deletions
|
|
@ -1,2 +0,0 @@
|
|||
/coverage
|
||||
/node_modules
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# This file is for unifying the coding style for different editors and IDEs.
|
||||
# More information at http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[test/**]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es2021": true,
|
||||
"jest/globals": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"jest",
|
||||
"prettier"
|
||||
]
|
||||
}
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
|
|
@ -1,2 +0,0 @@
|
|||
/dist/** linguist-generated=true
|
||||
/lib/** linguist-generated=true
|
||||
32
.github/CONTRIBUTING.md
vendored
32
.github/CONTRIBUTING.md
vendored
|
|
@ -1,32 +0,0 @@
|
|||
## Contributing
|
||||
|
||||
Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.
|
||||
|
||||
Contributions to this project are [released](https://docs.github.com/en/github/site-policy/github-terms-of-service#6-contributions-under-repository-license)
|
||||
to the public under the [project's open source license](LICENSE).
|
||||
|
||||
## Submitting a pull request
|
||||
|
||||
1. [Fork](https://github.com/dagger/dagger-for-github/fork) and clone the repository
|
||||
2. Configure and install the dependencies: `yarn install`
|
||||
3. Create a new branch: `git checkout -b my-branch-name`
|
||||
4. Make your changes
|
||||
5. Make sure the tests pass: `docker buildx bake test`
|
||||
6. Format code and build javascript artifacts: `docker buildx bake pre-checkin`
|
||||
7. Validate all code has correctly formatted and built: `docker buildx bake validate`
|
||||
8. Push to your fork and [submit a pull request](https://github.com/dagger/dagger-for-github/compare)
|
||||
9. Pat your self on the back and wait for your pull request to be reviewed and merged.
|
||||
|
||||
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
|
||||
|
||||
- Write tests.
|
||||
- Make sure the `README.md` and any other relevant **documentation are kept up-to-date**.
|
||||
- We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.
|
||||
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as **separate pull requests**.
|
||||
- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
||||
|
||||
## Resources
|
||||
|
||||
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
|
||||
- [Using Pull Requests](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
|
||||
- [GitHub Help](https://docs.github.com/en)
|
||||
29
.github/SUPPORT.md
vendored
29
.github/SUPPORT.md
vendored
|
|
@ -1,29 +0,0 @@
|
|||
# Support [](https://isitmaintained.com/project/dagger/dagger-for-github)
|
||||
|
||||
## Reporting an issue
|
||||
|
||||
Please do a search in [open issues](https://github.com/dagger/dagger-for-github/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed.
|
||||
|
||||
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
|
||||
|
||||
:+1: - upvote
|
||||
|
||||
:-1: - downvote
|
||||
|
||||
If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.
|
||||
|
||||
## Writing good bug reports and feature requests
|
||||
|
||||
File a single issue per problem and feature request.
|
||||
|
||||
* Do not enumerate multiple bugs or feature requests in the same issue.
|
||||
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
|
||||
|
||||
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
|
||||
|
||||
You are now ready to [create a new issue](https://github.com/dagger/dagger-for-github/issues/new/choose)!
|
||||
|
||||
## Closure policy
|
||||
|
||||
* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines.
|
||||
* Issues that go a week without a response from original poster are subject to closure at my discretion.
|
||||
BIN
.github/dagger-for-github.png
vendored
BIN
.github/dagger-for-github.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
BIN
.github/dagger.png
vendored
BIN
.github/dagger.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB |
18
.github/dependabot.yml
vendored
18
.github/dependabot.yml
vendored
|
|
@ -1,18 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
labels:
|
||||
- ":game_die: dependencies"
|
||||
- ":robot: bot"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "production"
|
||||
labels:
|
||||
- ":game_die: dependencies"
|
||||
- ":robot: bot"
|
||||
94
.github/workflows/ci.yml
vendored
94
.github/workflows/ci.yml
vendored
|
|
@ -1,94 +0,0 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 10 * * *' # everyday at 10am
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'releases/v*'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
do:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- latest
|
||||
- 0.2.232
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Dagger
|
||||
uses: ./
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
cmds: |
|
||||
project update
|
||||
do test
|
||||
workdir: ./test/ci
|
||||
|
||||
args-deprecated:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Dagger
|
||||
uses: ./
|
||||
with:
|
||||
cmds: |
|
||||
project update
|
||||
do test
|
||||
workdir: ./test/ci
|
||||
|
||||
install-only:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- 0.2.232
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Dagger
|
||||
uses: ./
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
install-only: true
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
dagger-cue version
|
||||
|
||||
build-ref:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ref:
|
||||
- refs/heads/cue-sdk
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Dagger
|
||||
uses: ./
|
||||
with:
|
||||
version: https://github.com/dagger/dagger.git#${{ matrix.ref }}
|
||||
cmds: |
|
||||
project update
|
||||
do test
|
||||
workdir: ./test/ci
|
||||
33
.github/workflows/test.yml
vendored
33
.github/workflows/test.yml
vendored
|
|
@ -1,33 +0,0 @@
|
|||
name: test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'releases/v*'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: validate
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: test
|
||||
-
|
||||
name: Upload coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: ./coverage/clover.xml
|
||||
96
.gitignore
vendored
96
.gitignore
vendored
|
|
@ -1,96 +0,0 @@
|
|||
/.dev
|
||||
node_modules/
|
||||
lib
|
||||
|
||||
# Jetbrains
|
||||
/.idea
|
||||
/*.iml
|
||||
|
||||
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"printWidth": 240,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
import {describe, expect, jest, it} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as context from '../src/context';
|
||||
|
||||
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||
const tmpDir = path.join('/tmp/.dagger-jest').split(path.sep).join(path.posix.sep);
|
||||
if (!fs.existsSync(tmpDir)) {
|
||||
fs.mkdirSync(tmpDir, {recursive: true});
|
||||
}
|
||||
return tmpDir;
|
||||
});
|
||||
|
||||
describe('getInputList', () => {
|
||||
it('handles single line correctly', async () => {
|
||||
await setInput('foo', 'bar');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar']);
|
||||
});
|
||||
|
||||
it('handles multiple lines correctly', async () => {
|
||||
setInput('foo', 'bar\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('remove empty lines correctly', async () => {
|
||||
setInput('foo', 'bar\n\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('handles comma correctly', async () => {
|
||||
setInput('foo', 'bar,baz');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('remove empty result correctly', async () => {
|
||||
setInput('foo', 'bar,baz,');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('handles different new lines correctly', async () => {
|
||||
setInput('foo', 'bar\r\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('handles different new lines and comma correctly', async () => {
|
||||
setInput('foo', 'bar\r\nbaz,bat');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz', 'bat']);
|
||||
});
|
||||
|
||||
it('handles multiple lines and ignoring comma correctly', async () => {
|
||||
setInput('driver-opts', 'foo,bar\nbaz');
|
||||
const res = await context.getInputList('driver-opts', true);
|
||||
expect(res).toEqual(['foo,bar', 'baz']);
|
||||
});
|
||||
|
||||
it('handles different new lines and ignoring comma correctly', async () => {
|
||||
setInput('driver-opts', 'foo,bar\r\nbaz');
|
||||
const res = await context.getInputList('driver-opts', true);
|
||||
expect(res).toEqual(['foo,bar', 'baz']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('asyncForEach', () => {
|
||||
it('executes async tasks sequentially', async () => {
|
||||
const testValues = [1, 2, 3, 4, 5];
|
||||
const results: number[] = [];
|
||||
|
||||
await context.asyncForEach(testValues, async value => {
|
||||
results.push(value);
|
||||
});
|
||||
|
||||
expect(results).toEqual(testValues);
|
||||
});
|
||||
});
|
||||
|
||||
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
|
||||
function getInputName(name: string): string {
|
||||
return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
|
||||
}
|
||||
|
||||
function setInput(name: string, value: string): void {
|
||||
process.env[getInputName(name)] = value;
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
import {describe, expect, it} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as dagger from '../src/dagger';
|
||||
|
||||
describe('build', () => {
|
||||
it.skip('valid', async () => {
|
||||
const daggerBin = await dagger.build('https://github.com/dagger/dagger.git#refs/pull/2161/head');
|
||||
expect(fs.existsSync(daggerBin)).toBe(true);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('install', () => {
|
||||
it('acquires latest version of dagger-cue', async () => {
|
||||
const daggerBin = await dagger.install('latest');
|
||||
expect(fs.existsSync(daggerBin)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
it('acquires latest 0.2.232 version', async () => {
|
||||
const daggerBin = await dagger.install('0.2.232');
|
||||
expect(fs.existsSync(daggerBin)).toBe(true);
|
||||
}, 100000);
|
||||
});
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
import {describe, expect, it} from '@jest/globals';
|
||||
import * as git from '../src/git';
|
||||
|
||||
describe('git', () => {
|
||||
it('returns git remote ref', async () => {
|
||||
const ref: string = await git.getRemoteSha('https://github.com/dagger/dagger.git', 'refs/pull/2161/head');
|
||||
expect(ref).toEqual('aeb8ea3973a7815fff7cbd16f986811baa08ae2f');
|
||||
});
|
||||
});
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import {describe, expect, test} from '@jest/globals';
|
||||
import * as util from '../src/util';
|
||||
|
||||
describe('isValidUrl', () => {
|
||||
test.each([
|
||||
['https://github.com/dagger/dagger.git', true],
|
||||
['https://github.com/dagger/dagger.git#refs/pull/2161/head', true],
|
||||
['v0.2.7', false]
|
||||
])('given %p', async (url, expected) => {
|
||||
expect(util.isValidUrl(url)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
comment: false
|
||||
github_checks:
|
||||
annotations: false
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG NODE_VERSION=16
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS base
|
||||
RUN apk add --no-cache cpio findutils git
|
||||
WORKDIR /src
|
||||
|
||||
FROM base AS deps
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/node_modules <<EOT
|
||||
yarn install
|
||||
mkdir /vendor
|
||||
cp yarn.lock /vendor
|
||||
EOT
|
||||
|
||||
FROM scratch AS vendor-update
|
||||
COPY --from=deps /vendor /
|
||||
|
||||
FROM deps AS vendor-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /vendor/* .
|
||||
diff=$(git status --porcelain -- yarn.lock)
|
||||
if [ -n "$diff" ]; then
|
||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"'
|
||||
echo "$diff"
|
||||
exit 1
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS build
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/node_modules <<EOT
|
||||
yarn run build
|
||||
mkdir /out
|
||||
cp -Rf dist /out/
|
||||
EOT
|
||||
|
||||
FROM scratch AS build-update
|
||||
COPY --from=build /out /
|
||||
|
||||
FROM build AS build-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /out/* .
|
||||
diff=$(git status --porcelain -- dist)
|
||||
if [ -n "$diff" ]; then
|
||||
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
|
||||
echo "$diff"
|
||||
exit 1
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS format
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/node_modules <<EOT
|
||||
yarn run format
|
||||
mkdir /out
|
||||
find . -name '*.ts' -not -path './node_modules/*' | cpio -pdm /out
|
||||
EOT
|
||||
|
||||
FROM scratch AS format-update
|
||||
COPY --from=format /out /
|
||||
|
||||
FROM deps AS lint
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run lint
|
||||
|
||||
FROM deps AS test
|
||||
ENV RUNNER_TEMP=/tmp/github_runner
|
||||
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run test --coverageDirectory=/tmp/coverage
|
||||
|
||||
FROM scratch AS test-coverage
|
||||
COPY --from=test /tmp/coverage /
|
||||
2
dist/index.js
vendored
2
dist/index.js
vendored
File diff suppressed because one or more lines are too long
1
dist/index.js.map
vendored
1
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
128
dist/licenses.txt
vendored
128
dist/licenses.txt
vendored
|
|
@ -1,128 +0,0 @@
|
|||
@actions/core
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@actions/exec
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@actions/http-client
|
||||
MIT
|
||||
Actions Http Client for Node.js
|
||||
|
||||
Copyright (c) GitHub, Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
@actions/io
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@actions/tool-cache
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
semver
|
||||
ISC
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
tunnel
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012 Koichi Kobayashi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
uuid
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2010-2020 Robert Kieffer and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
1
dist/sourcemap-register.js
vendored
1
dist/sourcemap-register.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1,53 +0,0 @@
|
|||
group "default" {
|
||||
targets = ["build"]
|
||||
}
|
||||
|
||||
group "pre-checkin" {
|
||||
targets = ["vendor-update", "format", "build"]
|
||||
}
|
||||
|
||||
group "validate" {
|
||||
targets = ["lint", "build-validate", "vendor-validate"]
|
||||
}
|
||||
|
||||
target "build" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "build-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "build-validate" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "build-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "format" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "format-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "lint" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "lint"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "vendor-update" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "vendor-validate" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "test" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "test-coverage"
|
||||
output = ["./coverage"]
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true
|
||||
};
|
||||
49
package.json
49
package.json
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
"name": "dagger-for-github",
|
||||
"description": "GitHub Action for Dagger, a programmable deployment system",
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"build": "ncc build src/main.ts --source-map --minify --license licenses.txt",
|
||||
"lint": "eslint src/**/*.ts __tests__/**/*.ts",
|
||||
"format": "eslint --fix src/**/*.ts __tests__/**/*.ts",
|
||||
"test": "jest --coverage",
|
||||
"all": "yarn run build && yarn run format && yarn test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/dagger/dagger-for-github.git"
|
||||
},
|
||||
"keywords": [
|
||||
"actions",
|
||||
"dagger"
|
||||
],
|
||||
"author": "Dagger",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "CrazyMax",
|
||||
"url": "https://crazymax.dev"
|
||||
}
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"@actions/tool-cache": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.0",
|
||||
"@typescript-eslint/parser": "^5.40.0",
|
||||
"@vercel/ncc": "^0.34.0",
|
||||
"eslint": "^8.25.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-jest": "^27.1.2",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "^29.2.0",
|
||||
"prettier": "^2.7.1",
|
||||
"ts-jest": "^29.0.3",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
import fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
let _tmpDir: string;
|
||||
|
||||
export function tmpDir(): string {
|
||||
if (!_tmpDir) {
|
||||
_tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dagger-')).split(path.sep).join(path.posix.sep);
|
||||
}
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
export interface Inputs {
|
||||
version: string;
|
||||
workdir: string;
|
||||
args: string;
|
||||
installOnly: boolean;
|
||||
cleanup: boolean;
|
||||
cmds: string[];
|
||||
}
|
||||
|
||||
export async function getInputs(): Promise<Inputs> {
|
||||
return {
|
||||
version: core.getInput('version') || '0.2.232',
|
||||
workdir: core.getInput('workdir') || '.',
|
||||
args: core.getInput('args'),
|
||||
installOnly: core.getBooleanInput('install-only'),
|
||||
cleanup: core.getBooleanInput('cleanup'),
|
||||
cmds: await getInputList('cmds')
|
||||
};
|
||||
}
|
||||
|
||||
export async function getInputList(name: string, ignoreComma?: boolean): Promise<string[]> {
|
||||
const items = core.getInput(name);
|
||||
if (items == '') {
|
||||
return [];
|
||||
}
|
||||
return items
|
||||
.split(/\r?\n/)
|
||||
.filter(x => x)
|
||||
.reduce<string[]>((acc, line) => acc.concat(!ignoreComma ? line.split(',').filter(x => x) : line).map(pat => pat.trim()), []);
|
||||
}
|
||||
|
||||
export const asyncForEach = async (array, callback) => {
|
||||
for (const index in array) {
|
||||
await callback(array[index], index, array);
|
||||
}
|
||||
};
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import * as context from './context';
|
||||
import * as git from './git';
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as http from '@actions/http-client';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
||||
const s3URL = 'https://dl.dagger.io/dagger-cue';
|
||||
const osPlat: string = os.platform();
|
||||
const osArch: string = os.arch();
|
||||
|
||||
export async function build(inputBuildRef: string): Promise<string> {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [repo, ref] = inputBuildRef.split('#');
|
||||
if (ref.length == 0) {
|
||||
ref = 'main';
|
||||
}
|
||||
|
||||
const sha = await git.getRemoteSha(repo, ref);
|
||||
core.debug(`Remote ref ${sha} found`);
|
||||
|
||||
let toolPath: string;
|
||||
toolPath = tc.find('dagger-cue', sha);
|
||||
if (!toolPath) {
|
||||
const outFolder = path.join(context.tmpDir(), 'out').split(path.sep).join(path.posix.sep);
|
||||
toolPath = await exec
|
||||
.getExecOutput('docker', ['buildx', 'build', '--build-arg', 'BUILDKIT_CONTEXT_KEEP_GIT_DIR=1', '--output', `type=local,dest=${outFolder}`, inputBuildRef], {
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.warning(res.stderr.trim());
|
||||
}
|
||||
return tc.cacheFile(`${outFolder}/bin/dagger-cue`, osPlat == 'win32' ? 'dagger-cue.exe' : 'dagger-cue', 'dagger-cue', sha);
|
||||
});
|
||||
}
|
||||
|
||||
return path.join(toolPath, osPlat == 'win32' ? 'dagger-cue.exe' : 'dagger-cue');
|
||||
}
|
||||
|
||||
export async function install(version: string): Promise<string> {
|
||||
version = await getVersionMapping(version);
|
||||
version = version.replace(/^v/, '');
|
||||
|
||||
const downloadUrl: string = util.format('%s/releases/%s/%s', s3URL, version, getFilename(version));
|
||||
core.info(`Downloading ${downloadUrl}`);
|
||||
const downloadPath: string = await tc.downloadTool(downloadUrl);
|
||||
core.debug(`Downloaded to ${downloadPath}`);
|
||||
|
||||
core.info('Extracting Dagger');
|
||||
let extPath: string;
|
||||
if (osPlat == 'win32') {
|
||||
extPath = await tc.extractZip(downloadPath);
|
||||
} else {
|
||||
extPath = await tc.extractTar(downloadPath);
|
||||
}
|
||||
core.debug(`Extracted to ${extPath}`);
|
||||
|
||||
const cachePath: string = await tc.cacheDir(extPath, 'dagger-cue', version);
|
||||
core.debug(`Cached to ${cachePath}`);
|
||||
|
||||
const exePath: string = path.join(cachePath, osPlat == 'win32' ? 'dagger-cue.exe' : 'dagger-cue');
|
||||
core.debug(`Exe path is ${exePath}`);
|
||||
|
||||
return path.join(cachePath, osPlat == 'win32' ? 'dagger-cue.exe' : 'dagger-cue');
|
||||
}
|
||||
|
||||
async function getVersionMapping(version: string): Promise<string> {
|
||||
const _http = new http.HttpClient('dagger-for-github');
|
||||
const res = await _http.get(`${s3URL}/versions/${version}`);
|
||||
if (res.message.statusCode != 200) {
|
||||
return version;
|
||||
}
|
||||
|
||||
return await res.readBody().then(body => {
|
||||
return body.trim();
|
||||
});
|
||||
}
|
||||
|
||||
const getFilename = (version: string): string => {
|
||||
const platform: string = osPlat == 'win32' ? 'windows' : osPlat;
|
||||
const arch: string = osArch == 'x64' ? 'amd64' : osArch;
|
||||
const ext: string = osPlat == 'win32' ? '.zip' : '.tar.gz';
|
||||
return util.format('dagger-cue_v%s_%s_%s%s', version, platform, arch, ext);
|
||||
};
|
||||
19
src/git.ts
19
src/git.ts
|
|
@ -1,19 +0,0 @@
|
|||
import * as exec from '@actions/exec';
|
||||
|
||||
export async function getRemoteSha(repo: string, ref: string): Promise<string> {
|
||||
return await exec
|
||||
.getExecOutput(`git`, ['ls-remote', repo, ref], {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr);
|
||||
}
|
||||
const [rsha] = res.stdout.trim().split(/[\s\t]/);
|
||||
if (rsha.length == 0) {
|
||||
throw new Error(`Cannot find remote ref for ${repo}#${ref}`);
|
||||
}
|
||||
return rsha;
|
||||
});
|
||||
}
|
||||
77
src/main.ts
77
src/main.ts
|
|
@ -1,77 +0,0 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import * as context from './context';
|
||||
import * as dagger from './dagger';
|
||||
import * as stateHelper from './state-helper';
|
||||
import * as util from './util';
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
const inputs: context.Inputs = await context.getInputs();
|
||||
|
||||
let daggerBin;
|
||||
if (util.isValidUrl(inputs.version)) {
|
||||
core.startGroup(`Build and install Dagger`);
|
||||
daggerBin = await dagger.build(inputs.version);
|
||||
core.endGroup();
|
||||
} else {
|
||||
core.startGroup(`Download and install Dagger`);
|
||||
daggerBin = await dagger.install(inputs.version);
|
||||
core.endGroup();
|
||||
}
|
||||
|
||||
if (inputs.installOnly) {
|
||||
const daggerDir = path.dirname(daggerBin);
|
||||
core.addPath(daggerDir);
|
||||
core.debug(`Added ${daggerDir} to PATH`);
|
||||
return;
|
||||
} else if (!inputs.args && !inputs.cmds.length) {
|
||||
throw new Error(`you need to provide either 'args' or 'cmds'`);
|
||||
}
|
||||
|
||||
if (inputs.workdir && inputs.workdir !== '.') {
|
||||
core.debug(`Using ${inputs.workdir} as working directory`);
|
||||
process.chdir(inputs.workdir);
|
||||
}
|
||||
|
||||
stateHelper.setCleanup(inputs.cleanup);
|
||||
|
||||
if (inputs.args) {
|
||||
inputs.cmds.unshift(inputs.args);
|
||||
}
|
||||
|
||||
for (const cmd of inputs.cmds) {
|
||||
await core.group(cmd, async () => {
|
||||
await exec.exec(`${daggerBin} ${cmd}`, undefined, {
|
||||
env: Object.assign({}, process.env, {
|
||||
DAGGER_LOG_FORMAT: 'plain'
|
||||
}) as {
|
||||
[key: string]: string;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanup(): Promise<void> {
|
||||
if (!stateHelper.cleanup) {
|
||||
return;
|
||||
}
|
||||
const daggerHome = path.join(os.homedir(), '.config', 'dagger');
|
||||
if (fs.existsSync(daggerHome)) {
|
||||
core.info(`Removing ${daggerHome}`);
|
||||
fs.rmSync(daggerHome, {recursive: true});
|
||||
}
|
||||
}
|
||||
|
||||
if (!stateHelper.IsPost) {
|
||||
run();
|
||||
} else {
|
||||
cleanup();
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import * as core from '@actions/core';
|
||||
|
||||
export const IsPost = !!process.env['STATE_isPost'];
|
||||
export const cleanup = /true/i.test(process.env['STATE_cleanup'] || '');
|
||||
|
||||
export function setCleanup(cleanup: boolean) {
|
||||
core.saveState('cleanup', cleanup);
|
||||
}
|
||||
|
||||
if (!IsPost) {
|
||||
core.saveState('isPost', 'true');
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
export function isValidUrl(url: string): boolean {
|
||||
try {
|
||||
new URL(url);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
```console
|
||||
dagger init
|
||||
cp ~/.config/dagger/keys.txt .
|
||||
dagger new ci -p ./ci
|
||||
mkdir -p ./ci
|
||||
dagger query
|
||||
dagger up --no-cache --log-format plain
|
||||
```
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
|
||||
"universe.dagger.io/alpine"
|
||||
"universe.dagger.io/bash"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
actions: test: {
|
||||
image: alpine.#Build & {
|
||||
packages: bash: {}
|
||||
}
|
||||
|
||||
bash.#Run & {
|
||||
input: image.output
|
||||
script: contents: "echo Hello World!"
|
||||
}
|
||||
}
|
||||
}
|
||||
1
test/cue.mod/.gitattributes
vendored
1
test/cue.mod/.gitattributes
vendored
|
|
@ -1 +0,0 @@
|
|||
pkg/** linguist-generated=true
|
||||
|
|
@ -1 +0,0 @@
|
|||
module: ""
|
||||
|
|
@ -1 +0,0 @@
|
|||
module: "dagger.io"
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
package dagger
|
||||
|
||||
// Execute a command in a container
|
||||
#Exec: {
|
||||
$dagger: task: _name: "Exec"
|
||||
|
||||
// Container filesystem
|
||||
input: #FS
|
||||
|
||||
// Transient filesystem mounts
|
||||
// Key is an arbitrary name, for example "app source code"
|
||||
// Value is mount configuration
|
||||
mounts: [name=string]: #Mount
|
||||
|
||||
// Command to execute
|
||||
// Example: ["echo", "hello, world!"]
|
||||
args: [...string]
|
||||
|
||||
// Environment variables
|
||||
env: [key=string]: string | #Secret
|
||||
|
||||
// Working directory
|
||||
workdir: string | *"/"
|
||||
|
||||
// User ID or name
|
||||
user: string | *"root"
|
||||
|
||||
// If set, always execute even if the operation could be cached
|
||||
always: true | *false
|
||||
|
||||
// Inject hostname resolution into the container
|
||||
// key is hostname, value is IP
|
||||
hosts: [hostname=string]: string
|
||||
|
||||
// Modified filesystem
|
||||
output: #FS
|
||||
|
||||
// Command exit code
|
||||
// Currently this field can only ever be zero.
|
||||
// If the command fails, DAG execution is immediately terminated.
|
||||
// FIXME: expand API to allow custom handling of failed commands
|
||||
exit: int & 0
|
||||
}
|
||||
|
||||
// A transient filesystem mount.
|
||||
#Mount: {
|
||||
dest: string
|
||||
type: string
|
||||
{
|
||||
type: "cache"
|
||||
contents: #CacheDir
|
||||
} | {
|
||||
type: "tmp"
|
||||
contents: #TempDir
|
||||
} | {
|
||||
type: "service"
|
||||
contents: #Service
|
||||
} | {
|
||||
type: "fs"
|
||||
contents: #FS
|
||||
source?: string
|
||||
ro?: true | *false
|
||||
} | {
|
||||
type: "secret"
|
||||
contents: #Secret
|
||||
uid: int | *0
|
||||
gid: int | *0
|
||||
mask: int | *0o400
|
||||
}
|
||||
}
|
||||
|
||||
// A (best effort) persistent cache dir
|
||||
#CacheDir: {
|
||||
id: string
|
||||
concurrency: *"shared" | "private" | "locked"
|
||||
}
|
||||
|
||||
// A temporary directory for command execution
|
||||
#TempDir: {
|
||||
size: int64 | *0
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
package dagger
|
||||
|
||||
// Access the source directory for the current CUE package
|
||||
// This may safely be called from any package
|
||||
#Source: {
|
||||
$dagger: task: _name: "Source"
|
||||
|
||||
// Relative path to source.
|
||||
path: string
|
||||
// Optionally exclude certain files
|
||||
include: [...string]
|
||||
// Optionally include certain files
|
||||
exclude: [...string]
|
||||
|
||||
output: #FS
|
||||
}
|
||||
|
||||
// Create one or multiple directory in a container
|
||||
#Mkdir: {
|
||||
$dagger: task: _name: "Mkdir"
|
||||
|
||||
// Container filesystem
|
||||
input: #FS
|
||||
|
||||
// Path of the directory to create
|
||||
// It can be nested (e.g : "/foo" or "/foo/bar")
|
||||
path: string
|
||||
|
||||
// Permissions of the directory
|
||||
permissions: *0o755 | int
|
||||
|
||||
// If set, it creates parents' directory if they do not exist
|
||||
parents: *true | false
|
||||
|
||||
// Modified filesystem
|
||||
output: #FS
|
||||
}
|
||||
|
||||
#ReadFile: {
|
||||
$dagger: task: _name: "ReadFile"
|
||||
|
||||
// Filesystem tree holding the file
|
||||
input: #FS
|
||||
// Path of the file to read
|
||||
path: string
|
||||
// Contents of the file
|
||||
contents: string
|
||||
}
|
||||
|
||||
// Write a file to a filesystem tree, creating it if needed
|
||||
#WriteFile: {
|
||||
$dagger: task: _name: "WriteFile"
|
||||
|
||||
// Input filesystem tree
|
||||
input: #FS
|
||||
// Path of the file to write
|
||||
path: string
|
||||
// Contents to write
|
||||
contents: string
|
||||
// Permissions of the file
|
||||
permissions: *0o600 | int
|
||||
// Output filesystem tree
|
||||
output: #FS
|
||||
}
|
||||
|
||||
// Copy files from one FS tree to another
|
||||
#Copy: {
|
||||
$dagger: task: _name: "Copy"
|
||||
// Input of the operation
|
||||
input: #FS
|
||||
// Contents to copy
|
||||
contents: #FS
|
||||
// Source path (optional)
|
||||
source: string | *"/"
|
||||
// Destination path (optional)
|
||||
dest: string | *"/"
|
||||
// Output of the operation
|
||||
output: #FS
|
||||
}
|
||||
|
||||
#CopyInfo: {
|
||||
source: {
|
||||
root: #FS
|
||||
path: string | *"/"
|
||||
}
|
||||
dest: string
|
||||
}
|
||||
|
||||
// Merge multiple FS trees into one
|
||||
#Merge: {
|
||||
@dagger(notimplemented)
|
||||
$dagger: task: _name: "Merge"
|
||||
|
||||
input: #FS
|
||||
layers: [...#CopyInfo]
|
||||
output: #FS
|
||||
}
|
||||
|
||||
// Select a subdirectory from a filesystem tree
|
||||
#Subdir: {
|
||||
// Input tree
|
||||
input: #FS
|
||||
|
||||
// Path of the subdirectory
|
||||
// Example: "/build"
|
||||
path: string
|
||||
|
||||
// Copy action
|
||||
_copy: #Copy & {
|
||||
"input": #Scratch
|
||||
contents: input
|
||||
source: path
|
||||
dest: "/"
|
||||
}
|
||||
|
||||
// Subdirectory tree
|
||||
output: #FS & _copy.output
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package dagger
|
||||
|
||||
// Push a directory to a git remote
|
||||
#GitPush: {
|
||||
@dagger(notimplemented)
|
||||
$dagger: task: _name: "GitPush"
|
||||
|
||||
input: #FS
|
||||
remote: string
|
||||
ref: string
|
||||
}
|
||||
|
||||
// Pull a directory from a git remote
|
||||
// Warning: do NOT embed credentials in the remote url as this will expose them in logs.
|
||||
// By using username and password Dagger will handle this for you in a secure manner.
|
||||
#GitPull: {
|
||||
$dagger: task: _name: "GitPull"
|
||||
remote: string
|
||||
ref: string
|
||||
keepGitDir: true | *false
|
||||
auth?: {
|
||||
username: string
|
||||
password: #Secret // can be password or personal access token
|
||||
} | {
|
||||
authToken: #Secret
|
||||
} | {
|
||||
authHeader: #Secret
|
||||
}
|
||||
output: #FS
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
package dagger
|
||||
|
||||
// HTTP operations
|
||||
|
||||
// Raw buildkit API
|
||||
//
|
||||
// package llb // import "github.com/moby/buildkit/client/llb"
|
||||
//
|
||||
// func HTTP(url string, opts ...HTTPOption) State
|
||||
//
|
||||
// type HTTPOption interface {
|
||||
// SetHTTPOption(*HTTPInfo)
|
||||
// }
|
||||
// func Checksum(dgst digest.Digest) HTTPOption
|
||||
// func Chmod(perm os.FileMode) HTTPOption
|
||||
// func Chown(uid, gid int) HTTPOption
|
||||
// func Filename(name string) HTTPOption
|
||||
|
||||
// Fetch a file over HTTP
|
||||
#HTTPFetch: {
|
||||
$dagger: task: _name: "HTTPFetch"
|
||||
|
||||
// Source url
|
||||
// Example: https://www.dagger.io/index.html
|
||||
source: string
|
||||
|
||||
// Destination path of the downloaded file
|
||||
// Example: "/downloads/index.html"
|
||||
dest: string
|
||||
|
||||
// Optionally verify the file checksum
|
||||
// FIXME: what is the best format to encode checksum?
|
||||
checksum?: string
|
||||
|
||||
// Optionally set file permissions on the downloaded file
|
||||
// FIXME: find a more developer-friendly way to input file permissions
|
||||
permissions?: int
|
||||
|
||||
// Optionally set UID of the downloaded file
|
||||
uid?: int
|
||||
|
||||
// Optionally set GID of the downloaded file
|
||||
gid?: int
|
||||
|
||||
// New filesystem state containing the downloaded file
|
||||
output: #FS
|
||||
}
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
package dagger
|
||||
|
||||
import (
|
||||
"list"
|
||||
)
|
||||
|
||||
// Upload a container image to a remote repository
|
||||
#Push: {
|
||||
$dagger: task: _name: "Push"
|
||||
|
||||
// Target repository address
|
||||
dest: #Ref
|
||||
|
||||
// Filesystem contents to push
|
||||
input: #FS
|
||||
|
||||
// Container image config
|
||||
config: #ImageConfig
|
||||
|
||||
// Authentication
|
||||
auth?: {
|
||||
username: string
|
||||
secret: #Secret
|
||||
}
|
||||
|
||||
// Complete ref of the pushed image, including digest
|
||||
result: #Ref
|
||||
}
|
||||
|
||||
// A ref is an address for a remote container image
|
||||
//
|
||||
// Examples:
|
||||
// - "index.docker.io/dagger"
|
||||
// - "dagger"
|
||||
// - "index.docker.io/dagger:latest"
|
||||
// - "index.docker.io/dagger:latest@sha256:a89cb097693dd354de598d279c304a1c73ee550fbfff6d9ee515568e0c749cfe"
|
||||
#Ref: string
|
||||
|
||||
// Container image config. See [OCI](https://www.opencontainers.org/).
|
||||
#ImageConfig: {
|
||||
user?: string
|
||||
expose?: [string]: {}
|
||||
env?: [string]: string
|
||||
entrypoint?: [...string]
|
||||
cmd?: [...string]
|
||||
volume?: [string]: {}
|
||||
workdir?: string
|
||||
label?: [string]: string
|
||||
stopsignal?: string
|
||||
healthcheck?: #HealthCheck
|
||||
argsescaped?: bool
|
||||
onbuild?: [...string]
|
||||
stoptimeout?: int
|
||||
shell?: [...string]
|
||||
}
|
||||
|
||||
#HealthCheck: {
|
||||
test?: [...string]
|
||||
interval?: int
|
||||
timeout?: int
|
||||
startperiod?: int
|
||||
retries?: int
|
||||
}
|
||||
|
||||
// Download a container image from a remote repository
|
||||
#Pull: {
|
||||
$dagger: task: _name: "Pull"
|
||||
|
||||
// Repository source ref
|
||||
source: #Ref
|
||||
|
||||
// Authentication
|
||||
auth?: {
|
||||
username: string
|
||||
secret: #Secret
|
||||
}
|
||||
|
||||
// Root filesystem of downloaded image
|
||||
output: #FS
|
||||
|
||||
// Image digest
|
||||
digest: string
|
||||
|
||||
// Downloaded container image config
|
||||
config: #ImageConfig
|
||||
}
|
||||
|
||||
// Build a container image using a Dockerfile
|
||||
#Dockerfile: {
|
||||
$dagger: task: _name: "Dockerfile"
|
||||
|
||||
// Source directory to build
|
||||
source: #FS
|
||||
|
||||
dockerfile: *{
|
||||
path: string | *"Dockerfile"
|
||||
} | {
|
||||
contents: string
|
||||
}
|
||||
|
||||
// Authentication
|
||||
auth: [registry=string]: {
|
||||
username: string
|
||||
secret: #Secret
|
||||
}
|
||||
|
||||
platforms?: [...string]
|
||||
target?: string
|
||||
buildArg?: [string]: string
|
||||
label?: [string]: string
|
||||
hosts?: [string]: string
|
||||
|
||||
// Root filesystem produced
|
||||
output: #FS
|
||||
|
||||
// Container image config produced
|
||||
config: #ImageConfig
|
||||
}
|
||||
|
||||
// Change image config
|
||||
#Set: {
|
||||
// The source image config
|
||||
input: #ImageConfig
|
||||
|
||||
// The config to merge
|
||||
config: #ImageConfig
|
||||
|
||||
// Resulting config
|
||||
output: #ImageConfig & {
|
||||
let structs = ["env", "label", "volume", "expose"]
|
||||
let lists = ["onbuild"]
|
||||
|
||||
// doesn't exist in config, copy away
|
||||
for field, value in input if config[field] == _|_ {
|
||||
"\(field)": value
|
||||
}
|
||||
|
||||
// only exists in config, just copy as is
|
||||
for field, value in config if input[field] == _|_ {
|
||||
"\(field)": value
|
||||
}
|
||||
|
||||
// these should exist in both places
|
||||
for field, value in config if input[field] != _|_ {
|
||||
"\(field)": {
|
||||
// handle structs that need merging
|
||||
if list.Contains(structs, field) {
|
||||
_#mergeStructs & {
|
||||
#a: input[field]
|
||||
#b: config[field]
|
||||
}
|
||||
}
|
||||
|
||||
// handle lists that need concatenation
|
||||
if list.Contains(lists, field) {
|
||||
list.Concat([
|
||||
input[field],
|
||||
config[field],
|
||||
])
|
||||
}
|
||||
|
||||
// replace anything else
|
||||
if !list.Contains(structs+lists, field) {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge two structs by overwriting or adding values
|
||||
_#mergeStructs: {
|
||||
// Struct with defaults
|
||||
#a: [string]: _
|
||||
|
||||
// Struct with overrides
|
||||
#b: [string]: _
|
||||
{
|
||||
// FIXME: we need exists() in if because this matches any kind of error (cue-lang/cue#943)
|
||||
// add anything not in b
|
||||
for field, value in #a if #b[field] == _|_ {
|
||||
"\(field)": value
|
||||
}
|
||||
|
||||
// safely add all of b
|
||||
for field, value in #b {
|
||||
"\(field)": value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
package dagger
|
||||
|
||||
// A special kind of program which `dagger` can execute.
|
||||
#Plan: {
|
||||
// Access client machine
|
||||
client: {
|
||||
// Access client filesystem
|
||||
// Path may be absolute, or relative to client working directory
|
||||
filesystem: [path=string]: {
|
||||
// Read data from that path
|
||||
read?: _#clientFilesystemRead & {
|
||||
"path": path
|
||||
}
|
||||
|
||||
// If set, Write to that path
|
||||
write?: _#clientFilesystemWrite & {
|
||||
"path": path
|
||||
|
||||
// avoid race condition
|
||||
if read != _|_ {
|
||||
_after: read
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Access client environment variables
|
||||
env: [string]: *string | #Secret
|
||||
|
||||
// Execute commands in the client
|
||||
commands: [id=string]: _#clientCommand
|
||||
|
||||
// Platform of the client machine
|
||||
platform: _#clientPlatform
|
||||
}
|
||||
|
||||
// Configure platform execution
|
||||
platform?: string
|
||||
|
||||
// Execute actions in containers
|
||||
actions: {
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
_#clientFilesystemRead: {
|
||||
$dagger: task: _name: "ClientFilesystemRead"
|
||||
|
||||
// Path may be absolute, or relative to client working directory
|
||||
path: string
|
||||
|
||||
{
|
||||
// CUE type defines expected content:
|
||||
// string: contents of a regular file
|
||||
// #Secret: secure reference to the file contents
|
||||
contents: string | #Secret
|
||||
} | {
|
||||
// CUE type defines expected content:
|
||||
// #FS: contents of a directory
|
||||
contents: #FS
|
||||
|
||||
// Filename patterns to include
|
||||
// Example: ["*.go", "Dockerfile"]
|
||||
include?: [...string]
|
||||
|
||||
// Filename patterns to exclude
|
||||
// Example: ["node_modules"]
|
||||
exclude?: [...string]
|
||||
} | {
|
||||
// CUE type defines expected content:
|
||||
// #Service: unix socket or npipe
|
||||
contents: #Service
|
||||
|
||||
// Type of service
|
||||
type: *"unix" | "npipe"
|
||||
}
|
||||
}
|
||||
|
||||
_#clientFilesystemWrite: {
|
||||
$dagger: task: _name: "ClientFilesystemWrite"
|
||||
|
||||
// Path may be absolute, or relative to client working directory
|
||||
path: string
|
||||
{
|
||||
// File contents to export (as a string or secret)
|
||||
contents: string | #Secret
|
||||
|
||||
// File permissions (defaults to 0o644)
|
||||
permissions?: int
|
||||
} | {
|
||||
// Filesystem contents to export
|
||||
// Reference an #FS field produced by an action
|
||||
contents: #FS
|
||||
}
|
||||
}
|
||||
|
||||
_#clientCommand: {
|
||||
$dagger: task: _name: "ClientCommand"
|
||||
|
||||
// Name of the command to execute
|
||||
// Examples: "ls", "/bin/bash"
|
||||
name: string
|
||||
|
||||
// Positional arguments to the command
|
||||
// Examples: ["/tmp"]
|
||||
args: [...string]
|
||||
|
||||
// Command-line flags represented in a civilized form
|
||||
// Example: {"-l": true, "-c": "echo hello world"}
|
||||
flags: [string]: bool | string
|
||||
|
||||
// Environment variables
|
||||
// Example: {"DEBUG": "1"}
|
||||
env: [string]: string | #Secret
|
||||
|
||||
// Capture standard output (as a string or secret)
|
||||
stdout?: *string | #Secret
|
||||
|
||||
// Capture standard error (as a string or secret)
|
||||
stderr?: *string | #Secret
|
||||
|
||||
// Inject standard input (from a string or secret)
|
||||
stdin?: string | #Secret
|
||||
}
|
||||
|
||||
_#clientPlatform: {
|
||||
$dagger: task: _name: "ClientPlatform"
|
||||
|
||||
// Operating system of the client machine
|
||||
os: string
|
||||
// Hardware architecture of the client machine
|
||||
arch: string
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
package dagger
|
||||
|
||||
// Decode the contents of a secrets without leaking it.
|
||||
// Supported formats: json, yaml
|
||||
#DecodeSecret: {
|
||||
$dagger: task: _name: "DecodeSecret"
|
||||
|
||||
// A #Secret whose plain text is a JSON or YAML string
|
||||
input: #Secret
|
||||
|
||||
format: "json" | "yaml"
|
||||
|
||||
// A new secret or (map of secrets) derived from unmarshaling the input secret's plain text
|
||||
output: #Secret | {[string]: output}
|
||||
}
|
||||
|
||||
// Create a new a secret from a filesystem tree
|
||||
#NewSecret: {
|
||||
$dagger: task: _name: "NewSecret"
|
||||
|
||||
// Filesystem tree holding the secret
|
||||
input: #FS
|
||||
// Path of the secret to read
|
||||
path: string
|
||||
// Whether to trim leading and trailing space characters from secret value
|
||||
trimSpace: *true | false
|
||||
// Contents of the secret
|
||||
output: #Secret
|
||||
}
|
||||
|
||||
// Trim leading and trailing space characters from a secret
|
||||
#TrimSecret: {
|
||||
$dagger: task: _name: "TrimSecret"
|
||||
|
||||
// Original secret
|
||||
input: #Secret
|
||||
|
||||
// New trimmed secret
|
||||
output: #Secret
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
package dagger
|
||||
|
||||
// A reference to a filesystem tree.
|
||||
// For example:
|
||||
// - The root filesystem of a container
|
||||
// - A source code repository
|
||||
// - A directory containing binary artifacts
|
||||
// Rule of thumb: if it fits in a tar archive, it fits in a #FS.
|
||||
#FS: {
|
||||
$dagger: fs: _id: string | null
|
||||
}
|
||||
|
||||
// An empty directory
|
||||
#Scratch: #FS & {
|
||||
$dagger: fs: _id: null
|
||||
}
|
||||
|
||||
// A reference to an external secret, for example:
|
||||
// - A password
|
||||
// - A SSH private key
|
||||
// - An API token
|
||||
// Secrets are never merged in the Cue tree. They can only be used
|
||||
// by a special filesystem mount designed to minimize leak risk.
|
||||
#Secret: {
|
||||
$dagger: secret: _id: string
|
||||
}
|
||||
|
||||
// A reference to a network service endpoint, for example:
|
||||
// - A TCP or UDP port
|
||||
// - A unix socket
|
||||
// - An HTTPS endpoint
|
||||
#Service: {
|
||||
$dagger: service: _id: string
|
||||
}
|
||||
|
||||
// A network service address
|
||||
#Address: string & =~"^(tcp://|unix://|udp://).*"
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
# Europa Universe
|
||||
|
||||
## About this directory
|
||||
|
||||
`europa-universe/` is a staging area for the upcoming `universe.dagger.io` package namespace,
|
||||
which will be shipped as part of the [Europa release](https://github.com/dagger/dagger/issues/1088).
|
||||
|
||||
## What is Universe?
|
||||
|
||||
The Dagger Universe is a catalog of reusable Cue packages, curated by Dagger but possibly authored by third parties. Most packages in Universe contain reusable actions; some may also contain entire configuration templates.
|
||||
|
||||
The import domain for Universe will be `universe.dagger.io`. It will deprecate the current domain `alpha.dagger.io`.
|
||||
|
||||
## Where is the `dagger` package?
|
||||
|
||||
Europa will also introduce a new package for the Dagger Core API: `dagger.io/dagger`.
|
||||
This is a core package, and is *not* part of Universe (note the import domain).
|
||||
|
||||
The development version of the Europa core API can be imported as [alpha.dagger.io/europa/dagger](../stdlib/europa/dagger).
|
||||
|
||||
## Where is the `dagger/engine` package?
|
||||
|
||||
Europa will also introduce a new package for the Low-Level Dagger Engine API : `dagger.io/dagger/engine`.
|
||||
This is a core package, and is *not* part of Universe (note the import domain).
|
||||
|
||||
The development version of the Europa Low-Level Engine API can be imported as either:
|
||||
|
||||
* [alpha.dagger.io/europa/dagger/engine/spec/engine](../stdlib/europa/dagger/engine/spec/engine) for the full spec
|
||||
* [alpha.dagger.io/dagger/europa/engine](../stdlib/europa/dagger/engine) for the implemented subset of the spec
|
||||
|
||||
## Universe vs other packages
|
||||
|
||||
This table compares Dagger core packages, Dagger Universe packages, and the overall CUE package ecosystem.
|
||||
|
||||
| | *Dagger core* | *Dagger Universe* | *CUE ecosystem* |
|
||||
|---|----------------|-------------------|-----------------|
|
||||
| Import path | `dagger.io` | `universe.dagger.io` | Everything else |
|
||||
| Purpose | Access core Dagger features | Safely reuse code from the Dagger community | Reuse any CUE code from anyone |
|
||||
| Author | Dagger team | Dagger community, curated by Dagger | Anyone |
|
||||
| Release cycle | Released with Dagger engine | Released continuously | No release cycle |
|
||||
| Size | Small | Large | Very large |
|
||||
| Growth rate | Grows slowly, with engine features | Grows fast, with Dagger community | Grows even faster, with CUE ecosystem |
|
||||
|
||||
|
||||
## Notable packages
|
||||
|
||||
### Docker API
|
||||
|
||||
*Import path: [`universe.dagger.io/docker`](./universe/docker)*
|
||||
|
||||
The `docker` package is a native Cue API for Docker. You can use it to build, run, push and pull Docker containers directly from Cue.
|
||||
|
||||
The Dagger container API defines the following types:
|
||||
|
||||
* `#Image`: a container image
|
||||
* `#Run`: run a command in a container
|
||||
* `#Push`: upload an image to a repository
|
||||
* `#Pull`: download an image from a repository
|
||||
* `#Build`: build an image
|
||||
|
||||
### Examples
|
||||
|
||||
*Import path: [`universe.dagger.io/examples`](./examples)*
|
||||
|
||||
This package contains examples of complete Dagger configurations, including the result of following tutorials in the documentations.
|
||||
|
||||
For example, [the todoapp example](./examples/todoapp) corresponds to the [Getting Started tutorial](https://docs.dagger.io/1003/get-started/)
|
||||
|
||||
|
||||
## TODO LIST
|
||||
|
||||
* Support native language dev in `docker.#Run` with good DX (Python, Go, Typescript etc.)
|
||||
* Coding style. When to use verbs vs. nouns?
|
||||
* Easy file injection API (`container.#Image.files` ?)
|
||||
* Use file injection instead of inline for `#Command.script` (to avoid hitting arg character limits)
|
||||
* Organize universe packages in sub-categories?
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
// Base package for Alpine Linux
|
||||
package alpine
|
||||
|
||||
import (
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
// Build an Alpine Linux container image
|
||||
#Build: {
|
||||
|
||||
// Alpine version to install.
|
||||
version: string | *"3.15.0@sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300"
|
||||
|
||||
// List of packages to install
|
||||
packages: [pkgName=string]: {
|
||||
// NOTE(samalba, gh issue #1532):
|
||||
// it's not recommended to pin the version as it is already pinned by the major Alpine version
|
||||
// version pinning is for future use (as soon as we support custom repositories like `community`,
|
||||
// `testing` or `edge`)
|
||||
version: string | *""
|
||||
}
|
||||
|
||||
docker.#Build & {
|
||||
steps: [
|
||||
docker.#Pull & {
|
||||
source: "index.docker.io/alpine:\(version)"
|
||||
},
|
||||
for pkgName, pkg in packages {
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "apk"
|
||||
args: ["add", "\(pkgName)\(pkg.version)"]
|
||||
flags: {
|
||||
"-U": true
|
||||
"--no-cache": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
setup() {
|
||||
load '../../bats_helpers'
|
||||
|
||||
common_setup
|
||||
}
|
||||
@test "alpine" {
|
||||
dagger up
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
package alpine
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
|
||||
"universe.dagger.io/alpine"
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
actions: tests: {
|
||||
// Test: customize alpine version
|
||||
alpineVersion: {
|
||||
build: alpine.#Build & {
|
||||
// install an old version on purpose
|
||||
version: "3.10.9"
|
||||
}
|
||||
|
||||
verify: dagger.#Readfile & {
|
||||
input: build.output.rootfs
|
||||
path: "/etc/alpine-release"
|
||||
contents: "3.10.9\n"
|
||||
}
|
||||
}
|
||||
|
||||
// Test: install packages
|
||||
packageInstall: {
|
||||
build: alpine.#Build & {
|
||||
packages: {
|
||||
jq: {}
|
||||
curl: {}
|
||||
}
|
||||
}
|
||||
|
||||
check: docker.#Run & {
|
||||
input: build.output
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": """
|
||||
jq --version > /jq-version.txt
|
||||
curl --version > /curl-version.txt
|
||||
"""
|
||||
}
|
||||
|
||||
export: files: {
|
||||
"/jq-version.txt": contents: =~"^jq"
|
||||
"/curl-version.txt": contents: =~"^curl"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
// AWS base package
|
||||
package aws
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
#DefaultLinuxVersion: "amazonlinux:2.0.20220121.0@sha256:f3a37f84f2644095e2c6f6fdf2bf4dbf68d5436c51afcfbfa747a5de391d5d62"
|
||||
#DefaultCliVersion: "2.4.12"
|
||||
|
||||
// Build provides a docker.#Image with the aws cli pre-installed to Amazon Linux 2.
|
||||
// Can be customized with packages, and can be used with docker.#Run for executing custom scripts.
|
||||
// Used by default with aws.#Run
|
||||
#Build: {
|
||||
|
||||
docker.#Build & {
|
||||
steps: [
|
||||
docker.#Pull & {
|
||||
source: #DefaultLinuxVersion
|
||||
},
|
||||
// cache yum install separately
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "yum"
|
||||
args: ["install", "unzip", "-y"]
|
||||
}
|
||||
},
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "/scripts/install.sh"
|
||||
args: [version]
|
||||
}
|
||||
mounts: scripts: {
|
||||
dest: "/scripts"
|
||||
contents: _scripts.output
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
_scripts: dagger.#Source & {
|
||||
path: "_scripts"
|
||||
}
|
||||
|
||||
// The version of the AWS CLI to install
|
||||
version: string | *#DefaultCliVersion
|
||||
}
|
||||
|
||||
// Credentials provides long or short-term credentials.
|
||||
#Credentials: {
|
||||
// AWS access key
|
||||
accessKeyId?: dagger.#Secret
|
||||
|
||||
// AWS secret key
|
||||
secretAccessKey?: dagger.#Secret
|
||||
|
||||
// AWS session token (provided with temporary credentials)
|
||||
sessionToken?: dagger.#Secret
|
||||
}
|
||||
|
||||
// Region provides a schema to validate acceptable region value.
|
||||
#Region: "us-east-2" | "us-east-1" | "us-west-1" | "us-west-2" | "af-south-1" | "ap-east-1" | "ap-southeast-3" | "ap-south-1" | "ap-northeast-3" | "ap-northeast-2" | "ap-southeast-1" | "ap-southeast-2" | "ap-northeast-1" | "ca-central-1" | "cn-north-1" | "cn-northwest-1" | "eu-central-1" | "eu-west-1" | "eu-west-2" | "eu-south-1" | "eu-west-3" | "eu-north-1" | "me-south-1" | "sa-east-1"
|
||||
|
||||
// Container a standalone environment pre-configured with credentials and .aws/config
|
||||
#Container: {
|
||||
// _build provides the default image
|
||||
_build: #Build
|
||||
|
||||
// configFile provides access to a config file, typically found in ~/.aws/config
|
||||
configFile?: dagger.#FS
|
||||
|
||||
// credentials provides long or short-term credentials
|
||||
credentials: #Credentials
|
||||
|
||||
docker.#Run & {
|
||||
input: docker.#Image | *_build.output
|
||||
|
||||
env: {
|
||||
// pass credentials as env vars
|
||||
if credentials.accessKeyId != _|_ {
|
||||
AWS_ACCESS_KEY_ID: credentials.accessKeyId
|
||||
}
|
||||
|
||||
if credentials.secretAccessKey != _|_ {
|
||||
AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey
|
||||
}
|
||||
|
||||
if credentials.sessionToken != _|_ {
|
||||
AWS_SESSION_TOKEN: credentials.sessionToken
|
||||
}
|
||||
}
|
||||
|
||||
if configFile != _|_ {
|
||||
mounts: aws: {
|
||||
contents: configFile
|
||||
dest: "/aws"
|
||||
ro: true
|
||||
}
|
||||
env: AWS_CONFIG_FILE: "/aws/config"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"list"
|
||||
"strings"
|
||||
"encoding/json"
|
||||
"universe.dagger.io/aws"
|
||||
)
|
||||
|
||||
// Command provides a declarative interface to the AWS CLI
|
||||
#Command: {
|
||||
// "register" output.txt
|
||||
export: files: "/output.txt": _
|
||||
|
||||
// Global arguments passed to the aws cli.
|
||||
options: {
|
||||
// Turn on debug logging.
|
||||
debug?: bool
|
||||
|
||||
// Override command's default URL with the given URL.
|
||||
"endpoint-url"?: string
|
||||
|
||||
// By default, the AWS CLI uses SSL when communicating with AWS services.
|
||||
// For each SSL connection, the AWS CLI will verify SSL certificates. This
|
||||
// option overrides the default behavior of verifying SSL certificates.
|
||||
"no-verify-ssl"?: bool
|
||||
|
||||
// Disable automatic pagination.
|
||||
"no-paginate"?: bool
|
||||
|
||||
// The formatting style for command output.
|
||||
output: *"json" | "text" | "table" | "yaml" | "yaml-stream"
|
||||
|
||||
// A JMESPath query to use in filtering the response data.
|
||||
query?: string
|
||||
|
||||
// Use a specific profile from your credential file.
|
||||
profile?: string
|
||||
|
||||
// The region to use. Overrides config/env settings.
|
||||
region?: string
|
||||
|
||||
// Display the version of this tool.
|
||||
version?: bool
|
||||
|
||||
// Turn on/off color output.
|
||||
color?: "off" | "on" | "auto"
|
||||
|
||||
// Do not sign requests. Credentials will not be loaded if this argument
|
||||
// is provided.
|
||||
"no-sign-request"?: bool
|
||||
|
||||
// The CA certificate bundle to use when verifying SSL certificates. Over-
|
||||
// rides config/env settings.
|
||||
"ca-bundle"?: string
|
||||
|
||||
// The maximum socket read time in seconds. If the value is set to 0, the
|
||||
// socket read will be blocking and not timeout. The default value is 60
|
||||
// seconds.
|
||||
"cli-read-timeout"?: int
|
||||
|
||||
// The maximum socket connect time in seconds. If the value is set to 0,
|
||||
// the socket connect will be blocking and not timeout. The default value
|
||||
// is 60 seconds.
|
||||
"cli-connect-timeout"?: int
|
||||
|
||||
// The formatting style to be used for binary blobs. The default format is
|
||||
// base64. The base64 format expects binary blobs to be provided as a
|
||||
// base64 encoded string. The raw-in-base64-out format preserves compati-
|
||||
// bility with AWS CLI V1 behavior and binary values must be passed liter-
|
||||
// ally. When providing contents from a file that map to a binary blob
|
||||
// fileb:// will always be treated as binary and use the file contents
|
||||
// directly regardless of the cli-binary-format setting. When using
|
||||
// file:// the file contents will need to properly formatted for the con-
|
||||
// figured cli-binary-format.
|
||||
"cli-binary-format"?: "base64" | "raw-in-base64-out"
|
||||
|
||||
// Disable cli pager for output.
|
||||
"no-cli-pager": true
|
||||
|
||||
// Automatically prompt for CLI input parameters.
|
||||
"cli-auto-prompt"?: bool
|
||||
|
||||
// Disable automatically prompt for CLI input parameters.
|
||||
"no-cli-auto-prompt"?: bool
|
||||
}
|
||||
|
||||
// Result will contain the cli output. If unmarshal is set to false this will be the raw string as provided by the aws cli command. If unmarshal is set to true this will be a map as returned by json.Unmarshal.
|
||||
_unmarshalable: string | number | bool | null | [..._unmarshalable] | {[string]: _unmarshalable}
|
||||
result: _unmarshalable
|
||||
|
||||
if unmarshal != false {
|
||||
options: output: "json"
|
||||
result: json.Unmarshal(export.files["/output.txt"])
|
||||
}
|
||||
|
||||
if unmarshal == false {
|
||||
result: export.files["/output.txt"]
|
||||
}
|
||||
|
||||
// The service to run the command against.
|
||||
service: {
|
||||
args: [...string]
|
||||
name: "accessanalyzer" | "account" | "acm" | "acm-pca" | "alexaforbusiness" | "amp" | "amplify" | "amplifybackend" | "amplifyuibuilder" | "apigateway" | "apigatewaymanagementapi" | "apigatewayv2" | "appconfig" | "appconfigdata" | "appflow" | "appintegrations" | "application-autoscaling" | "application-insights" | "applicationcostprofiler" | "appmesh" | "apprunner" | "appstream" | "appsync" | "athena" | "auditmanager" | "autoscaling" | "autoscaling-plans" | "backup" | "backup-gateway" | "batch" | "braket" | "budgets" | "ce" | "chime" | "chime-sdk-identity" | "chime-sdk-meetings" | "chime-sdk-messaging" | "cli-dev" | "cloud9" | "cloudcontrol" | "clouddirectory" | "cloudformation" | "cloudfront" | "cloudhsm" | "cloudtrail" | "cloudwatch" | "codeartifact" | "codebuild" | "codecommit" | "codeguru-reviewer" | "codeguruprofiler" | "codepipeline" | "codestar" | "codestar-connections" | "codestar-notifications" | "cognito-identity" | "cognito-idp" | "cognito-sync" | "comprehend" | "comprehendmedical" | "compute-optimizer" | "configservice" | "configure" | "connect" | "connect-contact-lens" | "connectparticipant" | "cur" | "customer-profiles" | "databrew" | "dataexchange" | "datapipeline" | "datasync" | "dax" | "ddb" | "deploy" | "detective" | "devicefarm" | "devops-guru" | "directconnect" | "discovery" | "dlm" | "dms" | "docdb" | "drs" | "ds" | "dynamodb" | "dynamodbstreams" | "ebs" | "ec2" | "ec2-instance-connect" | "ecr" | "ecr-public" | "ecs" | "efs" | "eks" | "elastic-inference" | "elasticache" | "elasticbeanstalk" | "elastictranscoder" | "elb" | "elbv2" | "emr" | "emr-containers" | "es" | "events" | "evidently" | "finspace" | "finspace-data" | "firehose" | "fis" | "fms" | "forecast" | "forecastquery" | "frauddetector" | "fsx" | "gamelift" | "glacier" | "globalaccelerator" | "glue" | "grafana" | "greengrass" | "greengrassv2" | "groundstation" | "guardduty" | "health" | "healthlake" | "help" | "history" | "honeycode" | "iam" | "identitystore" | "imagebuilder" | "importexport" | "inspector" | "inspector2" | "iot" | "iot-data" | "iot-jobs-data" | "iot1click-devices" | "iot1click-projects" | "iotanalytics" | "iotdeviceadvisor" | "iotevents" | "iotevents-data" | "iotfleethub" | "iotsecuretunneling" | "iotsitewise" | "iotthingsgraph" | "iottwinmaker" | "iotwireless" | "ivs" | "kafka" | "kafkaconnect" | "kendra" | "kinesis" | "kinesis-video-archived-media" | "kinesis-video-media" | "kinesis-video-signaling" | "kinesisanalytics" | "kinesisanalyticsv2" | "kinesisvideo" | "kms" | "lakeformation" | "lambda" | "lex-models" | "lex-runtime" | "lexv2-models" | "lexv2-runtime" | "license-manager" | "lightsail" | "location" | "logs" | "lookoutequipment" | "lookoutmetrics" | "lookoutvision" | "machinelearning" | "macie" | "macie2" | "managedblockchain" | "marketplace-catalog" | "marketplace-entitlement" | "marketplacecommerceanalytics" | "mediaconnect" | "mediaconvert" | "medialive" | "mediapackage" | "mediapackage-vod" | "mediastore" | "mediastore-data" | "mediatailor" | "memorydb" | "meteringmarketplace" | "mgh" | "mgn" | "migration-hub-refactor-spaces" | "migrationhub-config" | "migrationhubstrategy" | "mobile" | "mq" | "mturk" | "mwaa" | "neptune" | "network-firewall" | "networkmanager" | "nimble" | "opensearch" | "opsworks" | "opsworks-cm" | "organizations" | "outposts" | "panorama" | "personalize" | "personalize-events" | "personalize-runtime" | "pi" | "pinpoint" | "pinpoint-email" | "pinpoint-sms-voice" | "polly" | "pricing" | "proton" | "qldb" | "qldb-session" | "quicksight" | "ram" | "rbin" | "rds" | "rds-data" | "redshift" | "redshift-data" | "rekognition" | "resiliencehub" | "resource-groups" | "resourcegroupstaggingapi" | "robomaker" | "route53" | "route53-recovery-cluster" | "route53-recovery-control-config" | "route53-recovery-readiness" | "route53domains" | "route53resolver" | "rum" | "s3" | "s3api" | "s3control" | "s3outposts" | "sagemaker" | "sagemaker-a2i-runtime" | "sagemaker-edge" | "sagemaker-featurestore-runtime" | "sagemaker-runtime" | "savingsplans" | "schemas" | "sdb" | "secretsmanager" | "securityhub" | "serverlessrepo" | "service-quotas" | "servicecatalog" | "servicecatalog-appregistry" | "servicediscovery" | "ses" | "sesv2" | "shield" | "signer" | "sms" | "snow-device-management" | "snowball" | "sns" | "sqs" | "ssm" | "ssm-contacts" | "ssm-incidents" | "sso" | "sso-admin" | "sso-oidc" | "stepfunctions" | "storagegateway" | "sts" | "support" | "swf" | "synthetics" | "textract" | "timestream-query" | "timestream-write" | "transcribe" | "transfer" | "translate" | "voice-id" | "waf" | "waf-regional" | "wafv2" | "wellarchitected" | "wisdom" | "workdocs" | "worklink" | "workmail" | "workmailmessageflow" | "workspaces" | "workspaces-web" | "xray" | ""
|
||||
command: string
|
||||
}
|
||||
|
||||
// unmarshal determines whether to automatically json.Unmarshal() the command result. If set to true, the output field will be set to "json" and the command output will be Unmarshaled to result:
|
||||
unmarshal: false | *true
|
||||
|
||||
aws.#Container & {
|
||||
always: true
|
||||
_optionArgs: list.FlattenN([
|
||||
for k, v in options {
|
||||
if (v & bool) != _|_ {
|
||||
["--\(k)"]
|
||||
}
|
||||
if (v & string) != _|_ {
|
||||
["--\(k)", v]
|
||||
}
|
||||
},
|
||||
], 1)
|
||||
|
||||
command: {
|
||||
name: "/bin/sh"
|
||||
flags: "-c": strings.Join(["aws"]+_optionArgs+[service.name, service.command]+service.args+[">", "/output.txt"], " ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
"universe.dagger.io/aws"
|
||||
"universe.dagger.io/aws/cli"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
client: commands: sops: {
|
||||
name: "sops"
|
||||
args: ["-d", "--extract", "[\"AWS\"]", "../../../secrets_sops.yaml"]
|
||||
stdout: dagger.#Secret
|
||||
}
|
||||
|
||||
actions: {
|
||||
sopsSecrets: dagger.#DecodeSecret & {
|
||||
format: "yaml"
|
||||
input: client.commands.sops.stdout
|
||||
}
|
||||
|
||||
getCallerIdentity: cli.#Command & {
|
||||
credentials: aws.#Credentials & {
|
||||
accessKeyId: sopsSecrets.output.AWS_ACCESS_KEY_ID.contents
|
||||
secretAccessKey: sopsSecrets.output.AWS_SECRET_ACCESS_KEY.contents
|
||||
}
|
||||
options: region: "us-east-2"
|
||||
service: {
|
||||
name: "sts"
|
||||
command: "get-caller-identity"
|
||||
}
|
||||
}
|
||||
|
||||
verify: getCallerIdentity.result & {
|
||||
UserId: !~"^$"
|
||||
Account: !~"^$"
|
||||
Arn: !~"^$"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
setup() {
|
||||
load '../../../bats_helpers'
|
||||
|
||||
common_setup
|
||||
}
|
||||
|
||||
@test "aws/cli" {
|
||||
dagger up ./sts_get_caller_identity.cue
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[profile ci]
|
||||
credential_source = Environment
|
||||
region = us-east-2
|
||||
role_arn = arn:aws:iam::125635003186:role/dagger-ci
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"dagger.io/dagger"
|
||||
"universe.dagger.io/aws"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
client: {
|
||||
filesystem: ".": read: {
|
||||
contents: dagger.#FS
|
||||
include: ["config"]
|
||||
}
|
||||
commands: sops: {
|
||||
name: "sops"
|
||||
args: ["-d", "--extract", "[\"AWS\"]", "../../secrets_sops.yaml"]
|
||||
stdout: dagger.#Secret
|
||||
}
|
||||
}
|
||||
|
||||
actions: {
|
||||
sopsSecrets: dagger.#DecodeSecret & {
|
||||
format: "yaml"
|
||||
input: client.commands.sops.stdout
|
||||
}
|
||||
|
||||
getCallerIdentity: aws.#Container & {
|
||||
always: true
|
||||
configFile: client.filesystem.".".read.contents
|
||||
|
||||
credentials: aws.#Credentials & {
|
||||
accessKeyId: sopsSecrets.output.AWS_ACCESS_KEY_ID.contents
|
||||
secretAccessKey: sopsSecrets.output.AWS_SECRET_ACCESS_KEY.contents
|
||||
}
|
||||
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": "aws --profile ci sts get-caller-identity > /output.txt"
|
||||
}
|
||||
|
||||
export: files: "/output.txt": _
|
||||
}
|
||||
|
||||
verify: json.Unmarshal(getCallerIdentity.export.files."/output.txt") & {
|
||||
UserId: string
|
||||
Account: =~"^12[0-9]{8}86$"
|
||||
Arn: =~"^arn:aws:sts::(12[0-9]{8}86):assumed-role/dagger-ci"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"dagger.io/dagger"
|
||||
"universe.dagger.io/aws"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
client: commands: sops: {
|
||||
name: "sops"
|
||||
args: ["-d", "--extract", "[\"AWS\"]", "../../secrets_sops.yaml"]
|
||||
stdout: dagger.#Secret
|
||||
}
|
||||
|
||||
actions: {
|
||||
sopsSecrets: dagger.#DecodeSecret & {
|
||||
format: "yaml"
|
||||
input: client.commands.sops.stdout
|
||||
}
|
||||
|
||||
getCallerIdentity: aws.#Container & {
|
||||
always: true
|
||||
credentials: aws.#Credentials & {
|
||||
accessKeyId: sopsSecrets.output.AWS_ACCESS_KEY_ID.contents
|
||||
secretAccessKey: sopsSecrets.output.AWS_SECRET_ACCESS_KEY.contents
|
||||
}
|
||||
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": "aws --region us-east-2 sts get-caller-identity > /output.txt"
|
||||
}
|
||||
|
||||
export: files: "/output.txt": _
|
||||
}
|
||||
|
||||
verify: json.Unmarshal(getCallerIdentity.export.files."/output.txt") & {
|
||||
UserId: string & !~"^$"
|
||||
Account: =~"^12[0-9]{8}86$"
|
||||
Arn: =~"(12[0-9]{8}86)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
"universe.dagger.io/aws"
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
actions: {
|
||||
build: aws.#Build
|
||||
|
||||
getVersion: docker.#Run & {
|
||||
always: true
|
||||
input: build.output
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": "aws --version > /output.txt"
|
||||
}
|
||||
export: files: "/output.txt": =~"^aws-cli/\(aws.#DefaultCliVersion)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
setup() {
|
||||
load '../../bats_helpers'
|
||||
|
||||
common_setup
|
||||
}
|
||||
|
||||
@test "aws" {
|
||||
dagger up ./default_version.cue
|
||||
dagger up ./credentials.cue
|
||||
dagger up ./config_file.cue
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
// Helpers to run bash commands in containers
|
||||
package bash
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
// Run a bash script in a Docker container
|
||||
// Since this is a thin wrapper over docker.#Run, we embed it.
|
||||
// Whether to embed or wrap is a case-by-case decision, like in Go.
|
||||
#Run: {
|
||||
// The script to execute
|
||||
script: {
|
||||
// A directory containing one or more bash scripts
|
||||
directory: dagger.#FS
|
||||
|
||||
// Name of the file to execute
|
||||
filename: string
|
||||
|
||||
_directory: directory
|
||||
_filename: filename
|
||||
} | {
|
||||
// Script contents
|
||||
contents: string
|
||||
|
||||
_filename: "run.sh"
|
||||
_write: dagger.#WriteFile & {
|
||||
input: dagger.#Scratch
|
||||
path: _filename
|
||||
"contents": contents
|
||||
}
|
||||
_directory: _write.output
|
||||
}
|
||||
|
||||
// Arguments to the script
|
||||
args: [...string]
|
||||
|
||||
// Where in the container to mount the scripts directory
|
||||
_mountpoint: "/bash/scripts"
|
||||
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "bash"
|
||||
"args": ["\(_mountpoint)/\(script._filename)"] + args
|
||||
// FIXME: make default flags overrideable
|
||||
flags: {
|
||||
"--norc": true
|
||||
"-e": true
|
||||
"-o": "pipefail"
|
||||
}
|
||||
}
|
||||
mounts: "Bash scripts": {
|
||||
contents: script._directory
|
||||
dest: _mountpoint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo Hello, world > /out.txt
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
setup() {
|
||||
load '../../bats_helpers'
|
||||
|
||||
common_setup
|
||||
}
|
||||
|
||||
@test "bash" {
|
||||
dagger up
|
||||
}
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package bash
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
|
||||
"universe.dagger.io/docker"
|
||||
"universe.dagger.io/bash"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
actions: tests: {
|
||||
|
||||
_pull: docker.#Pull & {
|
||||
source: "index.docker.io/debian"
|
||||
}
|
||||
_image: _pull.output
|
||||
|
||||
// Run a script from source directory + filename
|
||||
runFile: {
|
||||
|
||||
dir: _load.output
|
||||
_load: dagger.#Source & {
|
||||
path: "./data"
|
||||
include: ["*.sh"]
|
||||
}
|
||||
|
||||
run: bash.#Run & {
|
||||
input: _image
|
||||
export: files: "/out.txt": _
|
||||
script: {
|
||||
directory: dir
|
||||
filename: "hello.sh"
|
||||
}
|
||||
}
|
||||
output: run.export.files."/out.txt" & "Hello, world\n"
|
||||
}
|
||||
|
||||
// Run a script from string
|
||||
runString: {
|
||||
run: bash.#Run & {
|
||||
input: _image
|
||||
export: files: "/output.txt": _
|
||||
script: contents: "echo 'Hello, inlined world!' > /output.txt"
|
||||
}
|
||||
output: run.export.files."/output.txt" & "Hello, inlined world!\n"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
common_setup() {
|
||||
load "$(dirname "${BASH_SOURCE[0]}")/node_modules/bats-support/load.bash"
|
||||
load "$(dirname "${BASH_SOURCE[0]}")/node_modules/bats-assert/load.bash"
|
||||
|
||||
# Dagger Binary
|
||||
# FIXME: `command -v` must be wrapped in a sub-bash,
|
||||
# otherwise infinite recursion when DAGGER_BINARY is not set.
|
||||
export DAGGER="${DAGGER_BINARY:-$(bash -c 'command -v dagger')}"
|
||||
|
||||
# Force Europa mode
|
||||
DAGGER_EUROPA="1"
|
||||
export DAGGER_EUROPA
|
||||
|
||||
# Force plain printing for error reporting
|
||||
DAGGER_LOG_FORMAT="plain"
|
||||
export DAGGER_LOG_FORMAT
|
||||
|
||||
# cd into the directory containing the bats file
|
||||
cd "$BATS_TEST_DIRNAME" || exit 1
|
||||
}
|
||||
|
||||
# dagger helper to execute the right binary
|
||||
dagger() {
|
||||
"${DAGGER}" "$@"
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
module: "universe.dagger.io"
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
// Modular build API for Docker containers
|
||||
#Build: {
|
||||
steps: [#Step, ...#Step]
|
||||
output: #Image
|
||||
|
||||
// Generate build DAG from linear steps
|
||||
_dag: {
|
||||
for idx, step in steps {
|
||||
"\(idx)": step & {
|
||||
// connect input to previous output
|
||||
if idx > 0 {
|
||||
// FIXME: the intermediary `output` is needed because of a possible CUE bug.
|
||||
// `._dag."0".output: 1 errors in empty disjunction::`
|
||||
// See: https://github.com/cue-lang/cue/issues/1446
|
||||
// input: _dag["\(idx-1)"].output
|
||||
_output: _dag["\(idx-1)"].output
|
||||
input: _output
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(_dag) > 0 {
|
||||
output: _dag["\(len(_dag)-1)"].output
|
||||
}
|
||||
}
|
||||
|
||||
// A build step is anything that produces a docker image
|
||||
#Step: {
|
||||
input?: #Image
|
||||
output: #Image
|
||||
...
|
||||
}
|
||||
|
||||
// Build step that copies files into the container image
|
||||
#Copy: {
|
||||
input: #Image
|
||||
contents: dagger.#FS
|
||||
source: string | *"/"
|
||||
dest: string | *"/"
|
||||
|
||||
// Execute copy operation
|
||||
_copy: dagger.#Copy & {
|
||||
"input": input.rootfs
|
||||
"contents": contents
|
||||
"source": source
|
||||
"dest": dest
|
||||
}
|
||||
|
||||
output: #Image & {
|
||||
config: input.config
|
||||
rootfs: _copy.output
|
||||
}
|
||||
}
|
||||
|
||||
// Build step that executes a Dockerfile
|
||||
#Dockerfile: {
|
||||
// Source directory
|
||||
source: dagger.#FS
|
||||
|
||||
// FIXME: not yet implemented
|
||||
*{
|
||||
// Look for Dockerfile in source at default path
|
||||
path: "Dockerfile"
|
||||
} | {
|
||||
// Look for Dockerfile in source at a custom path
|
||||
path: string
|
||||
} | {
|
||||
// Custom dockerfile contents
|
||||
contents: string
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
// A container image
|
||||
#Image: {
|
||||
// Root filesystem of the image.
|
||||
rootfs: dagger.#FS
|
||||
|
||||
// Image config
|
||||
config: dagger.#ImageConfig
|
||||
}
|
||||
|
||||
// A ref is an address for a remote container image
|
||||
// Examples:
|
||||
// - "index.docker.io/dagger"
|
||||
// - "dagger"
|
||||
// - "index.docker.io/dagger:latest"
|
||||
// - "index.docker.io/dagger:latest@sha256:a89cb097693dd354de598d279c304a1c73ee550fbfff6d9ee515568e0c749cfe"
|
||||
// FIXME: add formatting constraints
|
||||
#Ref: dagger.#Ref
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// Build, ship and run Docker containers in Dagger
|
||||
package docker
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
// Download an image from a remote registry
|
||||
#Pull: {
|
||||
// Source ref.
|
||||
source: #Ref
|
||||
|
||||
// Registry authentication
|
||||
auth?: {
|
||||
username: string
|
||||
secret: dagger.#Secret
|
||||
}
|
||||
|
||||
_op: dagger.#Pull & {
|
||||
"source": source
|
||||
if auth != _|_ {
|
||||
"auth": auth
|
||||
}
|
||||
}
|
||||
|
||||
// Downloaded image
|
||||
image: #Image & {
|
||||
rootfs: _op.output
|
||||
config: _op.config
|
||||
}
|
||||
|
||||
// FIXME: compat with Build API
|
||||
output: image
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
// Upload an image to a remote repository
|
||||
#Push: {
|
||||
// Destination ref
|
||||
dest: #Ref
|
||||
|
||||
// Complete ref after pushing (including digest)
|
||||
result: #Ref & _push.result
|
||||
|
||||
// Registry authentication
|
||||
auth?: {
|
||||
username: string
|
||||
secret: dagger.#Secret
|
||||
}
|
||||
|
||||
// Image to push
|
||||
image: #Image
|
||||
|
||||
_push: dagger.#Push & {
|
||||
"dest": dest
|
||||
if auth != _|_ {
|
||||
"auth": auth
|
||||
}
|
||||
input: image.rootfs
|
||||
config: image.config
|
||||
}
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"list"
|
||||
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
// Run a command in a container
|
||||
#Run: {
|
||||
// Docker image to execute
|
||||
input: #Image
|
||||
|
||||
always: bool | *false
|
||||
|
||||
// Filesystem mounts
|
||||
mounts: [name=string]: dagger.#Mount
|
||||
|
||||
// Expose network ports
|
||||
// FIXME: investigate feasibility
|
||||
ports: [name=string]: {
|
||||
frontend: dagger.#Service
|
||||
backend: {
|
||||
protocol: *"tcp" | "udp"
|
||||
address: string
|
||||
}
|
||||
}
|
||||
|
||||
// Command to execute
|
||||
command?: {
|
||||
// Name of the command to execute
|
||||
// Examples: "ls", "/bin/bash"
|
||||
name: string
|
||||
|
||||
// Positional arguments to the command
|
||||
// Examples: ["/tmp"]
|
||||
args: [...string]
|
||||
|
||||
// Command-line flags represented in a civilized form
|
||||
// Example: {"-l": true, "-c": "echo hello world"}
|
||||
flags: [string]: (string | true)
|
||||
|
||||
_flatFlags: list.FlattenN([
|
||||
for k, v in flags {
|
||||
if (v & bool) != _|_ {
|
||||
[k]
|
||||
}
|
||||
if (v & string) != _|_ {
|
||||
[k, v]
|
||||
}
|
||||
},
|
||||
], 1)
|
||||
}
|
||||
|
||||
// Environment variables
|
||||
// Example: {"DEBUG": "1"}
|
||||
env: [string]: string | dagger.#Secret
|
||||
|
||||
// Working directory for the command
|
||||
// Example: "/src"
|
||||
workdir: string
|
||||
|
||||
// Username or UID to ad
|
||||
// User identity for this command
|
||||
// Examples: "root", "0", "1002"
|
||||
user: string
|
||||
|
||||
// Output fields
|
||||
{
|
||||
// Has the command completed?
|
||||
completed: bool & (_exec.exit != _|_)
|
||||
|
||||
// Was completion successful?
|
||||
success: bool & (_exec.exit == 0)
|
||||
|
||||
// Details on error, if any
|
||||
error: {
|
||||
// Error code
|
||||
code: _exec.exit
|
||||
|
||||
// Error message
|
||||
message: string | *null
|
||||
}
|
||||
|
||||
export: {
|
||||
rootfs: dagger.#FS & _exec.output
|
||||
files: [path=string]: string
|
||||
_files: {
|
||||
for path, _ in files {
|
||||
"\(path)": {
|
||||
contents: string & _read.contents
|
||||
_read: dagger.#ReadFile & {
|
||||
input: _exec.output
|
||||
"path": path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for path, output in _files {
|
||||
files: "\(path)": output.contents
|
||||
}
|
||||
|
||||
directories: [path=string]: dagger.#FS
|
||||
_directories: {
|
||||
for path, _ in directories {
|
||||
"\(path)": {
|
||||
contents: dagger.#FS & _subdir.output
|
||||
_subdir: dagger.#Subdir & {
|
||||
input: _exec.output
|
||||
"path": path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for path, output in _directories {
|
||||
directories: "\(path)": output.contents
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For compatibility with #Build
|
||||
output: #Image & {
|
||||
rootfs: _exec.output
|
||||
config: input.config
|
||||
}
|
||||
|
||||
// Actually execute the command
|
||||
_exec: dagger.#Exec & {
|
||||
"input": input.rootfs
|
||||
"always": always
|
||||
"mounts": mounts
|
||||
|
||||
if command != _|_ {
|
||||
args: [command.name] + command._flatFlags + command.args
|
||||
}
|
||||
if command == _|_ {
|
||||
args: list.Concat([
|
||||
if input.config.entrypoint != _|_ {
|
||||
input.config.entrypoint
|
||||
},
|
||||
if input.config.cmd != _|_ {
|
||||
input.config.cmd
|
||||
},
|
||||
])
|
||||
}
|
||||
"env": env
|
||||
if input.config.env != _|_ {
|
||||
for key, val in input.config.env {
|
||||
if env[key] == _|_ {
|
||||
env: "\(key)": val
|
||||
}
|
||||
}
|
||||
}
|
||||
"workdir": workdir
|
||||
if workdir == _|_ && input.config.workdir != _|_ {
|
||||
workdir: input.config.workdir
|
||||
}
|
||||
"user": user
|
||||
if user == _|_ && input.config.user != _|_ {
|
||||
user: input.config.user
|
||||
}
|
||||
}
|
||||
|
||||
// Command exit code
|
||||
exit: _exec.exit
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
// Change image config
|
||||
#Set: {
|
||||
// The source image
|
||||
input: #Image
|
||||
|
||||
// The image config to change
|
||||
config: dagger.#ImageConfig
|
||||
|
||||
_set: dagger.#Set & {
|
||||
"input": input.config
|
||||
"config": config
|
||||
}
|
||||
|
||||
// Resulting image with the config changes
|
||||
output: #Image & {
|
||||
rootfs: input.rootfs
|
||||
config: _set.output
|
||||
}
|
||||
}
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
|
||||
"universe.dagger.io/alpine"
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
actions: tests: build: {
|
||||
// Test: simple docker.#Build
|
||||
simple: {
|
||||
#testValue: "hello world"
|
||||
|
||||
image: docker.#Build & {
|
||||
steps: [
|
||||
alpine.#Build,
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": "echo -n $TEST >> /test.txt"
|
||||
}
|
||||
env: TEST: #testValue
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
verify: dagger.#ReadFile & {
|
||||
input: image.output.rootfs
|
||||
path: "/test.txt"
|
||||
}
|
||||
verify: contents: #testValue
|
||||
}
|
||||
|
||||
// Test: docker.#Build with multiple steps
|
||||
multiSteps: {
|
||||
image: docker.#Build & {
|
||||
steps: [
|
||||
alpine.#Build,
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": "echo -n hello > /bar.txt"
|
||||
}
|
||||
},
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": "echo -n $(cat /bar.txt) world > /foo.txt"
|
||||
}
|
||||
},
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": "echo -n $(cat /foo.txt) >> /test.txt"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
verify: dagger.#ReadFile & {
|
||||
input: image.output.rootfs
|
||||
path: "/test.txt"
|
||||
}
|
||||
verify: contents: "hello world"
|
||||
}
|
||||
|
||||
// Test: simple nesting of docker.#Build
|
||||
nested: {
|
||||
build: docker.#Build & {
|
||||
steps: [
|
||||
docker.#Build & {
|
||||
steps: [
|
||||
docker.#Pull & {
|
||||
source: "alpine"
|
||||
},
|
||||
docker.#Run & {
|
||||
command: name: "ls"
|
||||
},
|
||||
]
|
||||
},
|
||||
docker.#Run & {
|
||||
command: name: "ls"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Test: nested docker.#Build with 3+ levels of depth
|
||||
// FIXME: this test currently fails.
|
||||
nestedDeep: {
|
||||
// build: docker.#Build & {
|
||||
// steps: [
|
||||
// docker.#Build & {
|
||||
// steps: [
|
||||
// docker.#Build & {
|
||||
// steps: [
|
||||
// docker.#Pull & {
|
||||
// source: "alpine"
|
||||
// },
|
||||
// docker.#Run & {
|
||||
// command: name: "ls"
|
||||
// },
|
||||
// ]
|
||||
// },
|
||||
// docker.#Run & {
|
||||
// command: name: "ls"
|
||||
// },
|
||||
// ]
|
||||
// },
|
||||
// docker.#Run & {
|
||||
// command: name: "ls"
|
||||
// },
|
||||
// ]
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
|
||||
actions: tests: image: {
|
||||
|
||||
// Test: change image config with docker.#Set
|
||||
set: {
|
||||
image: output: docker.#Image & {
|
||||
rootfs: dagger.#Scratch
|
||||
config: {
|
||||
cmd: ["/bin/sh"]
|
||||
env: PATH: "/sbin:/bin"
|
||||
onbuild: ["COPY . /app"]
|
||||
}
|
||||
}
|
||||
set: docker.#Set & {
|
||||
input: image.output
|
||||
config: {
|
||||
env: FOO: "bar"
|
||||
workdir: "/root"
|
||||
onbuild: ["RUN /app/build.sh"]
|
||||
}
|
||||
}
|
||||
verify: set.output.config & {
|
||||
env: {
|
||||
PATH: "/sbin:/bin"
|
||||
FOO: "bar"
|
||||
}
|
||||
cmd: ["/bin/sh"]
|
||||
workdir: "/root"
|
||||
onbuild: [
|
||||
"COPY . /app",
|
||||
"RUN /app/build.sh",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Test: image config behavior is correct
|
||||
config: {
|
||||
build: dagger.#Dockerfile & {
|
||||
source: dagger.#Scratch
|
||||
dockerfile: contents: """
|
||||
FROM alpine:3.15.0
|
||||
RUN echo -n 'not hello from dagger' > /dagger.txt
|
||||
RUN echo '#!/bin/sh' > /bin/dagger
|
||||
ENV HELLO_FROM=dagger
|
||||
RUN echo 'echo -n "hello from $HELLO_FROM" > /dagger.txt' >> /bin/dagger
|
||||
RUN chmod +x /bin/dagger
|
||||
WORKDIR /bin
|
||||
CMD /bin/dagger
|
||||
"""
|
||||
}
|
||||
myimage: docker.#Image & {
|
||||
rootfs: build.output
|
||||
config: build.config
|
||||
}
|
||||
run: docker.#Run & {
|
||||
input: myimage
|
||||
command: name: "ls"
|
||||
export: files: {
|
||||
"/dagger.txt": _ & {
|
||||
contents: "not hello from dagger"
|
||||
}
|
||||
"/bin/dagger": _ & {
|
||||
contents: """
|
||||
#!/bin/sh
|
||||
echo -n "hello from $HELLO_FROM" > /dagger.txt
|
||||
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
verify_cmd_is_run: docker.#Run & {
|
||||
input: myimage
|
||||
export: files: "/dagger.txt": _ & {
|
||||
contents: "hello from dagger"
|
||||
}
|
||||
}
|
||||
verify_env_is_overridden: docker.#Run & {
|
||||
input: myimage
|
||||
export: files: "/dagger.txt": _ & {
|
||||
contents: "hello from europa"
|
||||
}
|
||||
env: HELLO_FROM: "europa"
|
||||
}
|
||||
|
||||
verify_working_directory: docker.#Run & {
|
||||
input: myimage
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": #"""
|
||||
pwd > dir.txt
|
||||
"""#
|
||||
}
|
||||
export: files: "/bin/dir.txt": _ & {
|
||||
contents: "/bin\n"
|
||||
}
|
||||
}
|
||||
verify_working_directory_is_overridden: docker.#Run & {
|
||||
input: myimage
|
||||
workdir: "/"
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": #"""
|
||||
pwd > dir.txt
|
||||
"""#
|
||||
}
|
||||
export: files: "/dir.txt": _ & {
|
||||
contents: "/\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
|
||||
"universe.dagger.io/docker"
|
||||
"universe.dagger.io/alpine"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
actions: tests: run: {
|
||||
_build: alpine.#Build
|
||||
_image: _build.output
|
||||
|
||||
// Test: run a simple shell command
|
||||
simpleShell: {
|
||||
image: alpine.#Build
|
||||
|
||||
run: docker.#Run & {
|
||||
input: _image
|
||||
command: {
|
||||
name: "/bin/sh"
|
||||
args: ["-c", "echo -n hello world >> /output.txt"]
|
||||
}
|
||||
}
|
||||
|
||||
verify: dagger.#ReadFile & {
|
||||
input: run.output.rootfs
|
||||
path: "/output.txt"
|
||||
}
|
||||
verify: contents: "hello world"
|
||||
}
|
||||
|
||||
// Test: export a file
|
||||
exportFile: {
|
||||
run: docker.#Run & {
|
||||
input: _image
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": #"""
|
||||
echo -n hello world >> /output.txt
|
||||
"""#
|
||||
}
|
||||
export: files: "/output.txt": string & "hello world"
|
||||
}
|
||||
}
|
||||
|
||||
// Test: export a directory
|
||||
exportDirectory: {
|
||||
run: docker.#Run & {
|
||||
input: _image
|
||||
command: {
|
||||
name: "sh"
|
||||
flags: "-c": #"""
|
||||
mkdir -p /test
|
||||
echo -n hello world >> /test/output.txt
|
||||
"""#
|
||||
}
|
||||
export: directories: "/test": _
|
||||
}
|
||||
|
||||
verify: dagger.#ReadFile & {
|
||||
input: run.export.directories."/test"
|
||||
path: "/output.txt"
|
||||
}
|
||||
verify: contents: "hello world"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
setup() {
|
||||
load '../../bats_helpers'
|
||||
|
||||
common_setup
|
||||
}
|
||||
|
||||
@test "docker" {
|
||||
dagger up
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
## Dagger examples
|
||||
|
||||
A collection of examples to help Dagger developers get started.
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
package changelog
|
||||
|
||||
actions: {
|
||||
// Reuse in all mix commands
|
||||
|
||||
// prod: assets: docker.#Build & {
|
||||
// steps: [
|
||||
// // 1. Start from dev assets :)
|
||||
// dev.assets,
|
||||
// // 2. Mix magical command
|
||||
// mix.#Run & {
|
||||
// script: "mix phx.digest"
|
||||
// mix: {
|
||||
// env: "prod"
|
||||
// app: _appName
|
||||
// depsCache: "private"
|
||||
// buildCache: "private"
|
||||
// }
|
||||
// workdir: _
|
||||
// // FIXME: remove copy-pasta
|
||||
// mounts: nodeModules: {
|
||||
// contents: dagger.#CacheDir & {
|
||||
// // FIXME: do we need an ID here?
|
||||
// id: "\(mix.app)_assets_node_modules"
|
||||
// // FIXME: does this command need write access to node_modules cache?
|
||||
// concurrency: "private"
|
||||
// }
|
||||
// dest: "\(workdir)/node_modules"
|
||||
// }
|
||||
// },
|
||||
// ]
|
||||
// }
|
||||
|
||||
// dev: {
|
||||
// compile: mix.#Compile & {
|
||||
// env: "dev"
|
||||
// app: "thechangelog"
|
||||
// base: inputs.params.runtimeImage
|
||||
// source: inputs.directories.app.contents
|
||||
// }
|
||||
|
||||
// assets: docker.#Build & {
|
||||
// steps: [
|
||||
// // 1. Start from dev runtime build
|
||||
// {
|
||||
// output: build.output
|
||||
// },
|
||||
// // 2. Build web assets
|
||||
// mix.#Run & {
|
||||
// mix: {
|
||||
// env: "dev"
|
||||
// app: _appName
|
||||
// depsCache: "private"
|
||||
// buildCache: "private"
|
||||
// }
|
||||
// // FIXME: move this to a reusable def (yarn package? or private?)
|
||||
// mounts: nodeModules: {
|
||||
// contents: dagger.#CacheDir & {
|
||||
// // FIXME: do we need an ID here?
|
||||
// id: "\(mix.app)_assets_node_modules"
|
||||
// // FIXME: will there be multiple writers?
|
||||
// concurrency: "locked"
|
||||
// }
|
||||
// dest: "\(workdir)/node_modules"
|
||||
// }
|
||||
// // FIXME: run 'yarn install' and 'yarn run compile' separately, with different caching?
|
||||
// // FIXME: can we reuse universe.dagger.io/yarn ???? 0:-)
|
||||
// script: "yarn install --frozen-lockfile && yarn run compile"
|
||||
// workdir: "/app/assets"
|
||||
// },
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// test: {
|
||||
// build: mix.#Build & {
|
||||
// env: "test"
|
||||
// app: _appName
|
||||
// base: inputs.params.runtimeImage
|
||||
// source: inputs.directories.app.contents
|
||||
// }
|
||||
|
||||
// // Run tests
|
||||
// run: docker.#Run & {
|
||||
// image: build.output
|
||||
// script: "mix test"
|
||||
// }
|
||||
|
||||
// db: {
|
||||
// // Pull test DB image
|
||||
// pull: docker.#Pull & {
|
||||
// source: inputs.params.test_db_image
|
||||
// }
|
||||
|
||||
// // Run test DB
|
||||
// // FIXME: kill once no longer needed (when tests are done running)
|
||||
// run: docker.#Run & {
|
||||
// image: pull.output
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
package mix
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
#Get: #Run & {
|
||||
// Applies to all environments
|
||||
env: null
|
||||
cache: {
|
||||
build: null
|
||||
deps: "locked"
|
||||
}
|
||||
container: command: {
|
||||
name: "sh"
|
||||
flags: "-c": "mix do deps.get"
|
||||
}
|
||||
}
|
||||
|
||||
// Compile Elixir dependencies, including the app
|
||||
#Compile: #Run & {
|
||||
cache: {
|
||||
build: "locked"
|
||||
deps: "locked"
|
||||
}
|
||||
container: command: {
|
||||
name: "sh"
|
||||
flags: "-c": "mix do deps.compile, compile"
|
||||
}
|
||||
}
|
||||
|
||||
// Run mix task with all necessary mounts so compiled artefacts get cached
|
||||
// FIXME: add default image to hexpm/elixir:1.13.2-erlang-23.3.4.11-debian-bullseye-20210902
|
||||
#Run: {
|
||||
app: {
|
||||
// Application name
|
||||
name: string
|
||||
|
||||
// Application source code
|
||||
source: dagger.#FS
|
||||
}
|
||||
|
||||
// Mix environment
|
||||
env: string | null
|
||||
|
||||
// Configure mix caching
|
||||
// FIXME: simpler interface, eg. "ro" | "rw"
|
||||
cache: {
|
||||
// Dependencies cache
|
||||
deps: null | "locked"
|
||||
|
||||
// Build cache
|
||||
build: null | "locked"
|
||||
}
|
||||
|
||||
// Run mix in a docker container
|
||||
container: docker.#Run & {
|
||||
if env != null {
|
||||
"env": MIX_ENV: env
|
||||
}
|
||||
workdir: mounts.app.dest
|
||||
mounts: "app": {
|
||||
contents: app.source
|
||||
dest: "/mix/app"
|
||||
}
|
||||
if cache.deps != null {
|
||||
mounts: deps: {
|
||||
contents: dagger.#CacheDir & {
|
||||
id: "\(app.name)_deps"
|
||||
concurrency: cache.deps
|
||||
}
|
||||
dest: "\(mounts.app.dest)/deps"
|
||||
}
|
||||
}
|
||||
if cache.build != null {
|
||||
mounts: buildCache: {
|
||||
contents: dagger.#CacheDir & {
|
||||
id: "\(app.name)_build_\(env)"
|
||||
concurrency: cache.build
|
||||
}
|
||||
dest: "\(mounts.app.dest)/_build/\(env)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
package changelog
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
inputs: directories: app: path: "/Users/gerhard/github.com/thechangelog/changelog.com/"
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
package changelog
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
|
||||
"universe.dagger.io/docker"
|
||||
"universe.dagger.io/git"
|
||||
"universe.dagger.io/examples/changelog.com/elixir/mix"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
// Receive things from client
|
||||
inputs: {
|
||||
directories: {
|
||||
// App source code
|
||||
app?: _
|
||||
}
|
||||
secrets: {
|
||||
// Docker ID password
|
||||
docker: _
|
||||
}
|
||||
params: {
|
||||
app: {
|
||||
// App name
|
||||
name: string | *"changelog"
|
||||
|
||||
// Address of app base image
|
||||
image: docker.#Ref | *"thechangelog/runtime:2021-05-29T10.17.12Z"
|
||||
}
|
||||
|
||||
test: {
|
||||
// Address of test db image
|
||||
db: image: docker.#Ref | *"circleci/postgres:12.6"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Do things
|
||||
actions: {
|
||||
app: {
|
||||
name: inputs.params.app.name
|
||||
|
||||
// changelog.com source code
|
||||
source: dagger.#FS
|
||||
if inputs.directories.app != _|_ {
|
||||
source: inputs.directories.app.contents
|
||||
}
|
||||
if inputs.directories.app == _|_ {
|
||||
fetch: git.#Pull & {
|
||||
remote: "https://github.com/thechangelog/changelog.com"
|
||||
ref: "master"
|
||||
}
|
||||
source: fetch.output
|
||||
}
|
||||
|
||||
// Assemble base image
|
||||
base: docker.#Pull & {
|
||||
source: inputs.params.app.image
|
||||
}
|
||||
image: base.output
|
||||
|
||||
// Download Elixir dependencies
|
||||
deps: mix.#Get & {
|
||||
app: {
|
||||
"name": name
|
||||
"source": source
|
||||
}
|
||||
container: "image": image
|
||||
}
|
||||
|
||||
// Compile dev environment
|
||||
dev: mix.#Compile & {
|
||||
env: "dev"
|
||||
app: {
|
||||
"name": name
|
||||
"source": source
|
||||
}
|
||||
container: "image": image
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# Todo APP
|
||||
|
||||
[Dagger documentation website](https://docs.dagger.io/)
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
package netlify
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
"universe.dagger.io/alpine"
|
||||
"universe.dagger.io/bash"
|
||||
"universe.dagger.io/docker"
|
||||
"universe.dagger.io/netlify"
|
||||
)
|
||||
|
||||
dagger.#Plan & {
|
||||
client: {
|
||||
filesystem: {
|
||||
".": read: {
|
||||
contents: dagger.#FS
|
||||
exclude: [
|
||||
"README.md",
|
||||
"build",
|
||||
"netlify.cue",
|
||||
"node_modules",
|
||||
]
|
||||
}
|
||||
build: write: contents: actions.build.contents.output
|
||||
}
|
||||
env: {
|
||||
APP_NAME: string
|
||||
NETLIFY_TEAM: string
|
||||
NETLIFY_TOKEN: dagger.#Secret
|
||||
}
|
||||
}
|
||||
actions: {
|
||||
deps: docker.#Build & {
|
||||
steps: [
|
||||
alpine.#Build & {
|
||||
packages: {
|
||||
bash: {}
|
||||
yarn: {}
|
||||
git: {}
|
||||
}
|
||||
},
|
||||
docker.#Copy & {
|
||||
contents: client.filesystem.".".read.contents
|
||||
dest: "/src"
|
||||
},
|
||||
// bash.#Run is a superset of docker.#Run
|
||||
// install yarn dependencies
|
||||
bash.#Run & {
|
||||
workdir: "/src"
|
||||
mounts: "/cache/yarn": dagger.#Mount & {
|
||||
dest: "/cache/yarn"
|
||||
type: "cache"
|
||||
contents: dagger.#CacheDir & {
|
||||
id: "todoapp-yarn-cache"
|
||||
}
|
||||
}
|
||||
script: contents: #"""
|
||||
yarn config set cache-folder /cache/yarn
|
||||
yarn install
|
||||
"""#
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
test: bash.#Run & {
|
||||
input: deps.output
|
||||
workdir: "/src"
|
||||
script: contents: #"""
|
||||
yarn run test
|
||||
"""#
|
||||
}
|
||||
|
||||
build: {
|
||||
run: bash.#Run & {
|
||||
input: test.output
|
||||
workdir: "/src"
|
||||
script: contents: #"""
|
||||
yarn run build
|
||||
"""#
|
||||
}
|
||||
|
||||
contents: dagger.#Subdir & {
|
||||
input: run.output.rootfs
|
||||
path: "/src/build"
|
||||
}
|
||||
}
|
||||
|
||||
deploy: netlify.#Deploy & {
|
||||
contents: build.contents.output
|
||||
site: client.env.APP_NAME
|
||||
token: client.env.NETLIFY_TOKEN
|
||||
team: client.env.NETLIFY_TEAM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"name": "moz-todo-react",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"homepage": "./",
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
"gh-pages": "^3.2.3",
|
||||
"nanoid": "^3.1.31",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --watchAll=false --passWithNoTests",
|
||||
"gh-pages": "gh-pages -d build -u 'github-actions-bot <support+actions@github.com>'",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
|
|
@ -1,43 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>My Todo app</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB |
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
import React, { useState, useRef, useEffect } from "react";
|
||||
import Form from "./components/Form";
|
||||
import FilterButton from "./components/FilterButton";
|
||||
import Todo from "./components/Todo";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
|
||||
function usePrevious(value) {
|
||||
const ref = useRef();
|
||||
useEffect(() => {
|
||||
ref.current = value;
|
||||
});
|
||||
return ref.current;
|
||||
}
|
||||
|
||||
const FILTER_MAP = {
|
||||
All: () => true,
|
||||
Active: task => !task.completed,
|
||||
Completed: task => task.completed
|
||||
};
|
||||
|
||||
const FILTER_NAMES = Object.keys(FILTER_MAP);
|
||||
|
||||
function App(props) {
|
||||
const [tasks, setTasks] = useState(props.tasks);
|
||||
const [filter, setFilter] = useState('All');
|
||||
|
||||
function toggleTaskCompleted(id) {
|
||||
const updatedTasks = tasks.map(task => {
|
||||
// if this task has the same ID as the edited task
|
||||
if (id === task.id) {
|
||||
// use object spread to make a new obkect
|
||||
// whose `completed` prop has been inverted
|
||||
return {...task, completed: !task.completed}
|
||||
}
|
||||
return task;
|
||||
});
|
||||
setTasks(updatedTasks);
|
||||
}
|
||||
|
||||
|
||||
function deleteTask(id) {
|
||||
const remainingTasks = tasks.filter(task => id !== task.id);
|
||||
setTasks(remainingTasks);
|
||||
}
|
||||
|
||||
|
||||
function editTask(id, newName) {
|
||||
const editedTaskList = tasks.map(task => {
|
||||
// if this task has the same ID as the edited task
|
||||
if (id === task.id) {
|
||||
//
|
||||
return {...task, name: newName}
|
||||
}
|
||||
return task;
|
||||
});
|
||||
setTasks(editedTaskList);
|
||||
}
|
||||
|
||||
const taskList = tasks
|
||||
.filter(FILTER_MAP[filter])
|
||||
.map(task => (
|
||||
<Todo
|
||||
id={task.id}
|
||||
name={task.name}
|
||||
completed={task.completed}
|
||||
key={task.id}
|
||||
toggleTaskCompleted={toggleTaskCompleted}
|
||||
deleteTask={deleteTask}
|
||||
editTask={editTask}
|
||||
/>
|
||||
));
|
||||
|
||||
const filterList = FILTER_NAMES.map(name => (
|
||||
<FilterButton
|
||||
key={name}
|
||||
name={name}
|
||||
isPressed={name === filter}
|
||||
setFilter={setFilter}
|
||||
/>
|
||||
));
|
||||
|
||||
function addTask(name) {
|
||||
const newTask = { id: "todo-" + nanoid(), name: name, completed: false };
|
||||
setTasks([...tasks, newTask]);
|
||||
}
|
||||
|
||||
|
||||
const tasksNoun = taskList.length !== 1 ? 'tasks' : 'task';
|
||||
const headingText = `${taskList.length} ${tasksNoun} remaining`;
|
||||
|
||||
const listHeadingRef = useRef(null);
|
||||
const prevTaskLength = usePrevious(tasks.length);
|
||||
|
||||
useEffect(() => {
|
||||
if (tasks.length - prevTaskLength === -1) {
|
||||
listHeadingRef.current.focus();
|
||||
}
|
||||
}, [tasks.length, prevTaskLength]);
|
||||
|
||||
return (
|
||||
<div className="todoapp stack-large">
|
||||
<Form addTask={addTask} />
|
||||
<div className="filters btn-group stack-exception">
|
||||
{filterList}
|
||||
</div>
|
||||
<h2 id="list-heading" tabIndex="-1" ref={listHeadingRef}>
|
||||
{headingText}
|
||||
</h2>
|
||||
<ul
|
||||
className="todo-list stack-large stack-exception"
|
||||
aria-labelledby="list-heading"
|
||||
>
|
||||
{taskList}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
function FilterButton(props) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="btn toggle-btn"
|
||||
aria-pressed={props.isPressed}
|
||||
onClick={() => props.setFilter(props.name)}
|
||||
>
|
||||
<span className="visually-hidden">Show </span>
|
||||
<span>{props.name}</span>
|
||||
<span className="visually-hidden"> tasks</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export default FilterButton;
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
function Form(props) {
|
||||
const [name, setName] = useState('');
|
||||
|
||||
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
if (!name.trim()) {
|
||||
return;
|
||||
}
|
||||
props.addTask(name);
|
||||
setName("");
|
||||
}
|
||||
|
||||
|
||||
function handleChange(e) {
|
||||
setName(e.target.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<h2 className="label-wrapper">
|
||||
<label htmlFor="new-todo-input" className="label__lg">
|
||||
What needs to be done?
|
||||
</label>
|
||||
</h2>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
id="new-todo-input"
|
||||
className="input input__lg"
|
||||
name="text"
|
||||
autoComplete="off"
|
||||
value={name}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<button type="submit" className="btn btn__primary btn__lg">
|
||||
Add
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
export default Form;
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from "react";
|
||||
|
||||
|
||||
function usePrevious(value) {
|
||||
const ref = useRef();
|
||||
useEffect(() => {
|
||||
ref.current = value;
|
||||
});
|
||||
return ref.current;
|
||||
}
|
||||
|
||||
export default function Todo(props) {
|
||||
const [isEditing, setEditing] = useState(false);
|
||||
const [newName, setNewName] = useState('');
|
||||
|
||||
const editFieldRef = useRef(null);
|
||||
const editButtonRef = useRef(null);
|
||||
|
||||
const wasEditing = usePrevious(isEditing);
|
||||
|
||||
function handleChange(e) {
|
||||
setNewName(e.target.value);
|
||||
}
|
||||
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
if (!newName.trim()) {
|
||||
return;
|
||||
}
|
||||
props.editTask(props.id, newName);
|
||||
setNewName("");
|
||||
setEditing(false);
|
||||
}
|
||||
|
||||
const editingTemplate = (
|
||||
<form className="stack-small" onSubmit={handleSubmit}>
|
||||
<div className="form-group">
|
||||
<label className="todo-label" htmlFor={props.id}>
|
||||
New name for {props.name}
|
||||
</label>
|
||||
<input
|
||||
id={props.id}
|
||||
className="todo-text"
|
||||
type="text"
|
||||
value={newName || props.name}
|
||||
onChange={handleChange}
|
||||
ref={editFieldRef}
|
||||
/>
|
||||
</div>
|
||||
<div className="btn-group">
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="btn todo-cancel"
|
||||
onClick={() => setEditing(false)}
|
||||
>
|
||||
Cancel
|
||||
<span className="visually-hidden">renaming {props.name}</span>
|
||||
</button>
|
||||
<button type="submit" className="btn btn__primary todo-edit">
|
||||
Save
|
||||
<span className="visually-hidden">new name for {props.name}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
const viewTemplate = (
|
||||
<div className="stack-small">
|
||||
<div className="c-cb">
|
||||
<input
|
||||
id={props.id}
|
||||
type="checkbox"
|
||||
defaultChecked={props.completed}
|
||||
onChange={() => props.toggleTaskCompleted(props.id)}
|
||||
/>
|
||||
<label className="todo-label" htmlFor={props.id}>
|
||||
{props.name}
|
||||
</label>
|
||||
</div>
|
||||
<div className="btn-group">
|
||||
<button
|
||||
type="button"
|
||||
className="btn"
|
||||
onClick={() => setEditing(true)}
|
||||
ref={editButtonRef}
|
||||
>
|
||||
Edit <span className="visually-hidden">{props.name}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn__danger"
|
||||
onClick={() => props.deleteTask(props.id)}
|
||||
>
|
||||
Delete <span className="visually-hidden">{props.name}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!wasEditing && isEditing) {
|
||||
editFieldRef.current.focus();
|
||||
}
|
||||
if (wasEditing && !isEditing) {
|
||||
editButtonRef.current.focus();
|
||||
}
|
||||
}, [wasEditing, isEditing]);
|
||||
|
||||
|
||||
return <li className="todo">{isEditing ? editingTemplate : viewTemplate}</li>;
|
||||
}
|
||||
|
|
@ -1,293 +0,0 @@
|
|||
|
||||
/* RESETS */
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
*:focus {
|
||||
outline: 3px dashed #228bec;
|
||||
outline-offset: 0;
|
||||
}
|
||||
html {
|
||||
font: 62.5% / 1.15 sans-serif;
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
button {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
overflow: visible;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
line-height: normal;
|
||||
-webkit-font-smoothing: inherit;
|
||||
-moz-osx-font-smoothing: inherit;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
button::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
line-height: 1.15;
|
||||
margin: 0;
|
||||
}
|
||||
button,
|
||||
input {
|
||||
overflow: visible;
|
||||
}
|
||||
input[type="text"] {
|
||||
border-radius: 0;
|
||||
}
|
||||
body {
|
||||
width: 100%;
|
||||
max-width: 68rem;
|
||||
margin: 0 auto;
|
||||
font: 1.6rem/1.25 Arial, sans-serif;
|
||||
background-color: #f5f5f5;
|
||||
color: #4d4d4d;
|
||||
}
|
||||
@media screen and (min-width: 620px) {
|
||||
body {
|
||||
font-size: 1.9rem;
|
||||
line-height: 1.31579;
|
||||
}
|
||||
}
|
||||
/*END RESETS*/
|
||||
/* GLOBAL STYLES */
|
||||
.form-group > input[type="text"] {
|
||||
display: inline-block;
|
||||
margin-top: 0.4rem;
|
||||
}
|
||||
.btn {
|
||||
padding: 0.8rem 1rem 0.7rem;
|
||||
border: 0.2rem solid #4d4d4d;
|
||||
cursor: pointer;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
.btn.toggle-btn {
|
||||
border-width: 1px;
|
||||
border-color: #d3d3d3;
|
||||
}
|
||||
.btn.toggle-btn[aria-pressed="true"] {
|
||||
text-decoration: underline;
|
||||
border-color: #4d4d4d;
|
||||
}
|
||||
.btn__danger {
|
||||
color: #fff;
|
||||
background-color: #ca3c3c;
|
||||
border-color: #bd2130;
|
||||
}
|
||||
.btn__filter {
|
||||
border-color: lightgrey;
|
||||
}
|
||||
.btn__primary {
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
}
|
||||
.btn-group {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.btn-group > * {
|
||||
flex: 1 1 49%;
|
||||
}
|
||||
.btn-group > * + * {
|
||||
margin-left: 0.8rem;
|
||||
}
|
||||
.label-wrapper {
|
||||
margin: 0;
|
||||
flex: 0 0 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.visually-hidden {
|
||||
position: absolute !important;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
overflow: hidden;
|
||||
clip: rect(1px 1px 1px 1px);
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
white-space: nowrap;
|
||||
}
|
||||
[class*="stack"] > * {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.stack-small > * + * {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
.stack-large > * + * {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
@media screen and (min-width: 550px) {
|
||||
.stack-small > * + * {
|
||||
margin-top: 1.4rem;
|
||||
}
|
||||
.stack-large > * + * {
|
||||
margin-top: 2.8rem;
|
||||
}
|
||||
}
|
||||
.stack-exception {
|
||||
margin-top: 1.2rem;
|
||||
}
|
||||
/* END GLOBAL STYLES */
|
||||
.todoapp {
|
||||
background: #fff;
|
||||
margin: 2rem 0 4rem 0;
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 2.5rem 5rem 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@media screen and (min-width: 550px) {
|
||||
.todoapp {
|
||||
padding: 4rem;
|
||||
}
|
||||
}
|
||||
.todoapp > * {
|
||||
max-width: 50rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.todoapp > form {
|
||||
max-width: 100%;
|
||||
}
|
||||
.todoapp > h1 {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.label__lg {
|
||||
line-height: 1.01567;
|
||||
font-weight: 300;
|
||||
padding: 0.8rem;
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
.input__lg {
|
||||
padding: 2rem;
|
||||
border: 2px solid #000;
|
||||
}
|
||||
.input__lg:focus {
|
||||
border-color: #4d4d4d;
|
||||
box-shadow: inset 0 0 0 2px;
|
||||
}
|
||||
[class*="__lg"] {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
font-size: 1.9rem;
|
||||
}
|
||||
[class*="__lg"]:not(:last-child) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@media screen and (min-width: 620px) {
|
||||
[class*="__lg"] {
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
}
|
||||
.filters {
|
||||
width: 100%;
|
||||
margin: unset auto;
|
||||
}
|
||||
/* Todo item styles */
|
||||
.todo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.todo > * {
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
.todo-text {
|
||||
width: 100%;
|
||||
min-height: 4.4rem;
|
||||
padding: 0.4rem 0.8rem;
|
||||
border: 2px solid #565656;
|
||||
}
|
||||
.todo-text:focus {
|
||||
box-shadow: inset 0 0 0 2px;
|
||||
}
|
||||
/* CHECKBOX STYLES */
|
||||
.c-cb {
|
||||
box-sizing: border-box;
|
||||
font-family: Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-weight: 400;
|
||||
font-size: 1.6rem;
|
||||
line-height: 1.25;
|
||||
display: block;
|
||||
position: relative;
|
||||
min-height: 44px;
|
||||
padding-left: 40px;
|
||||
clear: left;
|
||||
}
|
||||
.c-cb > label::before,
|
||||
.c-cb > input[type="checkbox"] {
|
||||
box-sizing: border-box;
|
||||
top: -2px;
|
||||
left: -2px;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.c-cb > input[type="checkbox"] {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
.c-cb > label {
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
line-height: inherit;
|
||||
display: inline-block;
|
||||
margin-bottom: 0;
|
||||
padding: 8px 15px 5px;
|
||||
cursor: pointer;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
.c-cb > label::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border: 2px solid currentColor;
|
||||
background: transparent;
|
||||
}
|
||||
.c-cb > input[type="checkbox"]:focus + label::before {
|
||||
border-width: 4px;
|
||||
outline: 3px dashed #228bec;
|
||||
}
|
||||
.c-cb > label::after {
|
||||
box-sizing: content-box;
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
left: 9px;
|
||||
width: 18px;
|
||||
height: 7px;
|
||||
transform: rotate(-45deg);
|
||||
border: solid;
|
||||
border-width: 0 0 5px 5px;
|
||||
border-top-color: transparent;
|
||||
opacity: 0;
|
||||
background: transparent;
|
||||
}
|
||||
.c-cb > input[type="checkbox"]:checked + label::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
|
||||
const DATA = [
|
||||
{ id: "todo-0", name: "Eat", completed: true },
|
||||
{ id: "todo-1", name: "Sleep", completed: false },
|
||||
{ id: "todo-2", name: "Repeat", completed: false }
|
||||
];
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App tasks={DATA} />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +0,0 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
)
|
||||
|
||||
#Pull: dagger.#GitPull
|
||||
#Push: dagger.#GitPush
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
package go
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
// Build a go binary
|
||||
#Build: {
|
||||
// Source code
|
||||
source: dagger.#FS
|
||||
|
||||
// Target package to build
|
||||
package: *"." | string
|
||||
|
||||
// Target architecture
|
||||
arch: *"amd64" | string
|
||||
|
||||
// Target OS
|
||||
os: *"linux" | string
|
||||
|
||||
// Build tags to use for building
|
||||
tags: *"" | string
|
||||
|
||||
// LDFLAGS to use for linking
|
||||
ldflags: *"" | string
|
||||
|
||||
env: [string]: string
|
||||
|
||||
container: #Container & {
|
||||
"source": source
|
||||
"env": {
|
||||
env
|
||||
GOOS: os
|
||||
GOARCH: arch
|
||||
}
|
||||
command: {
|
||||
args: [package]
|
||||
flags: {
|
||||
build: true
|
||||
"-v": true
|
||||
"-tags": tags
|
||||
"-ldflags": ldflags
|
||||
"-o": "/output/"
|
||||
}
|
||||
}
|
||||
export: directories: "/output": _
|
||||
}
|
||||
|
||||
// Directory containing the output of the build
|
||||
output: container.export.directories."/output"
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Go operation
|
||||
package go
|
||||
|
||||
import (
|
||||
"dagger.io/dagger"
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
// A standalone go environment to run go command
|
||||
#Container: {
|
||||
// Container app name
|
||||
name: *"go_builder" | string
|
||||
|
||||
// Source code
|
||||
source: dagger.#FS
|
||||
|
||||
// Use go image
|
||||
_image: #Image
|
||||
|
||||
_sourcePath: "/src"
|
||||
_cachePath: "/root/.cache/gocache"
|
||||
|
||||
docker.#Run & {
|
||||
input: *_image.output | docker.#Image
|
||||
workdir: "/src"
|
||||
command: name: "go"
|
||||
mounts: {
|
||||
"source": {
|
||||
dest: _sourcePath
|
||||
contents: source
|
||||
}
|
||||
"go assets cache": {
|
||||
contents: dagger.#CacheDir & {
|
||||
id: "\(name)_assets"
|
||||
}
|
||||
dest: _cachePath
|
||||
}
|
||||
}
|
||||
env: GOMODCACHE: _cachePath
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
package go
|
||||
|
||||
import (
|
||||
"universe.dagger.io/docker"
|
||||
)
|
||||
|
||||
// Go image default version
|
||||
#DefaultVersion: "1.16"
|
||||
|
||||
// Build a go base image
|
||||
#Image: {
|
||||
version: *#DefaultVersion | string
|
||||
|
||||
packages: [pkgName=string]: version: string | *""
|
||||
|
||||
// FIXME Basically a copy of alpine.#Build with a different image
|
||||
// Should we create a special definition?
|
||||
docker.#Build & {
|
||||
steps: [
|
||||
docker.#Pull & {
|
||||
source: "index.docker.io/golang:\(version)-alpine"
|
||||
},
|
||||
for pkgName, pkg in packages {
|
||||
docker.#Run & {
|
||||
command: {
|
||||
name: "apk"
|
||||
args: ["add", "\(pkgName)\(pkg.version)"]
|
||||
flags: {
|
||||
"-U": true
|
||||
"--no-cache": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package go
|
||||
|
||||
// Test a go package
|
||||
#Test: {
|
||||
// Package to test
|
||||
package: *"." | string
|
||||
|
||||
#Container & {
|
||||
command: {
|
||||
args: [package]
|
||||
flags: {
|
||||
test: true
|
||||
"-v": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue