I'm trying to make my first action to build packages inside a given docker container. I have the following action.yaml file:
name: Build Package
description: Build Debian packages using Docker image
inputs:
docker_image:
description: Name of the docker image to use
required: true
runs:
using: 'composite'
steps:
- name: Check out the repository
uses: actions/checkout#v2
- name: Build `*.deb` packages
uses: 'docker://${{inputs.docker_image}}'
with:
entrypoint: ./build.sh
In the other repository I'm trying to use it:
...
steps:
- uses: CMakeify-me/build-package-action#v1-beta
with:
docker_image: 'cmakeifyme/debian-9-deb-build:1.3'
Unfortunately, I've got the error:
Error: CMakeify-me/build-package-action/v1-beta/action.yaml (Line: 19, Col: 13):
Error: CMakeify-me/build-package-action/v1-beta/action.yaml (Line: 19, Col: 13): Unrecognized named-value: 'inputs'. Located at position 1 within expression: inputs.docker_image
Error: GitHub.DistributedTask.ObjectTemplating.TemplateValidationException: The template is not valid. CMakeify-me/build-package-action/v1-beta/action.yaml (Line: 19, Col: 13): Unrecognized named-value: 'inputs'. Located at position 1 within expression: inputs.docker_image
at GitHub.DistributedTask.ObjectTemplating.TemplateValidationErrors.Check()
at GitHub.Runner.Worker.ActionManifestManager.ConvertRuns(IExecutionContext executionContext, TemplateContext templateContext, TemplateToken inputsToken, String fileRelativePath, MappingToken outputs)
at GitHub.Runner.Worker.ActionManifestManager.Load(IExecutionContext executionContext, String manifestFile)
Error: Fail to load CMakeify-me/build-package-action/v1-beta/action.yaml
Trying just print the inputs works fine:
- name: Spam
run: echo '${{ inputs.docker_image }}'
shell: bash
Meaning, that there is some problem when inputs.docker_image is used within the value of uses: ;-(
How can I pass the docker image name to be used in my action?
Thank you.
I don't think you can't use an input/variable with uses like that.
This is not explicitly mentioned in the documentation but you can see a warning here: https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions
Warning: When creating workflows and actions, you should always consider whether your code might execute untrusted input from possible attackers.
If you need to dynamically pick your docker container, you might have to look into an alternative. You can avoid uses and run docker from shell directly, like this...
Call your action, and pass the input via with:
- uses: CMakeify-me/build-package-action#v1-beta
with:
docker_image: 'cmakeifyme/debian-9-deb-build:1.3'
Then your action can us the input via run, using shell to call docker:
- name: run docker with dynamic image name
run: 'docker run ${{ inputs.docker_image }}'
shell: bash
Related
I am currently working on a CI pipeline for a project and just started setting up a Github Action for running integration tests but I can't get it to work.
My action looks like this:
name: Integration Tests
on:
push:
branches:
- main
workflow_dispatch:
jobs:
integration-tests:
runs-on: ubuntu-latest
services:
selenium:
image: selenium/standalone-chrome:latest
ports:
- 4444:4444
options: --shm-size="2g"
steps:
- uses: actions/checkout#v2
- name: Get IP Address
run: echo "##[set-output name=ip;]$(ifconfig eth0 | grep 'inet [0-9\.]* ' -o | sed 's/[^0-9\.]//g')"
id: ip_addr
- name: Setup Pyhon
uses: actions/setup-python#v2
with:
python-version: '3.8'
- name: Install Python dependencies
uses: py-actions/py-dependency-install#v2
with: /path/to/requirements
- name: Run Tests
run: python3 main.py --backend http://localhost:8080/ --frontend http://${{ steps.ip_addr.outputs.ip }}:4200 --selenium http://localhost:4444/wd/hub
main.py starts two docker containers (that expose their corresponding ports) and runs a suite of selenium tests. It works on my local machine with a container I run using docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-chrome:latest. It takes the url for the backend and the one for the frontend, which gets used by selenium.
I think I have to use the IP address of the runner so selenium can access the site (since it runs locally, localhost doesn't work), but it fails with the following error:
File "main.py", line 57, in <module>
testcase.run()
File "/home/runner/work/PROJECT_NAME/QualityAssurance/integration_tests/test_cases/t1.py", line 14, in run
self.web_driver.accept_cookies()
File "/home/runner/work/PROJECT_NAME/QualityAssurance/integration_tests/test_utils/parkview_webdriver.py", line 64, in accept_cookies
self.wait_and_click(By.ID, 'confirmCookies')
File "/home/runner/work/PROJECT_NAME/QualityAssurance/integration_tests/test_utils/parkview_webdriver.py", line 30, in wait_and_click
WebDriverWait(self.driver, 10).until(
File "/opt/hostedtoolcache/Python/3.8.11/x64/lib/python3.8/site-packages/selenium/webdriver/support/wait.py", line 80, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
It seems to just not load the time, but I don't know to fix this. I guess it could also be that I messed up the networking somehow?
I think the service container is referenced by the service name instead of localhost. i.e. in your example:
--selenium http://localhost:4444/wd/hub
would be:
--selenium http://selenium:4444/wd/hub
as you defined it:
services:
selenium:
I have this drone.yml which is running fine and generating a docker image. I am building the docker image with 2 tags.
SHA of commit in GitHub.
latest
What I want to do is to append the date & time of image creation in the format of YYYY-MM-DD_HH-MM to the 1st tag (SHA of commit in GitHub).
---
name: api-graph-base
kind: pipeline
type: docker
steps:
- name: push-azure-nonprod
when:
event:
- push
- pull_request
branch:
- master
image: plugins/docker
settings:
username: abc
password:
from_secret: xyz
repo: nonprodazure/graph-base-api
build_args:
- LOG_LEVEL=debug
registry: nonprodregistry.azurecir.io
custom_dns: [100.100.100.100, 99.99.99.99]
tags:
- '${DRONE_BUILD_FINISHED}-${DRONE_COMMIT}'
- latest
dockerfile: Dockerfile
Image tags in drone build logs:
/usr/local/bin/docker tag c692df4346acada797d9541135f37124b15d1183 nonprodazure/graph-base-api:1600986079-c692df4346acada797d9541135f37124b15d1183
You can see in logs that the UNIX timestamp(1600986079) appended in the docker image tag name. How can I change the value of ${DRONE_BUILD_FINISHED} - Unix timestamp to DateTime human-readable string format (YYYY-MM-DD_HH-MM)?
This is what I needed to do to get date/time in a human-readable format and not UNIX format.
---
name: api-graph-base
kind: pipeline
type: docker
steps:
- name: send-tags-to-tags-file
image: node
when:
event:
- push
- pull_request
commands:
- echo -n "$(date +'%Y-%m-%d_%H-%M')_${DRONE_COMMIT}, latest" > .tags
- name: push-azure-nonprod
when:
event:
- push
branch:
- master
image: plugins/docker
settings:
username: abc
password:
from_secret: xyz
repo: nonprodazure/graph-base-api
build_args:
- LOG_LEVEL=debug
registry: nonprodregistry.azurecir.io
custom_dns: [100.100.100.100, 99.99.99.99]
dockerfile: Dockerfile
Below 2 tags created for the docker image. The second tag name contains the required date-time format now.
Solution:
Remove tags in the existing step.
Added a new step to generate tags in a .tags file.
If you need to share data between sibling processes (pipeline steps) you need to share this information by writing to and reading from disk. The docker plugin will automatically read tags from a .tags file. One cannot create an environment variable in one process and read that environment variable in a sibling process.
References:
using custom generated tags for docker images.
plugins/docker configuration multiple tags using .tags file
Coming from this issue
I am using GitHub Actions for Gradle project with this given steps:
name: Java CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v1
- name: Set up JDK 13
uses: actions/setup-java#v1
with:
java-version: 13
- run: ./gradlew bootJar
- name: Login to Github regestry
run: docker login docker.pkg.github.com -u xxxxx -p xxxxx
- name: Build the Docker image
run: docker build . -t docker.pkg.github.com/sulimanlab/realtime-chat/realtimechat-snapshot-0.$GITHUB_REF
- name: Push the image to github
run: docker push docker.pkg.github.com/sulimanlab/realtime-chat/realtimechat-snapshot-0.$GITHUB_REF
At the last step I get this error:
The push refers to repository
[docker.pkg.github.com/sulimanlab/realtime-chat/realtimechat-snapshot-0.refs/heads/master]
3aad04996f8f: Preparing
77cae8ab23bf: Preparing
error parsing HTTP 404 response body: invalid character 'p' after top-level value:
"404 page not found\n"
actually I was using the wrong environment variable to tag my images.
I used $GITHUB_REF what I should use $GITHUB_SHA
This question already has an answer here:
Ansible shows error: "One or more undefined variables: 'item' is undefined" when using 'with_items'
(1 answer)
Closed 4 years ago.
ansible version
ansible --version
ansible 2.5.5
docker version
docker --version
Docker version 18.03.1-ce, build 9ee9f40
my Examples
- name: start container
docker_container:
name: "tomcat-container"
image: "tomcat-images"
state: started
ports:
- "{{ item[0]}}:{{ item[1] }}"
with_nested:
- [8080,8080]
- [8081,8081]
FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to have been in '/home/playbook/roles/ts-docker/tasks/main.yml': line 81, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: start container\n ^ here\n"}
...'item' is undefined
How to solve the problem of mounting multiple port?
-_-|| English is not good, forgive me
You just need to reduce the indent of the with_nested line like this:
- name: start container
docker_container:
name: "tomcat-container"
image: "tomcat-images"
state: started
ports:
- "{{ item[0]}}:{{ item[1] }}"
with_nested:
- [8080,8080]
- [8081,8081]
with_nested is an option for the task and the way you had it indented it was an option for the module (docker_container).
Im working on a little Ansible project in which I'm using Docker Containers.
I'll keep my question short:
I want to get the state of a running Dockercontainer!
What I mean by that is, that i want to get the current state of the container, that Docker shows you by using the "docker ps" command.
Examples would be:
Up
Exited
Restarting
I want to get one of those results from a specific container. But without using the Command or the Shell module!
KR
As of Ansible 2.8 you can use the docker_container_info, which essentially returns the input from docker inspect <container>:
- name: Get infos on container
docker_container_info:
name: my_container
register: result
- name: Does container exist?
debug:
msg: "The container {{ 'exists' if result.exists else 'does not exist' }}"
- name: Print the status of the container
debug:
msg: "The container status is {{ result.container['State']['Status'] }}"
when: result.exists
With my Docker version, State contains this:
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 8235,
"ExitCode": 0,
"Error": "",
"StartedAt": "2019-01-25T14:10:08.3206714Z",
"FinishedAt": "0001-01-01T00:00:00Z"
}
See https://docs.ansible.com/ansible/2.8/modules/docker_container_info_module.html for more details.
Unfortunately, none of the modules around docker can currently "List containers".
I did the following as work around to grab the status:
- name: get container status
shell: docker ps -a -f name={{ container }} --format {%raw%}"table {{.Status}}"{%endraw%} | awk 'FNR == 2 {print}' | awk '{print $1}'
register: status
Result will then be available in the status variable
This worked for me:
- name: Get container status
shell: docker inspect --format={{ '{{.State.Running}}' }} {{ container_name }}
register: status
#Start the container if it is not running
- name: Start the container if it is in stopeed state.
shell: docker start heuristic_mestorf
when: status.stdout != "true"
Edit: If you are running Ansible 2.8+ you can use docker_container_info. See David Pärsson's answer for details.
Here is one way to craft it using the docker_container module (note that it will create the container if it does not exist):
- name: "Check if container is running"
docker_container:
name: "{{ container_name }}"
state: present
register: container_test_started
ignore_errors: yes
- set_fact:
container_exists: "{{ container_test_started.ansible_facts is defined }}"
- set_fact:
container_is_running: "{{ container_test_started.ansible_facts is defined and container_test_started.ansible_facts.docker_container.State.Status == 'running' }}"
container_is_paused: "{{ container_test_started.ansible_facts is defined and container_test_started.ansible_facts.docker_container.State.Status == 'paused' }}"
For me the gotchya was that if the container doesn't exist, ansible_facts is not defined. If it does though, then that contains basically the whole docker inspect <container> output so I navigate that for the status.
If you just need to short circuit, a simpler alternative would be to move the desired set_fact'd value into a failed_when on the docker_container task.
I do it through set_fact to keep my options open for forking behavior elsewhere.. e.g. stop, do task, then put back how it was.
I included pause because it is commonly forgotten as a state :)
There is an ansible module docker_image_facts which give you information about images. You are looking for something that would be docker_container_facts, which does not currently exist. Good idea though.
The question is not clear, but generally speaking you can use ansible with docker in two cases:
by using docker module of ansible
http://docs.ansible.com/ansible/latest/docker_module.html
- name: data container
docker:
name: mydata
image: busybox
state: present
volumes:
- /data
by calling ansible inside Dockerfile
FROM centos7
RUN ansible-playbook -i inventory playbook.yml
Your question is slightly unclear.
My best try - you want to have output of 'docker ps' - the first thing comes in mind is to use the Ansible command module, but you don't want to use it.
Then there are few docker modules:
docker - This is the original Ansible module for managing the Docker container life cycle.
docker_container - ansible module to manage the life cycle of docker containers.
You can look into the options -> parameters to get what exactly you're looking for.
Here's the complete list of Ansible modules for managing/using Docker.